<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexey Melezhik</title>
    <description>The latest articles on DEV Community by Alexey Melezhik (@melezhik).</description>
    <link>https://dev.to/melezhik</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F36281%2F1de54bc5-85b1-4537-8ae5-11e2d484c529.jpeg</url>
      <title>DEV Community: Alexey Melezhik</title>
      <link>https://dev.to/melezhik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/melezhik"/>
    <language>en</language>
    <item>
      <title>Linux compliance checks with Sparrow plugin</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Thu, 09 Jul 2026 09:33:34 +0000</pubDate>
      <link>https://dev.to/melezhik/linux-compliance-checks-with-sparrow-plugin-2160</link>
      <guid>https://dev.to/melezhik/linux-compliance-checks-with-sparrow-plugin-2160</guid>
      <description>&lt;p&gt;&lt;a href="https://sparrowhub.io" rel="noopener noreferrer"&gt;Sparrow&lt;/a&gt; is Raku automation framework comes with useful plugins people can use to automate infrastructure. Scc plugin allows to check Linux essential configuration files for security compliance. &lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;p&gt;Plugin latest version&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sparrowhub.io/plugin/scc/0.000023" rel="noopener noreferrer"&gt;https://sparrowhub.io/plugin/scc/0.000023&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Supported checks&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sshd&lt;/li&gt;
&lt;li&gt;redis&lt;/li&gt;
&lt;li&gt;sudoers&lt;/li&gt;
&lt;li&gt;bind&lt;/li&gt;
&lt;li&gt;sysctl&lt;/li&gt;
&lt;li&gt;fstab&lt;/li&gt;
&lt;li&gt;ifconfig&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here some example reports&lt;/p&gt;

&lt;h2&gt;
  
  
  Sysctl
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sysctl &lt;span class="nt"&gt;-a&lt;/span&gt;  | s6 &lt;span class="nt"&gt;--plg-run&lt;/span&gt; scc@check&lt;span class="o"&gt;=&lt;/span&gt;sysctl
&lt;span class="go"&gt;12:24:07 :: [task] - run plg scc@check=sysctl
12:24:07 :: [task] - run [scc], thing: scc@check=sysctl
[task run: task.bash - scc]
[task stdout]
12:24:08 :: abi.cp15_barrier = 1
12:24:08 :: abi.setend = 1
12:24:08 :: abi.swp = 0
12:24:08 :: abi.tagged_addr_disabled = 0
12:24:08 :: debug.exception-trace = 0
12:24:08 :: dev.cdrom.autoclose = 1
12:24:08 :: dev.cdrom.autoeject = 0
12:24:08 :: dev.cdrom.check_media = 0
12:24:08 :: dev.cdrom.debug = 0
12:24:08 :: dev.cdrom.info = CD-ROM information, Id: cdrom.c 3.20 2003/12/17
12:24:08 :: dev.cdrom.info = 
12:24:08 :: dev.cdrom.info = drive name:    
12:24:08 :: dev.cdrom.info = drive speed:   
&lt;/span&gt;&lt;span class="gp"&gt;12:24:08 :: dev.cdrom.info = drive #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;of slots:
&lt;span class="go"&gt;12:24:08 :: dev.cdrom.info = Can close tray:    
12:24:08 :: dev.cdrom.info = Can open tray: 
12:24:08 :: dev.cdrom.info = Can lock tray: 
12:24:08 :: dev.cdrom.info = Can change speed:
12:24:08 :: dev.cdrom.info = Can select disk:
12:24:08 :: dev.cdrom.info = Can read multisession:
12:24:08 :: dev.cdrom.info = Can read MCN:  
12:24:08 :: dev.cdrom.info = Reports media changed:
12:24:08 :: dev.cdrom.info = Can play audio:    
12:24:08 :: dev.cdrom.info = Can write CD-R:    
12:24:08 :: dev.cdrom.info = Can write CD-RW:
12:24:08 :: dev.cdrom.info = Can read DVD:  
12:24:08 :: dev.cdrom.info = Can write DVD-R:
12:24:08 :: dev.cdrom.info = Can write DVD-RAM:
12:24:08 :: dev.cdrom.info = Can read MRW:  
12:24:08 :: dev.cdrom.info = Can write MRW: 
12:24:08 :: dev.cdrom.info = Can write RAM: 
12:24:08 :: dev.cdrom.info = 
12:24:08 :: dev.cdrom.info = 
12:24:08 :: dev.cdrom.lock = 0
12:24:08 :: dev.raid.speed_limit_max = 200000
12:24:08 :: dev.raid.speed_limit_min = 1000
12:24:08 :: dev.scsi.logging_level = 68
12:24:08 :: dev.tty.ldisc_autoload = 1
12:24:08 :: dev.tty.legacy_tiocsti = 0
12:24:08 :: fs.aio-max-nr = 65536
12:24:08 :: fs.aio-nr = 0
12:24:08 :: fs.binfmt_misc.llvm-14-runtime/binfmt = enabled
12:24:08 :: fs.binfmt_misc.llvm-14-runtime/binfmt = interpreter /usr/bin/lli-14
12:24:08 :: fs.binfmt_misc.llvm-14-runtime/binfmt = flags: 
12:24:08 :: fs.binfmt_misc.llvm-14-runtime/binfmt = offset 0
12:24:08 :: fs.binfmt_misc.llvm-14-runtime/binfmt = magic 4243
12:24:08 :: fs.binfmt_misc.python3/10 = enabled
12:24:08 :: fs.binfmt_misc.python3/10 = interpreter /usr/bin/python3.10
12:24:08 :: fs.binfmt_misc.python3/10 = flags: 
12:24:08 :: fs.binfmt_misc.python3/10 = offset 0
12:24:08 :: fs.binfmt_misc.python3/10 = magic 6f0d0d0a
12:24:08 :: fs.binfmt_misc.status = enabled
12:24:08 :: fs.dentry-state = 409950    398351  45  0   243512  0
12:24:08 :: fs.dir-notify-enable = 1
12:24:08 :: fs.epoll.max_user_watches = 5456495
12:24:08 :: fs.fanotify.max_queued_events = 16384
12:24:08 :: fs.fanotify.max_user_groups = 128
12:24:08 :: fs.fanotify.max_user_marks = 198574
12:24:08 :: fs.file-max = 9223372036854775807
12:24:08 :: fs.file-nr = 3520   0   9223372036854775807
12:24:08 :: fs.inode-nr = 166357    412
12:24:08 :: fs.inode-state = 166357 412 0   0   0   0   0
12:24:08 :: fs.inotify.max_queued_events = 16384
12:24:08 :: fs.inotify.max_user_instances = 128
12:24:08 :: fs.inotify.max_user_watches = 186755
12:24:08 :: fs.lease-break-time = 45
12:24:08 :: fs.leases-enable = 1
12:24:08 :: fs.mount-max = 100000
12:24:08 :: fs.mqueue.msg_default = 10
12:24:08 :: fs.mqueue.msg_max = 10
12:24:08 :: fs.mqueue.msgsize_default = 8192
12:24:08 :: fs.mqueue.msgsize_max = 8192
12:24:08 :: fs.mqueue.queues_max = 256
12:24:08 :: fs.nr_open = 1048576
12:24:08 :: fs.overflowgid = 65534
12:24:08 :: fs.overflowuid = 65534
12:24:08 :: fs.pipe-max-size = 1048576
12:24:08 :: fs.pipe-user-pages-hard = 0
12:24:08 :: fs.pipe-user-pages-soft = 16384
12:24:08 :: fs.protected_fifos = 1
12:24:08 :: fs.protected_hardlinks = 1
12:24:08 :: fs.protected_regular = 2
12:24:08 :: fs.protected_symlinks = 1
12:24:08 :: fs.quota.allocated_dquots = 0
12:24:08 :: fs.quota.cache_hits = 0
12:24:08 :: fs.quota.drops = 0
12:24:08 :: fs.quota.free_dquots = 0
12:24:08 :: fs.quota.lookups = 0
12:24:08 :: fs.quota.reads = 0
12:24:08 :: fs.quota.syncs = 320
12:24:08 :: fs.quota.writes = 0
12:24:08 :: fs.suid_dumpable = 2
12:24:08 :: fs.verity.require_signatures = 0
12:24:08 :: kernel.acct = 4 2   30
12:24:08 :: kernel.apparmor_display_secid_mode = 0
12:24:08 :: kernel.apparmor_restrict_unprivileged_io_uring = 0
12:24:08 :: kernel.apparmor_restrict_unprivileged_unconfined = 0
12:24:08 :: kernel.apparmor_restrict_unprivileged_userns = 0
12:24:08 :: kernel.apparmor_restrict_unprivileged_userns_complain = 0
12:24:08 :: kernel.apparmor_restrict_unprivileged_userns_force = 0
12:24:08 :: kernel.arch = aarch64
12:24:08 :: kernel.auto_msgmni = 0
12:24:08 :: kernel.bpf_stats_enabled = 0
12:24:08 :: kernel.cad_pid = 1
12:24:08 :: kernel.cap_last_cap = 40
12:24:08 :: kernel.core_pattern = |/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -F%F -- %E
12:24:08 :: kernel.core_pipe_limit = 10
12:24:08 :: kernel.core_uses_pid = 1
12:24:08 :: kernel.ctrl-alt-del = 0
12:24:08 :: kernel.dmesg_restrict = 1
12:24:08 :: kernel.domainname = (none)
12:24:08 :: kernel.firmware_config.force_sysfs_fallback = 0
12:24:08 :: kernel.firmware_config.ignore_sysfs_fallback = 0
12:24:08 :: kernel.ftrace_dump_on_oops = 0
12:24:08 :: kernel.ftrace_enabled = 1
12:24:08 :: kernel.hardlockup_all_cpu_backtrace = 0
12:24:08 :: kernel.hardlockup_panic = 0
12:24:08 :: kernel.hostname = sparky02b
12:24:08 :: kernel.hotplug = 
12:24:08 :: kernel.hung_task_all_cpu_backtrace = 0
12:24:08 :: kernel.hung_task_check_count = 4194304
12:24:08 :: kernel.hung_task_check_interval_secs = 0
12:24:08 :: kernel.hung_task_panic = 0
12:24:08 :: kernel.hung_task_timeout_secs = 120
12:24:08 :: kernel.hung_task_warnings = 10
12:24:08 :: kernel.io_uring_disabled = 0
12:24:08 :: kernel.io_uring_group = -1
12:24:08 :: kernel.kexec_load_disabled = 0
12:24:08 :: kernel.kexec_load_limit_panic = -1
12:24:08 :: kernel.kexec_load_limit_reboot = -1
12:24:08 :: kernel.keys.gc_delay = 300
12:24:08 :: kernel.keys.maxbytes = 20000
12:24:08 :: kernel.keys.maxkeys = 200
12:24:08 :: kernel.keys.persistent_keyring_expiry = 259200
12:24:08 :: kernel.keys.root_maxbytes = 25000000
12:24:08 :: kernel.keys.root_maxkeys = 1000000
12:24:08 :: kernel.kptr_restrict = 1
12:24:08 :: kernel.latencytop = 0
12:24:08 :: kernel.max_lock_depth = 1024
12:24:08 :: kernel.max_rcu_stall_to_panic = 0
12:24:08 :: kernel.modprobe = /sbin/modprobe
12:24:08 :: kernel.modules_disabled = 0
12:24:08 :: kernel.msg_next_id = -1
12:24:08 :: kernel.msgmax = 8192
12:24:08 :: kernel.msgmnb = 16384
12:24:08 :: kernel.msgmni = 32000
12:24:08 :: kernel.ngroups_max = 65536
12:24:08 :: kernel.nmi_watchdog = 0
12:24:08 :: kernel.ns_last_pid = 856760
12:24:08 :: kernel.numa_balancing = 0
12:24:08 :: kernel.numa_balancing_promote_rate_limit_MBps = 65536
12:24:08 :: kernel.oops_all_cpu_backtrace = 0
12:24:08 :: kernel.oops_limit = 10000
12:24:08 :: kernel.osrelease = 6.8.0-1050-oracle
12:24:08 :: kernel.ostype = Linux
12:24:08 :: kernel.overflowgid = 65534
12:24:08 :: kernel.overflowuid = 65534
12:24:08 :: kernel.panic = 0
12:24:08 :: kernel.panic_on_oops = 0
12:24:08 :: kernel.panic_on_rcu_stall = 0
12:24:08 :: kernel.panic_on_warn = 0
12:24:08 :: kernel.panic_print = 0
12:24:08 :: kernel.perf_cpu_time_max_percent = 25
12:24:08 :: kernel.perf_event_max_contexts_per_stack = 8
12:24:08 :: kernel.perf_event_max_sample_rate = 100000
12:24:08 :: kernel.perf_event_max_stack = 127
12:24:08 :: kernel.perf_event_mlock_kb = 516
12:24:08 :: kernel.perf_event_paranoid = 4
12:24:08 :: kernel.perf_user_access = 0
12:24:08 :: kernel.pid_max = 4194304
12:24:08 :: kernel.poweroff_cmd = /sbin/poweroff
12:24:08 :: kernel.print-fatal-signals = 0
12:24:08 :: kernel.printk = 4   4   1   7
12:24:08 :: kernel.printk_delay = 0
12:24:08 :: kernel.printk_devkmsg = on
12:24:08 :: kernel.printk_ratelimit = 5
12:24:08 :: kernel.printk_ratelimit_burst = 10
12:24:08 :: kernel.pty.max = 4096
12:24:08 :: kernel.pty.nr = 4
12:24:08 :: kernel.pty.reserve = 1024
12:24:08 :: kernel.random.boot_id = 03560fb6-eb3e-4cc2-a12c-1604610ee88a
12:24:08 :: kernel.random.entropy_avail = 256
12:24:08 :: kernel.random.poolsize = 256
12:24:08 :: kernel.random.urandom_min_reseed_secs = 60
12:24:08 :: kernel.random.uuid = bf318e69-c00e-4483-965d-eb1674fadf71
12:24:08 :: kernel.random.write_wakeup_threshold = 256
12:24:08 :: kernel.randomize_va_space = 2
12:24:08 :: kernel.real-root-dev = 0
12:24:08 :: kernel.sched_autogroup_enabled = 1
12:24:08 :: kernel.sched_cfs_bandwidth_slice_us = 5000
12:24:08 :: kernel.sched_deadline_period_max_us = 4194304
12:24:08 :: kernel.sched_deadline_period_min_us = 100
12:24:08 :: kernel.sched_rr_timeslice_ms = 100
12:24:08 :: kernel.sched_rt_period_us = 1000000
12:24:08 :: kernel.sched_rt_runtime_us = 950000
12:24:08 :: kernel.sched_schedstats = 0
12:24:08 :: kernel.sched_util_clamp_max = 1024
12:24:08 :: kernel.sched_util_clamp_min = 1024
12:24:08 :: kernel.sched_util_clamp_min_rt_default = 1024
12:24:08 :: kernel.seccomp.actions_avail = kill_process kill_thread trap errno user_notif trace log allow
12:24:08 :: kernel.seccomp.actions_logged = kill_process kill_thread trap errno user_notif trace log
12:24:08 :: kernel.sem = 32000  1024000000  500 32000
12:24:08 :: kernel.sem_next_id = -1
12:24:08 :: kernel.shm_next_id = -1
12:24:08 :: kernel.shm_rmid_forced = 0
12:24:08 :: kernel.shmall = 18446744073692774399
12:24:08 :: kernel.shmmax = 18446744073692774399
12:24:08 :: kernel.shmmni = 4096
12:24:08 :: kernel.soft_watchdog = 1
12:24:08 :: kernel.softlockup_all_cpu_backtrace = 0
12:24:08 :: kernel.softlockup_panic = 0
12:24:08 :: kernel.stack_tracer_enabled = 0
12:24:08 :: kernel.sysctl_writes_strict = 1
12:24:08 :: kernel.sysrq = 176
12:24:08 :: kernel.tainted = 0
12:24:08 :: kernel.task_delayacct = 0
12:24:08 :: kernel.threads-max = 191241
12:24:08 :: kernel.timer_migration = 1
12:24:08 :: kernel.traceoff_on_warning = 0
12:24:08 :: kernel.tracepoint_printk = 0
12:24:08 :: kernel.unprivileged_bpf_disabled = 2
12:24:08 :: kernel.unprivileged_userns_apparmor_policy = 1
12:24:08 :: kernel.unprivileged_userns_clone = 1
12:24:08 :: kernel.user_events_max = 32768
12:24:08 :: kernel.usermodehelper.bset = 4294967295 511
12:24:08 :: kernel.usermodehelper.inheritable = 4294967295  511
&lt;/span&gt;&lt;span class="gp"&gt;12:24:08 :: kernel.version = #&lt;/span&gt;51~22.04.1-Ubuntu SMP Tue Apr 21 04:35:38 UTC 2026
&lt;span class="go"&gt;12:24:08 :: kernel.warn_limit = 0
12:24:08 :: kernel.watchdog = 1
12:24:08 :: kernel.watchdog_cpumask = 0-3
12:24:08 :: kernel.watchdog_thresh = 10
12:24:08 :: kernel.yama.ptrace_scope = 1
12:24:08 :: net.bridge.bridge-nf-call-arptables = 1
12:24:08 :: net.bridge.bridge-nf-call-ip6tables = 1
12:24:08 :: net.bridge.bridge-nf-call-iptables = 1
12:24:08 :: net.bridge.bridge-nf-filter-pppoe-tagged = 0
12:24:08 :: net.bridge.bridge-nf-filter-vlan-tagged = 0
12:24:08 :: net.bridge.bridge-nf-pass-vlan-input-dev = 0
12:24:08 :: net.core.bpf_jit_enable = 1
12:24:08 :: net.core.bpf_jit_harden = 0
12:24:08 :: net.core.bpf_jit_kallsyms = 1
12:24:08 :: net.core.bpf_jit_limit = 68168512962560
12:24:08 :: net.core.busy_poll = 0
12:24:08 :: net.core.busy_read = 0
12:24:08 :: net.core.default_qdisc = fq_codel
12:24:08 :: net.core.dev_weight = 64
12:24:08 :: net.core.dev_weight_rx_bias = 1
12:24:08 :: net.core.dev_weight_tx_bias = 1
12:24:08 :: net.core.devconf_inherit_init_net = 0
12:24:08 :: net.core.fb_tunnels_only_for_init_net = 0
12:24:08 :: net.core.flow_limit_cpu_bitmap = 0
12:24:08 :: net.core.flow_limit_table_len = 4096
12:24:08 :: net.core.gro_normal_batch = 8
12:24:08 :: net.core.high_order_alloc_disable = 0
12:24:08 :: net.core.max_skb_frags = 17
12:24:08 :: net.core.mem_pcpu_rsv = 256
12:24:08 :: net.core.message_burst = 10
12:24:08 :: net.core.message_cost = 5
12:24:08 :: net.core.netdev_budget = 300
12:24:08 :: net.core.netdev_budget_usecs = 2000
12:24:08 :: net.core.netdev_max_backlog = 1000
12:24:08 :: net.core.netdev_rss_key = 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
12:24:08 :: net.core.netdev_tstamp_prequeue = 1
12:24:08 :: net.core.netdev_unregister_timeout_secs = 10
12:24:08 :: net.core.optmem_max = 131072
12:24:08 :: net.core.rmem_default = 212992
12:24:08 :: net.core.rmem_max = 212992
12:24:08 :: net.core.rps_default_mask = 0
12:24:08 :: net.core.rps_sock_flow_entries = 0
12:24:08 :: net.core.skb_defer_max = 64
12:24:08 :: net.core.somaxconn = 4096
12:24:08 :: net.core.tstamp_allow_data = 1
12:24:08 :: net.core.txrehash = 1
12:24:08 :: net.core.warnings = 0
12:24:08 :: net.core.wmem_default = 212992
12:24:08 :: net.core.wmem_max = 212992
12:24:08 :: net.core.xfrm_acq_expires = 30
12:24:08 :: net.core.xfrm_aevent_etime = 10
12:24:08 :: net.core.xfrm_aevent_rseqth = 2
12:24:08 :: net.core.xfrm_larval_drop = 1
12:24:08 :: net.ipv4.cipso_cache_bucket_size = 10
12:24:08 :: net.ipv4.cipso_cache_enable = 1
12:24:08 :: net.ipv4.cipso_rbm_optfmt = 0
12:24:08 :: net.ipv4.cipso_rbm_strictvalid = 1
12:24:08 :: net.ipv4.conf.all.accept_local = 0
12:24:08 :: net.ipv4.conf.all.accept_redirects = 0
12:24:08 :: net.ipv4.conf.all.accept_source_route = 0
12:24:08 :: net.ipv4.conf.all.arp_accept = 0
12:24:08 :: net.ipv4.conf.all.arp_announce = 0
12:24:08 :: net.ipv4.conf.all.arp_evict_nocarrier = 1
12:24:08 :: net.ipv4.conf.all.arp_filter = 0
12:24:08 :: net.ipv4.conf.all.arp_ignore = 0
12:24:08 :: net.ipv4.conf.all.arp_notify = 0
12:24:08 :: net.ipv4.conf.all.bc_forwarding = 0
12:24:08 :: net.ipv4.conf.all.bootp_relay = 0
12:24:08 :: net.ipv4.conf.all.disable_policy = 0
12:24:08 :: net.ipv4.conf.all.disable_xfrm = 0
12:24:08 :: net.ipv4.conf.all.drop_gratuitous_arp = 0
12:24:08 :: net.ipv4.conf.all.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv4.conf.all.force_igmp_version = 0
12:24:08 :: net.ipv4.conf.all.forwarding = 1
12:24:08 :: net.ipv4.conf.all.igmpv2_unsolicited_report_interval = 10000
12:24:08 :: net.ipv4.conf.all.igmpv3_unsolicited_report_interval = 1000
12:24:08 :: net.ipv4.conf.all.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv4.conf.all.log_martians = 0
12:24:08 :: net.ipv4.conf.all.mc_forwarding = 0
12:24:08 :: net.ipv4.conf.all.medium_id = 0
12:24:08 :: net.ipv4.conf.all.promote_secondaries = 0
12:24:08 :: net.ipv4.conf.all.proxy_arp = 0
12:24:08 :: net.ipv4.conf.all.proxy_arp_pvlan = 0
12:24:08 :: net.ipv4.conf.all.route_localnet = 0
12:24:08 :: net.ipv4.conf.all.rp_filter = 2
12:24:08 :: net.ipv4.conf.all.secure_redirects = 1
12:24:08 :: net.ipv4.conf.all.send_redirects = 1
12:24:08 :: net.ipv4.conf.all.shared_media = 1
12:24:08 :: net.ipv4.conf.all.src_valid_mark = 0
12:24:08 :: net.ipv4.conf.all.tag = 0
12:24:08 :: net.ipv4.conf.default.accept_local = 0
12:24:08 :: net.ipv4.conf.default.accept_redirects = 1
12:24:08 :: net.ipv4.conf.default.accept_source_route = 0
12:24:08 :: net.ipv4.conf.default.arp_accept = 0
12:24:08 :: net.ipv4.conf.default.arp_announce = 0
12:24:08 :: net.ipv4.conf.default.arp_evict_nocarrier = 1
12:24:08 :: net.ipv4.conf.default.arp_filter = 0
12:24:08 :: net.ipv4.conf.default.arp_ignore = 0
12:24:08 :: net.ipv4.conf.default.arp_notify = 0
12:24:08 :: net.ipv4.conf.default.bc_forwarding = 0
12:24:08 :: net.ipv4.conf.default.bootp_relay = 0
12:24:08 :: net.ipv4.conf.default.disable_policy = 0
12:24:08 :: net.ipv4.conf.default.disable_xfrm = 0
12:24:08 :: net.ipv4.conf.default.drop_gratuitous_arp = 0
12:24:08 :: net.ipv4.conf.default.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv4.conf.default.force_igmp_version = 0
12:24:08 :: net.ipv4.conf.default.forwarding = 1
12:24:08 :: net.ipv4.conf.default.igmpv2_unsolicited_report_interval = 10000
12:24:08 :: net.ipv4.conf.default.igmpv3_unsolicited_report_interval = 1000
12:24:08 :: net.ipv4.conf.default.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv4.conf.default.log_martians = 0
12:24:08 :: net.ipv4.conf.default.mc_forwarding = 0
12:24:08 :: net.ipv4.conf.default.medium_id = 0
12:24:08 :: net.ipv4.conf.default.promote_secondaries = 1
12:24:08 :: net.ipv4.conf.default.proxy_arp = 0
12:24:08 :: net.ipv4.conf.default.proxy_arp_pvlan = 0
12:24:08 :: net.ipv4.conf.default.route_localnet = 0
12:24:08 :: net.ipv4.conf.default.rp_filter = 2
12:24:08 :: net.ipv4.conf.default.secure_redirects = 1
12:24:08 :: net.ipv4.conf.default.send_redirects = 1
12:24:08 :: net.ipv4.conf.default.shared_media = 1
12:24:08 :: net.ipv4.conf.default.src_valid_mark = 0
12:24:08 :: net.ipv4.conf.default.tag = 0
12:24:08 :: net.ipv4.conf.docker0.accept_local = 0
12:24:08 :: net.ipv4.conf.docker0.accept_redirects = 1
12:24:08 :: net.ipv4.conf.docker0.accept_source_route = 0
12:24:08 :: net.ipv4.conf.docker0.arp_accept = 0
12:24:08 :: net.ipv4.conf.docker0.arp_announce = 0
12:24:08 :: net.ipv4.conf.docker0.arp_evict_nocarrier = 1
12:24:08 :: net.ipv4.conf.docker0.arp_filter = 0
12:24:08 :: net.ipv4.conf.docker0.arp_ignore = 0
12:24:08 :: net.ipv4.conf.docker0.arp_notify = 0
12:24:08 :: net.ipv4.conf.docker0.bc_forwarding = 0
12:24:08 :: net.ipv4.conf.docker0.bootp_relay = 0
12:24:08 :: net.ipv4.conf.docker0.disable_policy = 0
12:24:08 :: net.ipv4.conf.docker0.disable_xfrm = 0
12:24:08 :: net.ipv4.conf.docker0.drop_gratuitous_arp = 0
12:24:08 :: net.ipv4.conf.docker0.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv4.conf.docker0.force_igmp_version = 0
12:24:08 :: net.ipv4.conf.docker0.forwarding = 1
12:24:08 :: net.ipv4.conf.docker0.igmpv2_unsolicited_report_interval = 10000
12:24:08 :: net.ipv4.conf.docker0.igmpv3_unsolicited_report_interval = 1000
12:24:08 :: net.ipv4.conf.docker0.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv4.conf.docker0.log_martians = 0
12:24:08 :: net.ipv4.conf.docker0.mc_forwarding = 0
12:24:08 :: net.ipv4.conf.docker0.medium_id = 0
12:24:08 :: net.ipv4.conf.docker0.promote_secondaries = 1
12:24:08 :: net.ipv4.conf.docker0.proxy_arp = 0
12:24:08 :: net.ipv4.conf.docker0.proxy_arp_pvlan = 0
12:24:08 :: net.ipv4.conf.docker0.route_localnet = 0
12:24:08 :: net.ipv4.conf.docker0.rp_filter = 2
12:24:08 :: net.ipv4.conf.docker0.secure_redirects = 1
12:24:08 :: net.ipv4.conf.docker0.send_redirects = 1
12:24:08 :: net.ipv4.conf.docker0.shared_media = 1
12:24:08 :: net.ipv4.conf.docker0.src_valid_mark = 0
12:24:08 :: net.ipv4.conf.docker0.tag = 0
12:24:08 :: net.ipv4.conf.enp0s3.accept_local = 0
12:24:08 :: net.ipv4.conf.enp0s3.accept_redirects = 1
12:24:08 :: net.ipv4.conf.enp0s3.accept_source_route = 0
12:24:08 :: net.ipv4.conf.enp0s3.arp_accept = 0
12:24:08 :: net.ipv4.conf.enp0s3.arp_announce = 0
12:24:08 :: net.ipv4.conf.enp0s3.arp_evict_nocarrier = 1
12:24:08 :: net.ipv4.conf.enp0s3.arp_filter = 0
12:24:08 :: net.ipv4.conf.enp0s3.arp_ignore = 0
12:24:08 :: net.ipv4.conf.enp0s3.arp_notify = 0
12:24:08 :: net.ipv4.conf.enp0s3.bc_forwarding = 0
12:24:08 :: net.ipv4.conf.enp0s3.bootp_relay = 0
12:24:08 :: net.ipv4.conf.enp0s3.disable_policy = 0
12:24:08 :: net.ipv4.conf.enp0s3.disable_xfrm = 0
12:24:08 :: net.ipv4.conf.enp0s3.drop_gratuitous_arp = 0
12:24:08 :: net.ipv4.conf.enp0s3.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv4.conf.enp0s3.force_igmp_version = 0
12:24:08 :: net.ipv4.conf.enp0s3.forwarding = 1
12:24:08 :: net.ipv4.conf.enp0s3.igmpv2_unsolicited_report_interval = 10000
12:24:08 :: net.ipv4.conf.enp0s3.igmpv3_unsolicited_report_interval = 1000
12:24:08 :: net.ipv4.conf.enp0s3.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv4.conf.enp0s3.log_martians = 0
12:24:08 :: net.ipv4.conf.enp0s3.mc_forwarding = 0
12:24:08 :: net.ipv4.conf.enp0s3.medium_id = 0
12:24:08 :: net.ipv4.conf.enp0s3.promote_secondaries = 1
12:24:08 :: net.ipv4.conf.enp0s3.proxy_arp = 0
12:24:08 :: net.ipv4.conf.enp0s3.proxy_arp_pvlan = 0
12:24:08 :: net.ipv4.conf.enp0s3.route_localnet = 0
12:24:08 :: net.ipv4.conf.enp0s3.rp_filter = 2
12:24:08 :: net.ipv4.conf.enp0s3.secure_redirects = 1
12:24:08 :: net.ipv4.conf.enp0s3.send_redirects = 1
12:24:08 :: net.ipv4.conf.enp0s3.shared_media = 1
12:24:08 :: net.ipv4.conf.enp0s3.src_valid_mark = 0
12:24:08 :: net.ipv4.conf.enp0s3.tag = 0
12:24:08 :: net.ipv4.conf.lo.accept_local = 0
12:24:08 :: net.ipv4.conf.lo.accept_redirects = 1
12:24:08 :: net.ipv4.conf.lo.accept_source_route = 0
12:24:08 :: net.ipv4.conf.lo.arp_accept = 0
12:24:08 :: net.ipv4.conf.lo.arp_announce = 0
12:24:08 :: net.ipv4.conf.lo.arp_evict_nocarrier = 1
12:24:08 :: net.ipv4.conf.lo.arp_filter = 0
12:24:08 :: net.ipv4.conf.lo.arp_ignore = 0
12:24:08 :: net.ipv4.conf.lo.arp_notify = 0
12:24:08 :: net.ipv4.conf.lo.bc_forwarding = 0
12:24:08 :: net.ipv4.conf.lo.bootp_relay = 0
12:24:08 :: net.ipv4.conf.lo.disable_policy = 1
12:24:08 :: net.ipv4.conf.lo.disable_xfrm = 1
12:24:08 :: net.ipv4.conf.lo.drop_gratuitous_arp = 0
12:24:08 :: net.ipv4.conf.lo.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv4.conf.lo.force_igmp_version = 0
12:24:08 :: net.ipv4.conf.lo.forwarding = 1
12:24:08 :: net.ipv4.conf.lo.igmpv2_unsolicited_report_interval = 10000
12:24:08 :: net.ipv4.conf.lo.igmpv3_unsolicited_report_interval = 1000
12:24:08 :: net.ipv4.conf.lo.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv4.conf.lo.log_martians = 0
12:24:08 :: net.ipv4.conf.lo.mc_forwarding = 0
12:24:08 :: net.ipv4.conf.lo.medium_id = 0
12:24:08 :: net.ipv4.conf.lo.promote_secondaries = 1
12:24:08 :: net.ipv4.conf.lo.proxy_arp = 0
12:24:08 :: net.ipv4.conf.lo.proxy_arp_pvlan = 0
12:24:08 :: net.ipv4.conf.lo.route_localnet = 0
12:24:08 :: net.ipv4.conf.lo.rp_filter = 2
12:24:08 :: net.ipv4.conf.lo.secure_redirects = 1
12:24:08 :: net.ipv4.conf.lo.send_redirects = 1
12:24:08 :: net.ipv4.conf.lo.shared_media = 1
12:24:08 :: net.ipv4.conf.lo.src_valid_mark = 0
12:24:08 :: net.ipv4.conf.lo.tag = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.accept_local = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.accept_redirects = 1
12:24:08 :: net.ipv4.conf.vethd9a62a1.accept_source_route = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.arp_accept = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.arp_announce = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.arp_evict_nocarrier = 1
12:24:08 :: net.ipv4.conf.vethd9a62a1.arp_filter = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.arp_ignore = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.arp_notify = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.bc_forwarding = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.bootp_relay = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.disable_policy = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.disable_xfrm = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.drop_gratuitous_arp = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.force_igmp_version = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.forwarding = 1
12:24:08 :: net.ipv4.conf.vethd9a62a1.igmpv2_unsolicited_report_interval = 10000
12:24:08 :: net.ipv4.conf.vethd9a62a1.igmpv3_unsolicited_report_interval = 1000
12:24:08 :: net.ipv4.conf.vethd9a62a1.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.log_martians = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.mc_forwarding = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.medium_id = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.promote_secondaries = 1
12:24:08 :: net.ipv4.conf.vethd9a62a1.proxy_arp = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.proxy_arp_pvlan = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.route_localnet = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.rp_filter = 2
12:24:08 :: net.ipv4.conf.vethd9a62a1.secure_redirects = 1
12:24:08 :: net.ipv4.conf.vethd9a62a1.send_redirects = 1
12:24:08 :: net.ipv4.conf.vethd9a62a1.shared_media = 1
12:24:08 :: net.ipv4.conf.vethd9a62a1.src_valid_mark = 0
12:24:08 :: net.ipv4.conf.vethd9a62a1.tag = 0
12:24:08 :: net.ipv4.conf.virbr0.accept_local = 0
12:24:08 :: net.ipv4.conf.virbr0.accept_redirects = 1
12:24:08 :: net.ipv4.conf.virbr0.accept_source_route = 0
12:24:08 :: net.ipv4.conf.virbr0.arp_accept = 0
12:24:08 :: net.ipv4.conf.virbr0.arp_announce = 0
12:24:08 :: net.ipv4.conf.virbr0.arp_evict_nocarrier = 1
12:24:08 :: net.ipv4.conf.virbr0.arp_filter = 0
12:24:08 :: net.ipv4.conf.virbr0.arp_ignore = 0
12:24:08 :: net.ipv4.conf.virbr0.arp_notify = 0
12:24:08 :: net.ipv4.conf.virbr0.bc_forwarding = 0
12:24:08 :: net.ipv4.conf.virbr0.bootp_relay = 0
12:24:08 :: net.ipv4.conf.virbr0.disable_policy = 0
12:24:08 :: net.ipv4.conf.virbr0.disable_xfrm = 0
12:24:08 :: net.ipv4.conf.virbr0.drop_gratuitous_arp = 0
12:24:08 :: net.ipv4.conf.virbr0.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv4.conf.virbr0.force_igmp_version = 0
12:24:08 :: net.ipv4.conf.virbr0.forwarding = 1
12:24:08 :: net.ipv4.conf.virbr0.igmpv2_unsolicited_report_interval = 10000
12:24:08 :: net.ipv4.conf.virbr0.igmpv3_unsolicited_report_interval = 1000
12:24:08 :: net.ipv4.conf.virbr0.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv4.conf.virbr0.log_martians = 0
12:24:08 :: net.ipv4.conf.virbr0.mc_forwarding = 0
12:24:08 :: net.ipv4.conf.virbr0.medium_id = 0
12:24:08 :: net.ipv4.conf.virbr0.promote_secondaries = 1
12:24:08 :: net.ipv4.conf.virbr0.proxy_arp = 0
12:24:08 :: net.ipv4.conf.virbr0.proxy_arp_pvlan = 0
12:24:08 :: net.ipv4.conf.virbr0.route_localnet = 0
12:24:08 :: net.ipv4.conf.virbr0.rp_filter = 2
12:24:08 :: net.ipv4.conf.virbr0.secure_redirects = 1
12:24:08 :: net.ipv4.conf.virbr0.send_redirects = 1
12:24:08 :: net.ipv4.conf.virbr0.shared_media = 1
12:24:08 :: net.ipv4.conf.virbr0.src_valid_mark = 0
12:24:08 :: net.ipv4.conf.virbr0.tag = 0
12:24:08 :: net.ipv4.fib_multipath_hash_fields = 7
12:24:08 :: net.ipv4.fib_multipath_hash_policy = 0
12:24:08 :: net.ipv4.fib_multipath_use_neigh = 0
12:24:08 :: net.ipv4.fib_notify_on_flag_change = 0
12:24:08 :: net.ipv4.fib_sync_mem = 524288
12:24:08 :: net.ipv4.fwmark_reflect = 0
12:24:08 :: net.ipv4.icmp_echo_enable_probe = 0
12:24:08 :: net.ipv4.icmp_echo_ignore_all = 0
12:24:08 :: net.ipv4.icmp_echo_ignore_broadcasts = 1
12:24:08 :: net.ipv4.icmp_errors_use_inbound_ifaddr = 0
12:24:08 :: net.ipv4.icmp_ignore_bogus_error_responses = 1
12:24:08 :: net.ipv4.icmp_msgs_burst = 50
12:24:08 :: net.ipv4.icmp_msgs_per_sec = 1000
12:24:08 :: net.ipv4.icmp_ratelimit = 1000
12:24:08 :: net.ipv4.icmp_ratemask = 6168
12:24:08 :: net.ipv4.igmp_link_local_mcast_reports = 1
12:24:08 :: net.ipv4.igmp_max_memberships = 20
12:24:08 :: net.ipv4.igmp_max_msf = 10
12:24:08 :: net.ipv4.igmp_qrv = 2
12:24:08 :: net.ipv4.inet_peer_maxttl = 600
12:24:08 :: net.ipv4.inet_peer_minttl = 120
12:24:08 :: net.ipv4.inet_peer_threshold = 65664
12:24:08 :: net.ipv4.ip_autobind_reuse = 0
12:24:08 :: net.ipv4.ip_default_ttl = 64
12:24:08 :: net.ipv4.ip_dynaddr = 0
12:24:08 :: net.ipv4.ip_early_demux = 1
12:24:08 :: net.ipv4.ip_forward = 1
12:24:08 :: net.ipv4.ip_forward_update_priority = 1
12:24:08 :: net.ipv4.ip_forward_use_pmtu = 0
12:24:08 :: net.ipv4.ip_local_port_range = 32768    60999
12:24:08 :: net.ipv4.ip_local_reserved_ports = 
12:24:08 :: net.ipv4.ip_no_pmtu_disc = 0
12:24:08 :: net.ipv4.ip_nonlocal_bind = 0
12:24:08 :: net.ipv4.ip_unprivileged_port_start = 1024
12:24:08 :: net.ipv4.ipfrag_high_thresh = 4194304
12:24:08 :: net.ipv4.ipfrag_low_thresh = 3145728
12:24:08 :: net.ipv4.ipfrag_max_dist = 64
12:24:08 :: net.ipv4.ipfrag_secret_interval = 0
12:24:08 :: net.ipv4.ipfrag_time = 30
12:24:08 :: net.ipv4.neigh.default.anycast_delay = 100
12:24:08 :: net.ipv4.neigh.default.app_solicit = 0
12:24:08 :: net.ipv4.neigh.default.base_reachable_time_ms = 30000
12:24:08 :: net.ipv4.neigh.default.delay_first_probe_time = 5
12:24:08 :: net.ipv4.neigh.default.gc_interval = 30
12:24:08 :: net.ipv4.neigh.default.gc_stale_time = 60
12:24:08 :: net.ipv4.neigh.default.gc_thresh1 = 128
12:24:08 :: net.ipv4.neigh.default.gc_thresh2 = 512
12:24:08 :: net.ipv4.neigh.default.gc_thresh3 = 1024
12:24:08 :: net.ipv4.neigh.default.interval_probe_time_ms = 5000
12:24:08 :: net.ipv4.neigh.default.locktime = 100
12:24:08 :: net.ipv4.neigh.default.mcast_resolicit = 0
12:24:08 :: net.ipv4.neigh.default.mcast_solicit = 3
12:24:08 :: net.ipv4.neigh.default.proxy_delay = 80
12:24:08 :: net.ipv4.neigh.default.proxy_qlen = 64
12:24:08 :: net.ipv4.neigh.default.retrans_time_ms = 1000
12:24:08 :: net.ipv4.neigh.default.ucast_solicit = 3
12:24:08 :: net.ipv4.neigh.default.unres_qlen = 101
12:24:08 :: net.ipv4.neigh.default.unres_qlen_bytes = 212992
12:24:08 :: net.ipv4.neigh.docker0.anycast_delay = 100
12:24:08 :: net.ipv4.neigh.docker0.app_solicit = 0
12:24:08 :: net.ipv4.neigh.docker0.base_reachable_time_ms = 30000
12:24:08 :: net.ipv4.neigh.docker0.delay_first_probe_time = 5
12:24:08 :: net.ipv4.neigh.docker0.gc_stale_time = 60
12:24:08 :: net.ipv4.neigh.docker0.interval_probe_time_ms = 5000
12:24:08 :: net.ipv4.neigh.docker0.locktime = 100
12:24:08 :: net.ipv4.neigh.docker0.mcast_resolicit = 0
12:24:08 :: net.ipv4.neigh.docker0.mcast_solicit = 3
12:24:08 :: net.ipv4.neigh.docker0.proxy_delay = 80
12:24:08 :: net.ipv4.neigh.docker0.proxy_qlen = 64
12:24:08 :: net.ipv4.neigh.docker0.retrans_time_ms = 1000
12:24:08 :: net.ipv4.neigh.docker0.ucast_solicit = 3
12:24:08 :: net.ipv4.neigh.docker0.unres_qlen = 101
12:24:08 :: net.ipv4.neigh.docker0.unres_qlen_bytes = 212992
12:24:08 :: net.ipv4.neigh.enp0s3.anycast_delay = 100
12:24:08 :: net.ipv4.neigh.enp0s3.app_solicit = 0
12:24:08 :: net.ipv4.neigh.enp0s3.base_reachable_time_ms = 30000
12:24:08 :: net.ipv4.neigh.enp0s3.delay_first_probe_time = 5
12:24:08 :: net.ipv4.neigh.enp0s3.gc_stale_time = 60
12:24:08 :: net.ipv4.neigh.enp0s3.interval_probe_time_ms = 5000
12:24:08 :: net.ipv4.neigh.enp0s3.locktime = 100
12:24:08 :: net.ipv4.neigh.enp0s3.mcast_resolicit = 0
12:24:08 :: net.ipv4.neigh.enp0s3.mcast_solicit = 3
12:24:08 :: net.ipv4.neigh.enp0s3.proxy_delay = 80
12:24:08 :: net.ipv4.neigh.enp0s3.proxy_qlen = 64
12:24:08 :: net.ipv4.neigh.enp0s3.retrans_time_ms = 1000
12:24:08 :: net.ipv4.neigh.enp0s3.ucast_solicit = 3
12:24:08 :: net.ipv4.neigh.enp0s3.unres_qlen = 101
12:24:08 :: net.ipv4.neigh.enp0s3.unres_qlen_bytes = 212992
12:24:08 :: net.ipv4.neigh.lo.anycast_delay = 100
12:24:08 :: net.ipv4.neigh.lo.app_solicit = 0
12:24:08 :: net.ipv4.neigh.lo.base_reachable_time_ms = 30000
12:24:08 :: net.ipv4.neigh.lo.delay_first_probe_time = 5
12:24:08 :: net.ipv4.neigh.lo.gc_stale_time = 60
12:24:08 :: net.ipv4.neigh.lo.interval_probe_time_ms = 5000
12:24:08 :: net.ipv4.neigh.lo.locktime = 100
12:24:08 :: net.ipv4.neigh.lo.mcast_resolicit = 0
12:24:08 :: net.ipv4.neigh.lo.mcast_solicit = 3
12:24:08 :: net.ipv4.neigh.lo.proxy_delay = 80
12:24:08 :: net.ipv4.neigh.lo.proxy_qlen = 64
12:24:08 :: net.ipv4.neigh.lo.retrans_time_ms = 1000
12:24:08 :: net.ipv4.neigh.lo.ucast_solicit = 3
12:24:08 :: net.ipv4.neigh.lo.unres_qlen = 101
12:24:08 :: net.ipv4.neigh.lo.unres_qlen_bytes = 212992
12:24:08 :: net.ipv4.neigh.vethd9a62a1.anycast_delay = 100
12:24:08 :: net.ipv4.neigh.vethd9a62a1.app_solicit = 0
12:24:08 :: net.ipv4.neigh.vethd9a62a1.base_reachable_time_ms = 30000
12:24:08 :: net.ipv4.neigh.vethd9a62a1.delay_first_probe_time = 5
12:24:08 :: net.ipv4.neigh.vethd9a62a1.gc_stale_time = 60
12:24:08 :: net.ipv4.neigh.vethd9a62a1.interval_probe_time_ms = 5000
12:24:08 :: net.ipv4.neigh.vethd9a62a1.locktime = 100
12:24:08 :: net.ipv4.neigh.vethd9a62a1.mcast_resolicit = 0
12:24:08 :: net.ipv4.neigh.vethd9a62a1.mcast_solicit = 3
12:24:08 :: net.ipv4.neigh.vethd9a62a1.proxy_delay = 80
12:24:08 :: net.ipv4.neigh.vethd9a62a1.proxy_qlen = 64
12:24:08 :: net.ipv4.neigh.vethd9a62a1.retrans_time_ms = 1000
12:24:08 :: net.ipv4.neigh.vethd9a62a1.ucast_solicit = 3
12:24:08 :: net.ipv4.neigh.vethd9a62a1.unres_qlen = 101
12:24:08 :: net.ipv4.neigh.vethd9a62a1.unres_qlen_bytes = 212992
12:24:08 :: net.ipv4.neigh.virbr0.anycast_delay = 100
12:24:08 :: net.ipv4.neigh.virbr0.app_solicit = 0
12:24:08 :: net.ipv4.neigh.virbr0.base_reachable_time_ms = 30000
12:24:08 :: net.ipv4.neigh.virbr0.delay_first_probe_time = 5
12:24:08 :: net.ipv4.neigh.virbr0.gc_stale_time = 60
12:24:08 :: net.ipv4.neigh.virbr0.interval_probe_time_ms = 5000
12:24:08 :: net.ipv4.neigh.virbr0.locktime = 100
12:24:08 :: net.ipv4.neigh.virbr0.mcast_resolicit = 0
12:24:08 :: net.ipv4.neigh.virbr0.mcast_solicit = 3
12:24:08 :: net.ipv4.neigh.virbr0.proxy_delay = 80
12:24:08 :: net.ipv4.neigh.virbr0.proxy_qlen = 64
12:24:08 :: net.ipv4.neigh.virbr0.retrans_time_ms = 1000
12:24:08 :: net.ipv4.neigh.virbr0.ucast_solicit = 3
12:24:08 :: net.ipv4.neigh.virbr0.unres_qlen = 101
12:24:08 :: net.ipv4.neigh.virbr0.unres_qlen_bytes = 212992
12:24:08 :: net.ipv4.nexthop_compat_mode = 1
12:24:08 :: net.ipv4.ping_group_range = 0   2147483647
12:24:08 :: net.ipv4.raw_l3mdev_accept = 1
12:24:08 :: net.ipv4.route.error_burst = 5000
12:24:08 :: net.ipv4.route.error_cost = 1000
12:24:08 :: net.ipv4.route.gc_elasticity = 8
12:24:08 :: net.ipv4.route.gc_interval = 60
12:24:08 :: net.ipv4.route.gc_min_interval = 0
12:24:08 :: net.ipv4.route.gc_min_interval_ms = 500
12:24:08 :: net.ipv4.route.gc_thresh = -1
12:24:08 :: net.ipv4.route.gc_timeout = 300
12:24:08 :: net.ipv4.route.max_size = 2147483647
12:24:08 :: net.ipv4.route.min_adv_mss = 256
12:24:08 :: net.ipv4.route.min_pmtu = 552
12:24:08 :: net.ipv4.route.mtu_expires = 600
12:24:08 :: net.ipv4.route.redirect_load = 20
12:24:08 :: net.ipv4.route.redirect_number = 9
12:24:08 :: net.ipv4.route.redirect_silence = 20480
12:24:08 :: net.ipv4.tcp_abort_on_overflow = 0
12:24:08 :: net.ipv4.tcp_adv_win_scale = 1
12:24:08 :: net.ipv4.tcp_allowed_congestion_control = reno cubic
12:24:08 :: net.ipv4.tcp_app_win = 31
12:24:08 :: net.ipv4.tcp_autocorking = 1
12:24:08 :: net.ipv4.tcp_available_congestion_control = reno cubic
12:24:08 :: net.ipv4.tcp_available_ulp = espintcp mptcp tls
12:24:08 :: net.ipv4.tcp_backlog_ack_defer = 1
12:24:08 :: net.ipv4.tcp_base_mss = 1024
12:24:08 :: net.ipv4.tcp_challenge_ack_limit = 2147483647
12:24:08 :: net.ipv4.tcp_child_ehash_entries = 0
12:24:08 :: net.ipv4.tcp_comp_sack_delay_ns = 1000000
12:24:08 :: net.ipv4.tcp_comp_sack_nr = 44
12:24:08 :: net.ipv4.tcp_comp_sack_slack_ns = 100000
12:24:08 :: net.ipv4.tcp_congestion_control = cubic
12:24:08 :: net.ipv4.tcp_dsack = 1
12:24:08 :: net.ipv4.tcp_early_demux = 1
12:24:08 :: net.ipv4.tcp_early_retrans = 3
12:24:08 :: net.ipv4.tcp_ecn = 2
12:24:08 :: net.ipv4.tcp_ecn_fallback = 1
12:24:08 :: net.ipv4.tcp_ehash_entries = 262144
12:24:08 :: net.ipv4.tcp_fack = 0
12:24:08 :: net.ipv4.tcp_fastopen = 1
12:24:08 :: net.ipv4.tcp_fastopen_blackhole_timeout_sec = 0
12:24:08 :: net.ipv4.tcp_fastopen_key = 18c50a1b-669e94a6-55bcd76f-11216f14
12:24:08 :: net.ipv4.tcp_fin_timeout = 60
12:24:08 :: net.ipv4.tcp_frto = 2
12:24:08 :: net.ipv4.tcp_fwmark_accept = 0
12:24:08 :: net.ipv4.tcp_invalid_ratelimit = 500
12:24:08 :: net.ipv4.tcp_keepalive_intvl = 75
12:24:08 :: net.ipv4.tcp_keepalive_probes = 9
12:24:08 :: net.ipv4.tcp_keepalive_time = 7200
12:24:08 :: net.ipv4.tcp_l3mdev_accept = 0
12:24:08 :: net.ipv4.tcp_limit_output_bytes = 1048576
12:24:08 :: net.ipv4.tcp_low_latency = 0
12:24:08 :: net.ipv4.tcp_max_orphans = 131072
12:24:08 :: net.ipv4.tcp_max_reordering = 300
12:24:08 :: net.ipv4.tcp_max_syn_backlog = 2048
12:24:08 :: net.ipv4.tcp_max_tw_buckets = 131072
12:24:08 :: net.ipv4.tcp_mem = 286143   381525  572286
12:24:08 :: net.ipv4.tcp_migrate_req = 0
12:24:08 :: net.ipv4.tcp_min_rtt_wlen = 300
12:24:08 :: net.ipv4.tcp_min_snd_mss = 48
12:24:08 :: net.ipv4.tcp_min_tso_segs = 2
12:24:08 :: net.ipv4.tcp_moderate_rcvbuf = 1
12:24:08 :: net.ipv4.tcp_mtu_probe_floor = 48
12:24:08 :: net.ipv4.tcp_mtu_probing = 0
12:24:08 :: net.ipv4.tcp_no_metrics_save = 0
12:24:08 :: net.ipv4.tcp_no_ssthresh_metrics_save = 1
12:24:08 :: net.ipv4.tcp_notsent_lowat = 4294967295
12:24:08 :: net.ipv4.tcp_orphan_retries = 0
12:24:08 :: net.ipv4.tcp_pacing_ca_ratio = 120
12:24:08 :: net.ipv4.tcp_pacing_ss_ratio = 200
12:24:08 :: net.ipv4.tcp_pingpong_thresh = 1
12:24:08 :: net.ipv4.tcp_plb_cong_thresh = 128
12:24:08 :: net.ipv4.tcp_plb_enabled = 0
12:24:08 :: net.ipv4.tcp_plb_idle_rehash_rounds = 3
12:24:08 :: net.ipv4.tcp_plb_rehash_rounds = 12
12:24:08 :: net.ipv4.tcp_plb_suspend_rto_sec = 60
12:24:08 :: net.ipv4.tcp_probe_interval = 600
12:24:08 :: net.ipv4.tcp_probe_threshold = 8
12:24:08 :: net.ipv4.tcp_recovery = 1
12:24:08 :: net.ipv4.tcp_reflect_tos = 0
12:24:08 :: net.ipv4.tcp_reordering = 3
12:24:08 :: net.ipv4.tcp_retrans_collapse = 1
12:24:08 :: net.ipv4.tcp_retries1 = 3
12:24:08 :: net.ipv4.tcp_retries2 = 15
12:24:08 :: net.ipv4.tcp_rfc1337 = 0
12:24:08 :: net.ipv4.tcp_rmem = 4096    131072  6291456
12:24:08 :: net.ipv4.tcp_sack = 1
12:24:08 :: net.ipv4.tcp_shrink_window = 0
12:24:08 :: net.ipv4.tcp_slow_start_after_idle = 1
12:24:08 :: net.ipv4.tcp_stdurg = 0
12:24:08 :: net.ipv4.tcp_syn_linear_timeouts = 4
12:24:08 :: net.ipv4.tcp_syn_retries = 6
12:24:08 :: net.ipv4.tcp_synack_retries = 5
12:24:08 :: net.ipv4.tcp_syncookies = 1
12:24:08 :: net.ipv4.tcp_thin_linear_timeouts = 0
12:24:08 :: net.ipv4.tcp_timestamps = 1
12:24:08 :: net.ipv4.tcp_tso_rtt_log = 9
12:24:08 :: net.ipv4.tcp_tso_win_divisor = 3
12:24:08 :: net.ipv4.tcp_tw_reuse = 2
12:24:08 :: net.ipv4.tcp_window_scaling = 1
12:24:08 :: net.ipv4.tcp_wmem = 4096    16384   4194304
12:24:08 :: net.ipv4.tcp_workaround_signed_windows = 0
12:24:08 :: net.ipv4.udp_child_hash_entries = 0
12:24:08 :: net.ipv4.udp_early_demux = 1
12:24:08 :: net.ipv4.udp_hash_entries = 16384
12:24:08 :: net.ipv4.udp_l3mdev_accept = 0
12:24:08 :: net.ipv4.udp_mem = 572286   763050  1144572
12:24:08 :: net.ipv4.udp_rmem_min = 4096
12:24:08 :: net.ipv4.udp_wmem_min = 4096
12:24:08 :: net.ipv4.xfrm4_gc_thresh = 32768
12:24:08 :: net.ipv6.anycast_src_echo_reply = 0
12:24:08 :: net.ipv6.auto_flowlabels = 1
12:24:08 :: net.ipv6.bindv6only = 0
12:24:08 :: net.ipv6.calipso_cache_bucket_size = 10
12:24:08 :: net.ipv6.calipso_cache_enable = 1
12:24:08 :: net.ipv6.conf.all.accept_dad = 0
12:24:08 :: net.ipv6.conf.all.accept_ra = 1
12:24:08 :: net.ipv6.conf.all.accept_ra_defrtr = 1
12:24:08 :: net.ipv6.conf.all.accept_ra_from_local = 0
12:24:08 :: net.ipv6.conf.all.accept_ra_min_hop_limit = 1
12:24:08 :: net.ipv6.conf.all.accept_ra_min_lft = 0
12:24:08 :: net.ipv6.conf.all.accept_ra_mtu = 1
12:24:08 :: net.ipv6.conf.all.accept_ra_pinfo = 1
12:24:08 :: net.ipv6.conf.all.accept_ra_rt_info_max_plen = 0
12:24:08 :: net.ipv6.conf.all.accept_ra_rt_info_min_plen = 0
12:24:08 :: net.ipv6.conf.all.accept_ra_rtr_pref = 1
12:24:08 :: net.ipv6.conf.all.accept_redirects = 1
12:24:08 :: net.ipv6.conf.all.accept_source_route = 0
12:24:08 :: net.ipv6.conf.all.accept_untracked_na = 0
12:24:08 :: net.ipv6.conf.all.addr_gen_mode = 0
12:24:08 :: net.ipv6.conf.all.autoconf = 1
12:24:08 :: net.ipv6.conf.all.dad_transmits = 1
12:24:08 :: net.ipv6.conf.all.disable_ipv6 = 0
12:24:08 :: net.ipv6.conf.all.disable_policy = 0
12:24:08 :: net.ipv6.conf.all.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv6.conf.all.drop_unsolicited_na = 0
12:24:08 :: net.ipv6.conf.all.enhanced_dad = 1
12:24:08 :: net.ipv6.conf.all.force_mld_version = 0
12:24:08 :: net.ipv6.conf.all.force_tllao = 0
12:24:08 :: net.ipv6.conf.all.forwarding = 0
12:24:08 :: net.ipv6.conf.all.hop_limit = 64
12:24:08 :: net.ipv6.conf.all.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv6.conf.all.ioam6_enabled = 0
12:24:08 :: net.ipv6.conf.all.ioam6_id = 65535
12:24:08 :: net.ipv6.conf.all.ioam6_id_wide = 4294967295
12:24:08 :: net.ipv6.conf.all.keep_addr_on_down = 0
12:24:08 :: net.ipv6.conf.all.max_addresses = 16
12:24:08 :: net.ipv6.conf.all.max_desync_factor = 600
12:24:08 :: net.ipv6.conf.all.mc_forwarding = 0
12:24:08 :: net.ipv6.conf.all.mldv1_unsolicited_report_interval = 10000
12:24:08 :: net.ipv6.conf.all.mldv2_unsolicited_report_interval = 1000
12:24:08 :: net.ipv6.conf.all.mtu = 1280
12:24:08 :: net.ipv6.conf.all.ndisc_evict_nocarrier = 1
12:24:08 :: net.ipv6.conf.all.ndisc_notify = 0
12:24:08 :: net.ipv6.conf.all.ndisc_tclass = 0
12:24:08 :: net.ipv6.conf.all.proxy_ndp = 0
12:24:08 :: net.ipv6.conf.all.ra_defrtr_metric = 1024
12:24:08 :: net.ipv6.conf.all.ra_honor_pio_life = 0
12:24:08 :: net.ipv6.conf.all.regen_max_retry = 3
12:24:08 :: net.ipv6.conf.all.router_probe_interval = 60
12:24:08 :: net.ipv6.conf.all.router_solicitation_delay = 1
12:24:08 :: net.ipv6.conf.all.router_solicitation_interval = 4
12:24:08 :: net.ipv6.conf.all.router_solicitation_max_interval = 3600
12:24:08 :: net.ipv6.conf.all.router_solicitations = -1
12:24:08 :: net.ipv6.conf.all.rpl_seg_enabled = 0
12:24:08 :: net.ipv6.conf.all.seg6_enabled = 0
12:24:08 :: net.ipv6.conf.all.seg6_require_hmac = 0
12:24:08 :: net.ipv6.conf.all.suppress_frag_ndisc = 1
12:24:08 :: net.ipv6.conf.all.temp_prefered_lft = 86400
12:24:08 :: net.ipv6.conf.all.temp_valid_lft = 604800
12:24:08 :: net.ipv6.conf.all.use_oif_addrs_only = 0
12:24:08 :: net.ipv6.conf.all.use_tempaddr = 0
12:24:08 :: net.ipv6.conf.default.accept_dad = 1
12:24:08 :: net.ipv6.conf.default.accept_ra = 1
12:24:08 :: net.ipv6.conf.default.accept_ra_defrtr = 1
12:24:08 :: net.ipv6.conf.default.accept_ra_from_local = 0
12:24:08 :: net.ipv6.conf.default.accept_ra_min_hop_limit = 1
12:24:08 :: net.ipv6.conf.default.accept_ra_min_lft = 0
12:24:08 :: net.ipv6.conf.default.accept_ra_mtu = 1
12:24:08 :: net.ipv6.conf.default.accept_ra_pinfo = 1
12:24:08 :: net.ipv6.conf.default.accept_ra_rt_info_max_plen = 0
12:24:08 :: net.ipv6.conf.default.accept_ra_rt_info_min_plen = 0
12:24:08 :: net.ipv6.conf.default.accept_ra_rtr_pref = 1
12:24:08 :: net.ipv6.conf.default.accept_redirects = 1
12:24:08 :: net.ipv6.conf.default.accept_source_route = 0
12:24:08 :: net.ipv6.conf.default.accept_untracked_na = 0
12:24:08 :: net.ipv6.conf.default.addr_gen_mode = 0
12:24:08 :: net.ipv6.conf.default.autoconf = 1
12:24:08 :: net.ipv6.conf.default.dad_transmits = 1
12:24:08 :: net.ipv6.conf.default.disable_ipv6 = 0
12:24:08 :: net.ipv6.conf.default.disable_policy = 0
12:24:08 :: net.ipv6.conf.default.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv6.conf.default.drop_unsolicited_na = 0
12:24:08 :: net.ipv6.conf.default.enhanced_dad = 1
12:24:08 :: net.ipv6.conf.default.force_mld_version = 0
12:24:08 :: net.ipv6.conf.default.force_tllao = 0
12:24:08 :: net.ipv6.conf.default.forwarding = 0
12:24:08 :: net.ipv6.conf.default.hop_limit = 64
12:24:08 :: net.ipv6.conf.default.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv6.conf.default.ioam6_enabled = 0
12:24:08 :: net.ipv6.conf.default.ioam6_id = 65535
12:24:08 :: net.ipv6.conf.default.ioam6_id_wide = 4294967295
12:24:08 :: net.ipv6.conf.default.keep_addr_on_down = 0
12:24:08 :: net.ipv6.conf.default.max_addresses = 16
12:24:08 :: net.ipv6.conf.default.max_desync_factor = 600
12:24:08 :: net.ipv6.conf.default.mc_forwarding = 0
12:24:08 :: net.ipv6.conf.default.mldv1_unsolicited_report_interval = 10000
12:24:08 :: net.ipv6.conf.default.mldv2_unsolicited_report_interval = 1000
12:24:08 :: net.ipv6.conf.default.mtu = 1280
12:24:08 :: net.ipv6.conf.default.ndisc_evict_nocarrier = 1
12:24:08 :: net.ipv6.conf.default.ndisc_notify = 0
12:24:08 :: net.ipv6.conf.default.ndisc_tclass = 0
12:24:08 :: net.ipv6.conf.default.proxy_ndp = 0
12:24:08 :: net.ipv6.conf.default.ra_defrtr_metric = 1024
12:24:08 :: net.ipv6.conf.default.ra_honor_pio_life = 0
12:24:08 :: net.ipv6.conf.default.regen_max_retry = 3
12:24:08 :: net.ipv6.conf.default.router_probe_interval = 60
12:24:08 :: net.ipv6.conf.default.router_solicitation_delay = 1
12:24:08 :: net.ipv6.conf.default.router_solicitation_interval = 4
12:24:08 :: net.ipv6.conf.default.router_solicitation_max_interval = 3600
12:24:08 :: net.ipv6.conf.default.router_solicitations = -1
12:24:08 :: net.ipv6.conf.default.rpl_seg_enabled = 0
12:24:08 :: net.ipv6.conf.default.seg6_enabled = 0
12:24:08 :: net.ipv6.conf.default.seg6_require_hmac = 0
12:24:08 :: net.ipv6.conf.default.suppress_frag_ndisc = 1
12:24:08 :: net.ipv6.conf.default.temp_prefered_lft = 86400
12:24:08 :: net.ipv6.conf.default.temp_valid_lft = 604800
12:24:08 :: net.ipv6.conf.default.use_oif_addrs_only = 0
12:24:08 :: net.ipv6.conf.default.use_tempaddr = 0
12:24:08 :: net.ipv6.conf.docker0.accept_dad = 1
12:24:08 :: net.ipv6.conf.docker0.accept_ra = 0
12:24:08 :: net.ipv6.conf.docker0.accept_ra_defrtr = 1
12:24:08 :: net.ipv6.conf.docker0.accept_ra_from_local = 0
12:24:08 :: net.ipv6.conf.docker0.accept_ra_min_hop_limit = 1
12:24:08 :: net.ipv6.conf.docker0.accept_ra_min_lft = 0
12:24:08 :: net.ipv6.conf.docker0.accept_ra_mtu = 1
12:24:08 :: net.ipv6.conf.docker0.accept_ra_pinfo = 1
12:24:08 :: net.ipv6.conf.docker0.accept_ra_rt_info_max_plen = 0
12:24:08 :: net.ipv6.conf.docker0.accept_ra_rt_info_min_plen = 0
12:24:08 :: net.ipv6.conf.docker0.accept_ra_rtr_pref = 1
12:24:08 :: net.ipv6.conf.docker0.accept_redirects = 1
12:24:08 :: net.ipv6.conf.docker0.accept_source_route = 0
12:24:08 :: net.ipv6.conf.docker0.accept_untracked_na = 0
12:24:08 :: net.ipv6.conf.docker0.addr_gen_mode = 0
12:24:08 :: net.ipv6.conf.docker0.autoconf = 1
12:24:08 :: net.ipv6.conf.docker0.dad_transmits = 1
12:24:08 :: net.ipv6.conf.docker0.disable_ipv6 = 0
12:24:08 :: net.ipv6.conf.docker0.disable_policy = 0
12:24:08 :: net.ipv6.conf.docker0.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv6.conf.docker0.drop_unsolicited_na = 0
12:24:08 :: net.ipv6.conf.docker0.enhanced_dad = 1
12:24:08 :: net.ipv6.conf.docker0.force_mld_version = 0
12:24:08 :: net.ipv6.conf.docker0.force_tllao = 0
12:24:08 :: net.ipv6.conf.docker0.forwarding = 0
12:24:08 :: net.ipv6.conf.docker0.hop_limit = 64
12:24:08 :: net.ipv6.conf.docker0.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv6.conf.docker0.ioam6_enabled = 0
12:24:08 :: net.ipv6.conf.docker0.ioam6_id = 65535
12:24:08 :: net.ipv6.conf.docker0.ioam6_id_wide = 4294967295
12:24:08 :: net.ipv6.conf.docker0.keep_addr_on_down = 0
12:24:08 :: net.ipv6.conf.docker0.max_addresses = 16
12:24:08 :: net.ipv6.conf.docker0.max_desync_factor = 600
12:24:08 :: net.ipv6.conf.docker0.mc_forwarding = 0
12:24:08 :: net.ipv6.conf.docker0.mldv1_unsolicited_report_interval = 10000
12:24:08 :: net.ipv6.conf.docker0.mldv2_unsolicited_report_interval = 1000
12:24:08 :: net.ipv6.conf.docker0.mtu = 1500
12:24:08 :: net.ipv6.conf.docker0.ndisc_evict_nocarrier = 1
12:24:08 :: net.ipv6.conf.docker0.ndisc_notify = 0
12:24:08 :: net.ipv6.conf.docker0.ndisc_tclass = 0
12:24:08 :: net.ipv6.conf.docker0.proxy_ndp = 0
12:24:08 :: net.ipv6.conf.docker0.ra_defrtr_metric = 1024
12:24:08 :: net.ipv6.conf.docker0.ra_honor_pio_life = 0
12:24:08 :: net.ipv6.conf.docker0.regen_max_retry = 3
12:24:08 :: net.ipv6.conf.docker0.router_probe_interval = 60
12:24:08 :: net.ipv6.conf.docker0.router_solicitation_delay = 1
12:24:08 :: net.ipv6.conf.docker0.router_solicitation_interval = 4
12:24:08 :: net.ipv6.conf.docker0.router_solicitation_max_interval = 3600
12:24:08 :: net.ipv6.conf.docker0.router_solicitations = -1
12:24:08 :: net.ipv6.conf.docker0.rpl_seg_enabled = 0
12:24:08 :: net.ipv6.conf.docker0.seg6_enabled = 0
12:24:08 :: net.ipv6.conf.docker0.seg6_require_hmac = 0
12:24:08 :: net.ipv6.conf.docker0.suppress_frag_ndisc = 1
12:24:08 :: net.ipv6.conf.docker0.temp_prefered_lft = 86400
12:24:08 :: net.ipv6.conf.docker0.temp_valid_lft = 604800
12:24:08 :: net.ipv6.conf.docker0.use_oif_addrs_only = 0
12:24:08 :: net.ipv6.conf.docker0.use_tempaddr = 0
12:24:08 :: net.ipv6.conf.enp0s3.accept_dad = 1
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra = 0
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_defrtr = 1
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_from_local = 0
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_min_hop_limit = 1
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_min_lft = 0
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_mtu = 1
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_pinfo = 1
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_rt_info_max_plen = 0
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_rt_info_min_plen = 0
12:24:08 :: net.ipv6.conf.enp0s3.accept_ra_rtr_pref = 1
12:24:08 :: net.ipv6.conf.enp0s3.accept_redirects = 1
12:24:08 :: net.ipv6.conf.enp0s3.accept_source_route = 0
12:24:08 :: net.ipv6.conf.enp0s3.accept_untracked_na = 0
12:24:08 :: net.ipv6.conf.enp0s3.addr_gen_mode = 0
12:24:08 :: net.ipv6.conf.enp0s3.autoconf = 1
12:24:08 :: net.ipv6.conf.enp0s3.dad_transmits = 1
12:24:08 :: net.ipv6.conf.enp0s3.disable_ipv6 = 0
12:24:08 :: net.ipv6.conf.enp0s3.disable_policy = 0
12:24:08 :: net.ipv6.conf.enp0s3.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv6.conf.enp0s3.drop_unsolicited_na = 0
12:24:08 :: net.ipv6.conf.enp0s3.enhanced_dad = 1
12:24:08 :: net.ipv6.conf.enp0s3.force_mld_version = 0
12:24:08 :: net.ipv6.conf.enp0s3.force_tllao = 0
12:24:08 :: net.ipv6.conf.enp0s3.forwarding = 0
12:24:08 :: net.ipv6.conf.enp0s3.hop_limit = 64
12:24:08 :: net.ipv6.conf.enp0s3.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv6.conf.enp0s3.ioam6_enabled = 0
12:24:08 :: net.ipv6.conf.enp0s3.ioam6_id = 65535
12:24:08 :: net.ipv6.conf.enp0s3.ioam6_id_wide = 4294967295
12:24:08 :: net.ipv6.conf.enp0s3.keep_addr_on_down = 0
12:24:08 :: net.ipv6.conf.enp0s3.max_addresses = 16
12:24:08 :: net.ipv6.conf.enp0s3.max_desync_factor = 600
12:24:08 :: net.ipv6.conf.enp0s3.mc_forwarding = 0
12:24:08 :: net.ipv6.conf.enp0s3.mldv1_unsolicited_report_interval = 10000
12:24:08 :: net.ipv6.conf.enp0s3.mldv2_unsolicited_report_interval = 1000
12:24:08 :: net.ipv6.conf.enp0s3.mtu = 9000
12:24:08 :: net.ipv6.conf.enp0s3.ndisc_evict_nocarrier = 1
12:24:08 :: net.ipv6.conf.enp0s3.ndisc_notify = 0
12:24:08 :: net.ipv6.conf.enp0s3.ndisc_tclass = 0
12:24:08 :: net.ipv6.conf.enp0s3.proxy_ndp = 0
12:24:08 :: net.ipv6.conf.enp0s3.ra_defrtr_metric = 1024
12:24:08 :: net.ipv6.conf.enp0s3.ra_honor_pio_life = 0
12:24:08 :: net.ipv6.conf.enp0s3.regen_max_retry = 3
12:24:08 :: net.ipv6.conf.enp0s3.router_probe_interval = 60
12:24:08 :: net.ipv6.conf.enp0s3.router_solicitation_delay = 1
12:24:08 :: net.ipv6.conf.enp0s3.router_solicitation_interval = 4
12:24:08 :: net.ipv6.conf.enp0s3.router_solicitation_max_interval = 3600
12:24:08 :: net.ipv6.conf.enp0s3.router_solicitations = -1
12:24:08 :: net.ipv6.conf.enp0s3.rpl_seg_enabled = 0
12:24:08 :: net.ipv6.conf.enp0s3.seg6_enabled = 0
12:24:08 :: net.ipv6.conf.enp0s3.seg6_require_hmac = 0
12:24:08 :: net.ipv6.conf.enp0s3.suppress_frag_ndisc = 1
12:24:08 :: net.ipv6.conf.enp0s3.temp_prefered_lft = 86400
12:24:08 :: net.ipv6.conf.enp0s3.temp_valid_lft = 604800
12:24:08 :: net.ipv6.conf.enp0s3.use_oif_addrs_only = 0
12:24:08 :: net.ipv6.conf.enp0s3.use_tempaddr = 0
12:24:08 :: net.ipv6.conf.lo.accept_dad = -1
12:24:08 :: net.ipv6.conf.lo.accept_ra = 1
12:24:08 :: net.ipv6.conf.lo.accept_ra_defrtr = 1
12:24:08 :: net.ipv6.conf.lo.accept_ra_from_local = 0
12:24:08 :: net.ipv6.conf.lo.accept_ra_min_hop_limit = 1
12:24:08 :: net.ipv6.conf.lo.accept_ra_min_lft = 0
12:24:08 :: net.ipv6.conf.lo.accept_ra_mtu = 1
12:24:08 :: net.ipv6.conf.lo.accept_ra_pinfo = 1
12:24:08 :: net.ipv6.conf.lo.accept_ra_rt_info_max_plen = 0
12:24:08 :: net.ipv6.conf.lo.accept_ra_rt_info_min_plen = 0
12:24:08 :: net.ipv6.conf.lo.accept_ra_rtr_pref = 1
12:24:08 :: net.ipv6.conf.lo.accept_redirects = 1
12:24:08 :: net.ipv6.conf.lo.accept_source_route = 0
12:24:08 :: net.ipv6.conf.lo.accept_untracked_na = 0
12:24:08 :: net.ipv6.conf.lo.addr_gen_mode = 0
12:24:08 :: net.ipv6.conf.lo.autoconf = 1
12:24:08 :: net.ipv6.conf.lo.dad_transmits = 1
12:24:08 :: net.ipv6.conf.lo.disable_ipv6 = 0
12:24:08 :: net.ipv6.conf.lo.disable_policy = 0
12:24:08 :: net.ipv6.conf.lo.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv6.conf.lo.drop_unsolicited_na = 0
12:24:08 :: net.ipv6.conf.lo.enhanced_dad = 1
12:24:08 :: net.ipv6.conf.lo.force_mld_version = 0
12:24:08 :: net.ipv6.conf.lo.force_tllao = 0
12:24:08 :: net.ipv6.conf.lo.forwarding = 0
12:24:08 :: net.ipv6.conf.lo.hop_limit = 64
12:24:08 :: net.ipv6.conf.lo.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv6.conf.lo.ioam6_enabled = 0
12:24:08 :: net.ipv6.conf.lo.ioam6_id = 65535
12:24:08 :: net.ipv6.conf.lo.ioam6_id_wide = 4294967295
12:24:08 :: net.ipv6.conf.lo.keep_addr_on_down = 0
12:24:08 :: net.ipv6.conf.lo.max_addresses = 16
12:24:08 :: net.ipv6.conf.lo.max_desync_factor = 600
12:24:08 :: net.ipv6.conf.lo.mc_forwarding = 0
12:24:08 :: net.ipv6.conf.lo.mldv1_unsolicited_report_interval = 10000
12:24:08 :: net.ipv6.conf.lo.mldv2_unsolicited_report_interval = 1000
12:24:08 :: net.ipv6.conf.lo.mtu = 65536
12:24:08 :: net.ipv6.conf.lo.ndisc_evict_nocarrier = 1
12:24:08 :: net.ipv6.conf.lo.ndisc_notify = 0
12:24:08 :: net.ipv6.conf.lo.ndisc_tclass = 0
12:24:08 :: net.ipv6.conf.lo.proxy_ndp = 0
12:24:08 :: net.ipv6.conf.lo.ra_defrtr_metric = 1024
12:24:08 :: net.ipv6.conf.lo.ra_honor_pio_life = 0
12:24:08 :: net.ipv6.conf.lo.regen_max_retry = 3
12:24:08 :: net.ipv6.conf.lo.router_probe_interval = 60
12:24:08 :: net.ipv6.conf.lo.router_solicitation_delay = 1
12:24:08 :: net.ipv6.conf.lo.router_solicitation_interval = 4
12:24:08 :: net.ipv6.conf.lo.router_solicitation_max_interval = 3600
12:24:08 :: net.ipv6.conf.lo.router_solicitations = -1
12:24:08 :: net.ipv6.conf.lo.rpl_seg_enabled = 0
12:24:08 :: net.ipv6.conf.lo.seg6_enabled = 0
12:24:08 :: net.ipv6.conf.lo.seg6_require_hmac = 0
12:24:08 :: net.ipv6.conf.lo.suppress_frag_ndisc = 1
12:24:08 :: net.ipv6.conf.lo.temp_prefered_lft = 86400
12:24:08 :: net.ipv6.conf.lo.temp_valid_lft = 604800
12:24:08 :: net.ipv6.conf.lo.use_oif_addrs_only = 0
12:24:08 :: net.ipv6.conf.lo.use_tempaddr = -1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_dad = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_defrtr = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_from_local = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_min_hop_limit = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_min_lft = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_mtu = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_pinfo = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_rt_info_max_plen = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_rt_info_min_plen = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_ra_rtr_pref = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_redirects = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_source_route = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.accept_untracked_na = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.addr_gen_mode = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.autoconf = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.dad_transmits = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.disable_ipv6 = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.disable_policy = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.drop_unsolicited_na = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.enhanced_dad = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.force_mld_version = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.force_tllao = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.forwarding = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.hop_limit = 64
12:24:08 :: net.ipv6.conf.vethd9a62a1.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.ioam6_enabled = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.ioam6_id = 65535
12:24:08 :: net.ipv6.conf.vethd9a62a1.ioam6_id_wide = 4294967295
12:24:08 :: net.ipv6.conf.vethd9a62a1.keep_addr_on_down = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.max_addresses = 16
12:24:08 :: net.ipv6.conf.vethd9a62a1.max_desync_factor = 600
12:24:08 :: net.ipv6.conf.vethd9a62a1.mc_forwarding = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.mldv1_unsolicited_report_interval = 10000
12:24:08 :: net.ipv6.conf.vethd9a62a1.mldv2_unsolicited_report_interval = 1000
12:24:08 :: net.ipv6.conf.vethd9a62a1.mtu = 1500
12:24:08 :: net.ipv6.conf.vethd9a62a1.ndisc_evict_nocarrier = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.ndisc_notify = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.ndisc_tclass = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.proxy_ndp = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.ra_defrtr_metric = 1024
12:24:08 :: net.ipv6.conf.vethd9a62a1.ra_honor_pio_life = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.regen_max_retry = 3
12:24:08 :: net.ipv6.conf.vethd9a62a1.router_probe_interval = 60
12:24:08 :: net.ipv6.conf.vethd9a62a1.router_solicitation_delay = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.router_solicitation_interval = 4
12:24:08 :: net.ipv6.conf.vethd9a62a1.router_solicitation_max_interval = 3600
12:24:08 :: net.ipv6.conf.vethd9a62a1.router_solicitations = -1
12:24:08 :: net.ipv6.conf.vethd9a62a1.rpl_seg_enabled = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.seg6_enabled = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.seg6_require_hmac = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.suppress_frag_ndisc = 1
12:24:08 :: net.ipv6.conf.vethd9a62a1.temp_prefered_lft = 86400
12:24:08 :: net.ipv6.conf.vethd9a62a1.temp_valid_lft = 604800
12:24:08 :: net.ipv6.conf.vethd9a62a1.use_oif_addrs_only = 0
12:24:08 :: net.ipv6.conf.vethd9a62a1.use_tempaddr = 0
12:24:08 :: net.ipv6.conf.virbr0.accept_dad = 1
12:24:08 :: net.ipv6.conf.virbr0.accept_ra = 0
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_defrtr = 1
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_from_local = 0
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_min_hop_limit = 1
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_min_lft = 0
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_mtu = 1
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_pinfo = 1
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_rt_info_max_plen = 0
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_rt_info_min_plen = 0
12:24:08 :: net.ipv6.conf.virbr0.accept_ra_rtr_pref = 1
12:24:08 :: net.ipv6.conf.virbr0.accept_redirects = 1
12:24:08 :: net.ipv6.conf.virbr0.accept_source_route = 0
12:24:08 :: net.ipv6.conf.virbr0.accept_untracked_na = 0
12:24:08 :: net.ipv6.conf.virbr0.addr_gen_mode = 0
12:24:08 :: net.ipv6.conf.virbr0.autoconf = 0
12:24:08 :: net.ipv6.conf.virbr0.dad_transmits = 1
12:24:08 :: net.ipv6.conf.virbr0.disable_ipv6 = 1
12:24:08 :: net.ipv6.conf.virbr0.disable_policy = 0
12:24:08 :: net.ipv6.conf.virbr0.drop_unicast_in_l2_multicast = 0
12:24:08 :: net.ipv6.conf.virbr0.drop_unsolicited_na = 0
12:24:08 :: net.ipv6.conf.virbr0.enhanced_dad = 1
12:24:08 :: net.ipv6.conf.virbr0.force_mld_version = 0
12:24:08 :: net.ipv6.conf.virbr0.force_tllao = 0
12:24:08 :: net.ipv6.conf.virbr0.forwarding = 0
12:24:08 :: net.ipv6.conf.virbr0.hop_limit = 64
12:24:08 :: net.ipv6.conf.virbr0.ignore_routes_with_linkdown = 0
12:24:08 :: net.ipv6.conf.virbr0.ioam6_enabled = 0
12:24:08 :: net.ipv6.conf.virbr0.ioam6_id = 65535
12:24:08 :: net.ipv6.conf.virbr0.ioam6_id_wide = 4294967295
12:24:08 :: net.ipv6.conf.virbr0.keep_addr_on_down = 0
12:24:08 :: net.ipv6.conf.virbr0.max_addresses = 16
12:24:08 :: net.ipv6.conf.virbr0.max_desync_factor = 600
12:24:08 :: net.ipv6.conf.virbr0.mc_forwarding = 0
12:24:08 :: net.ipv6.conf.virbr0.mldv1_unsolicited_report_interval = 10000
12:24:08 :: net.ipv6.conf.virbr0.mldv2_unsolicited_report_interval = 1000
12:24:08 :: net.ipv6.conf.virbr0.mtu = 1500
12:24:08 :: net.ipv6.conf.virbr0.ndisc_evict_nocarrier = 1
12:24:08 :: net.ipv6.conf.virbr0.ndisc_notify = 0
12:24:08 :: net.ipv6.conf.virbr0.ndisc_tclass = 0
12:24:08 :: net.ipv6.conf.virbr0.proxy_ndp = 0
12:24:08 :: net.ipv6.conf.virbr0.ra_defrtr_metric = 1024
12:24:08 :: net.ipv6.conf.virbr0.ra_honor_pio_life = 0
12:24:08 :: net.ipv6.conf.virbr0.regen_max_retry = 3
12:24:08 :: net.ipv6.conf.virbr0.router_probe_interval = 60
12:24:08 :: net.ipv6.conf.virbr0.router_solicitation_delay = 1
12:24:08 :: net.ipv6.conf.virbr0.router_solicitation_interval = 4
12:24:08 :: net.ipv6.conf.virbr0.router_solicitation_max_interval = 3600
12:24:08 :: net.ipv6.conf.virbr0.router_solicitations = -1
12:24:08 :: net.ipv6.conf.virbr0.rpl_seg_enabled = 0
12:24:08 :: net.ipv6.conf.virbr0.seg6_enabled = 0
12:24:08 :: net.ipv6.conf.virbr0.seg6_require_hmac = 0
12:24:08 :: net.ipv6.conf.virbr0.suppress_frag_ndisc = 1
12:24:08 :: net.ipv6.conf.virbr0.temp_prefered_lft = 86400
12:24:08 :: net.ipv6.conf.virbr0.temp_valid_lft = 604800
12:24:08 :: net.ipv6.conf.virbr0.use_oif_addrs_only = 0
12:24:08 :: net.ipv6.conf.virbr0.use_tempaddr = 0
12:24:08 :: net.ipv6.fib_multipath_hash_fields = 7
12:24:08 :: net.ipv6.fib_multipath_hash_policy = 0
12:24:08 :: net.ipv6.fib_notify_on_flag_change = 0
12:24:08 :: net.ipv6.flowlabel_consistency = 1
12:24:08 :: net.ipv6.flowlabel_reflect = 0
12:24:08 :: net.ipv6.flowlabel_state_ranges = 0
12:24:08 :: net.ipv6.fwmark_reflect = 0
12:24:08 :: net.ipv6.icmp.echo_ignore_all = 0
12:24:08 :: net.ipv6.icmp.echo_ignore_anycast = 0
12:24:08 :: net.ipv6.icmp.echo_ignore_multicast = 0
12:24:08 :: net.ipv6.icmp.error_anycast_as_unicast = 0
12:24:08 :: net.ipv6.icmp.ratelimit = 1000
12:24:08 :: net.ipv6.icmp.ratemask = 0-1,3-127
12:24:08 :: net.ipv6.idgen_delay = 1
12:24:08 :: net.ipv6.idgen_retries = 3
12:24:08 :: net.ipv6.ioam6_id = 16777215
12:24:08 :: net.ipv6.ioam6_id_wide = 72057594037927935
12:24:08 :: net.ipv6.ip6frag_high_thresh = 4194304
12:24:08 :: net.ipv6.ip6frag_low_thresh = 3145728
12:24:08 :: net.ipv6.ip6frag_secret_interval = 0
12:24:08 :: net.ipv6.ip6frag_time = 60
12:24:08 :: net.ipv6.ip_nonlocal_bind = 0
12:24:08 :: net.ipv6.max_dst_opts_length = 2147483647
12:24:08 :: net.ipv6.max_dst_opts_number = 8
12:24:08 :: net.ipv6.max_hbh_length = 2147483647
12:24:08 :: net.ipv6.max_hbh_opts_number = 8
12:24:08 :: net.ipv6.mld_max_msf = 64
12:24:08 :: net.ipv6.mld_qrv = 2
12:24:08 :: net.ipv6.neigh.default.anycast_delay = 100
12:24:08 :: net.ipv6.neigh.default.app_solicit = 0
12:24:08 :: net.ipv6.neigh.default.base_reachable_time_ms = 30000
12:24:08 :: net.ipv6.neigh.default.delay_first_probe_time = 5
12:24:08 :: net.ipv6.neigh.default.gc_interval = 30
12:24:08 :: net.ipv6.neigh.default.gc_stale_time = 60
12:24:08 :: net.ipv6.neigh.default.gc_thresh1 = 128
12:24:08 :: net.ipv6.neigh.default.gc_thresh2 = 512
12:24:08 :: net.ipv6.neigh.default.gc_thresh3 = 1024
12:24:08 :: net.ipv6.neigh.default.interval_probe_time_ms = 5000
12:24:08 :: net.ipv6.neigh.default.locktime = 0
12:24:08 :: net.ipv6.neigh.default.mcast_resolicit = 0
12:24:08 :: net.ipv6.neigh.default.mcast_solicit = 3
12:24:08 :: net.ipv6.neigh.default.proxy_delay = 80
12:24:08 :: net.ipv6.neigh.default.proxy_qlen = 64
12:24:08 :: net.ipv6.neigh.default.retrans_time_ms = 1000
12:24:08 :: net.ipv6.neigh.default.ucast_solicit = 3
12:24:08 :: net.ipv6.neigh.default.unres_qlen = 101
12:24:08 :: net.ipv6.neigh.default.unres_qlen_bytes = 212992
12:24:08 :: net.ipv6.neigh.docker0.anycast_delay = 100
12:24:08 :: net.ipv6.neigh.docker0.app_solicit = 0
12:24:08 :: net.ipv6.neigh.docker0.base_reachable_time_ms = 30000
12:24:08 :: net.ipv6.neigh.docker0.delay_first_probe_time = 5
12:24:08 :: net.ipv6.neigh.docker0.gc_stale_time = 60
12:24:08 :: net.ipv6.neigh.docker0.interval_probe_time_ms = 5000
12:24:08 :: net.ipv6.neigh.docker0.locktime = 0
12:24:08 :: net.ipv6.neigh.docker0.mcast_resolicit = 0
12:24:08 :: net.ipv6.neigh.docker0.mcast_solicit = 3
12:24:08 :: net.ipv6.neigh.docker0.proxy_delay = 80
12:24:08 :: net.ipv6.neigh.docker0.proxy_qlen = 64
12:24:08 :: net.ipv6.neigh.docker0.retrans_time_ms = 1000
12:24:08 :: net.ipv6.neigh.docker0.ucast_solicit = 3
12:24:08 :: net.ipv6.neigh.docker0.unres_qlen = 101
12:24:08 :: net.ipv6.neigh.docker0.unres_qlen_bytes = 212992
12:24:08 :: net.ipv6.neigh.enp0s3.anycast_delay = 100
12:24:08 :: net.ipv6.neigh.enp0s3.app_solicit = 0
12:24:08 :: net.ipv6.neigh.enp0s3.base_reachable_time_ms = 30000
12:24:08 :: net.ipv6.neigh.enp0s3.delay_first_probe_time = 5
12:24:08 :: net.ipv6.neigh.enp0s3.gc_stale_time = 60
12:24:08 :: net.ipv6.neigh.enp0s3.interval_probe_time_ms = 5000
12:24:08 :: net.ipv6.neigh.enp0s3.locktime = 0
12:24:08 :: net.ipv6.neigh.enp0s3.mcast_resolicit = 0
12:24:08 :: net.ipv6.neigh.enp0s3.mcast_solicit = 3
12:24:08 :: net.ipv6.neigh.enp0s3.proxy_delay = 80
12:24:08 :: net.ipv6.neigh.enp0s3.proxy_qlen = 64
12:24:08 :: net.ipv6.neigh.enp0s3.retrans_time_ms = 1000
12:24:08 :: net.ipv6.neigh.enp0s3.ucast_solicit = 3
12:24:08 :: net.ipv6.neigh.enp0s3.unres_qlen = 101
12:24:08 :: net.ipv6.neigh.enp0s3.unres_qlen_bytes = 212992
12:24:08 :: net.ipv6.neigh.lo.anycast_delay = 100
12:24:08 :: net.ipv6.neigh.lo.app_solicit = 0
12:24:08 :: net.ipv6.neigh.lo.base_reachable_time_ms = 30000
12:24:08 :: net.ipv6.neigh.lo.delay_first_probe_time = 5
12:24:08 :: net.ipv6.neigh.lo.gc_stale_time = 60
12:24:08 :: net.ipv6.neigh.lo.interval_probe_time_ms = 5000
12:24:08 :: net.ipv6.neigh.lo.locktime = 0
12:24:08 :: net.ipv6.neigh.lo.mcast_resolicit = 0
12:24:08 :: net.ipv6.neigh.lo.mcast_solicit = 3
12:24:08 :: net.ipv6.neigh.lo.proxy_delay = 80
12:24:08 :: net.ipv6.neigh.lo.proxy_qlen = 64
12:24:08 :: net.ipv6.neigh.lo.retrans_time_ms = 1000
12:24:08 :: net.ipv6.neigh.lo.ucast_solicit = 3
12:24:08 :: net.ipv6.neigh.lo.unres_qlen = 101
12:24:08 :: net.ipv6.neigh.lo.unres_qlen_bytes = 212992
12:24:08 :: net.ipv6.neigh.vethd9a62a1.anycast_delay = 100
12:24:08 :: net.ipv6.neigh.vethd9a62a1.app_solicit = 0
12:24:08 :: net.ipv6.neigh.vethd9a62a1.base_reachable_time_ms = 30000
12:24:08 :: net.ipv6.neigh.vethd9a62a1.delay_first_probe_time = 5
12:24:08 :: net.ipv6.neigh.vethd9a62a1.gc_stale_time = 60
12:24:08 :: net.ipv6.neigh.vethd9a62a1.interval_probe_time_ms = 5000
12:24:08 :: net.ipv6.neigh.vethd9a62a1.locktime = 0
12:24:08 :: net.ipv6.neigh.vethd9a62a1.mcast_resolicit = 0
12:24:08 :: net.ipv6.neigh.vethd9a62a1.mcast_solicit = 3
12:24:08 :: net.ipv6.neigh.vethd9a62a1.proxy_delay = 80
12:24:08 :: net.ipv6.neigh.vethd9a62a1.proxy_qlen = 64
12:24:08 :: net.ipv6.neigh.vethd9a62a1.retrans_time_ms = 1000
12:24:08 :: net.ipv6.neigh.vethd9a62a1.ucast_solicit = 3
12:24:08 :: net.ipv6.neigh.vethd9a62a1.unres_qlen = 101
12:24:08 :: net.ipv6.neigh.vethd9a62a1.unres_qlen_bytes = 212992
12:24:08 :: net.ipv6.neigh.virbr0.anycast_delay = 100
12:24:08 :: net.ipv6.neigh.virbr0.app_solicit = 0
12:24:08 :: net.ipv6.neigh.virbr0.base_reachable_time_ms = 30000
12:24:08 :: net.ipv6.neigh.virbr0.delay_first_probe_time = 5
12:24:08 :: net.ipv6.neigh.virbr0.gc_stale_time = 60
12:24:08 :: net.ipv6.neigh.virbr0.interval_probe_time_ms = 5000
12:24:08 :: net.ipv6.neigh.virbr0.locktime = 0
12:24:08 :: net.ipv6.neigh.virbr0.mcast_resolicit = 0
12:24:08 :: net.ipv6.neigh.virbr0.mcast_solicit = 3
12:24:08 :: net.ipv6.neigh.virbr0.proxy_delay = 80
12:24:08 :: net.ipv6.neigh.virbr0.proxy_qlen = 64
12:24:08 :: net.ipv6.neigh.virbr0.retrans_time_ms = 1000
12:24:08 :: net.ipv6.neigh.virbr0.ucast_solicit = 3
12:24:08 :: net.ipv6.neigh.virbr0.unres_qlen = 101
12:24:08 :: net.ipv6.neigh.virbr0.unres_qlen_bytes = 212992
12:24:08 :: net.ipv6.route.gc_elasticity = 9
12:24:08 :: net.ipv6.route.gc_interval = 30
12:24:08 :: net.ipv6.route.gc_min_interval = 0
12:24:08 :: net.ipv6.route.gc_min_interval_ms = 500
12:24:08 :: net.ipv6.route.gc_thresh = 1024
12:24:08 :: net.ipv6.route.gc_timeout = 60
12:24:08 :: net.ipv6.route.max_size = 2147483647
12:24:08 :: net.ipv6.route.min_adv_mss = 1220
12:24:08 :: net.ipv6.route.mtu_expires = 600
12:24:08 :: net.ipv6.route.skip_notify_on_dev_down = 0
12:24:08 :: net.ipv6.seg6_flowlabel = 0
12:24:08 :: net.ipv6.xfrm6_gc_thresh = 32768
12:24:08 :: net.mptcp.add_addr_timeout = 120
12:24:08 :: net.mptcp.allow_join_initial_addr_port = 1
12:24:08 :: net.mptcp.checksum_enabled = 0
12:24:08 :: net.mptcp.close_timeout = 60
12:24:08 :: net.mptcp.enabled = 1
12:24:08 :: net.mptcp.pm_type = 0
12:24:08 :: net.mptcp.scheduler = default
12:24:08 :: net.mptcp.stale_loss_cnt = 4
12:24:08 :: net.netfilter.nf_conntrack_acct = 0
12:24:08 :: net.netfilter.nf_conntrack_buckets = 262144
12:24:08 :: net.netfilter.nf_conntrack_checksum = 1
12:24:08 :: net.netfilter.nf_conntrack_count = 225
12:24:08 :: net.netfilter.nf_conntrack_dccp_loose = 1
12:24:08 :: net.netfilter.nf_conntrack_dccp_timeout_closereq = 64
12:24:08 :: net.netfilter.nf_conntrack_dccp_timeout_closing = 64
12:24:08 :: net.netfilter.nf_conntrack_dccp_timeout_open = 43200
12:24:08 :: net.netfilter.nf_conntrack_dccp_timeout_partopen = 480
12:24:08 :: net.netfilter.nf_conntrack_dccp_timeout_request = 240
12:24:08 :: net.netfilter.nf_conntrack_dccp_timeout_respond = 480
12:24:08 :: net.netfilter.nf_conntrack_dccp_timeout_timewait = 240
12:24:08 :: net.netfilter.nf_conntrack_events = 2
12:24:08 :: net.netfilter.nf_conntrack_expect_max = 4096
12:24:08 :: net.netfilter.nf_conntrack_frag6_high_thresh = 4194304
12:24:08 :: net.netfilter.nf_conntrack_frag6_low_thresh = 3145728
12:24:08 :: net.netfilter.nf_conntrack_frag6_timeout = 60
12:24:08 :: net.netfilter.nf_conntrack_generic_timeout = 600
12:24:08 :: net.netfilter.nf_conntrack_gre_timeout = 30
12:24:08 :: net.netfilter.nf_conntrack_gre_timeout_stream = 180
12:24:08 :: net.netfilter.nf_conntrack_icmp_timeout = 30
12:24:08 :: net.netfilter.nf_conntrack_icmpv6_timeout = 30
12:24:08 :: net.netfilter.nf_conntrack_log_invalid = 0
12:24:08 :: net.netfilter.nf_conntrack_max = 262144
12:24:08 :: net.netfilter.nf_conntrack_sctp_timeout_closed = 10
12:24:08 :: net.netfilter.nf_conntrack_sctp_timeout_cookie_echoed = 3
12:24:08 :: net.netfilter.nf_conntrack_sctp_timeout_cookie_wait = 3
12:24:08 :: net.netfilter.nf_conntrack_sctp_timeout_established = 210
12:24:08 :: net.netfilter.nf_conntrack_sctp_timeout_heartbeat_sent = 30
12:24:08 :: net.netfilter.nf_conntrack_sctp_timeout_shutdown_ack_sent = 3
12:24:08 :: net.netfilter.nf_conntrack_sctp_timeout_shutdown_recd = 3
12:24:08 :: net.netfilter.nf_conntrack_sctp_timeout_shutdown_sent = 3
12:24:08 :: net.netfilter.nf_conntrack_tcp_be_liberal = 0
12:24:08 :: net.netfilter.nf_conntrack_tcp_ignore_invalid_rst = 0
12:24:08 :: net.netfilter.nf_conntrack_tcp_loose = 1
12:24:08 :: net.netfilter.nf_conntrack_tcp_max_retrans = 3
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_close = 10
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_established = 432000
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
12:24:08 :: net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
12:24:08 :: net.netfilter.nf_conntrack_timestamp = 0
12:24:08 :: net.netfilter.nf_conntrack_udp_timeout = 30
12:24:08 :: net.netfilter.nf_conntrack_udp_timeout_stream = 120
12:24:08 :: net.netfilter.nf_flowtable_tcp_timeout = 30
12:24:08 :: net.netfilter.nf_flowtable_udp_timeout = 30
12:24:08 :: net.netfilter.nf_hooks_lwtunnel = 0
12:24:08 :: net.netfilter.nf_log.0 = NONE
12:24:08 :: net.netfilter.nf_log.1 = NONE
12:24:08 :: net.netfilter.nf_log.10 = NONE
12:24:08 :: net.netfilter.nf_log.2 = NONE
12:24:08 :: net.netfilter.nf_log.3 = NONE
12:24:08 :: net.netfilter.nf_log.4 = NONE
12:24:08 :: net.netfilter.nf_log.5 = NONE
12:24:08 :: net.netfilter.nf_log.6 = NONE
12:24:08 :: net.netfilter.nf_log.7 = NONE
12:24:08 :: net.netfilter.nf_log.8 = NONE
12:24:08 :: net.netfilter.nf_log.9 = NONE
12:24:08 :: net.netfilter.nf_log_all_netns = 0
12:24:08 :: net.nf_conntrack_max = 262144
12:24:08 :: net.unix.max_dgram_qlen = 512
12:24:08 :: sunrpc.max_resvport = 1023
12:24:08 :: sunrpc.min_resvport = 665
12:24:08 :: sunrpc.nfs_debug = 0x0000
12:24:08 :: sunrpc.nfsd_debug = 0x0000
12:24:08 :: sunrpc.nlm_debug = 0x0000
12:24:08 :: sunrpc.rpc_debug = 0x0000
12:24:08 :: sunrpc.tcp_fin_timeout = 15
12:24:08 :: sunrpc.tcp_max_slot_table_entries = 65536
12:24:08 :: sunrpc.tcp_slot_table_entries = 2
12:24:08 :: sunrpc.transports = tcp 1048576
12:24:08 :: sunrpc.transports = udp 32768
12:24:08 :: sunrpc.udp_slot_table_entries = 16
12:24:08 :: user.max_cgroup_namespaces = 95620
12:24:08 :: user.max_fanotify_groups = 128
12:24:08 :: user.max_fanotify_marks = 198574
12:24:08 :: user.max_inotify_instances = 128
12:24:08 :: user.max_inotify_watches = 186755
12:24:08 :: user.max_ipc_namespaces = 95620
12:24:08 :: user.max_mnt_namespaces = 95620
12:24:08 :: user.max_net_namespaces = 95620
12:24:08 :: user.max_pid_namespaces = 95620
12:24:08 :: user.max_time_namespaces = 95620
12:24:08 :: user.max_user_namespaces = 95620
12:24:08 :: user.max_uts_namespaces = 95620
12:24:08 :: vm.admin_reserve_kbytes = 8192
12:24:08 :: vm.compact_unevictable_allowed = 1
12:24:08 :: vm.compaction_proactiveness = 20
12:24:08 :: vm.dirty_background_bytes = 0
12:24:08 :: vm.dirty_background_ratio = 10
12:24:08 :: vm.dirty_bytes = 0
12:24:08 :: vm.dirty_expire_centisecs = 3000
12:24:08 :: vm.dirty_ratio = 20
12:24:08 :: vm.dirty_writeback_centisecs = 500
12:24:08 :: vm.dirtytime_expire_seconds = 43200
12:24:08 :: vm.extfrag_threshold = 500
12:24:08 :: vm.hugetlb_shm_group = 0
12:24:08 :: vm.laptop_mode = 0
12:24:08 :: vm.legacy_va_layout = 0
12:24:08 :: vm.lowmem_reserve_ratio = 256   256 32  0   0
12:24:08 :: vm.max_map_count = 65530
12:24:08 :: vm.memfd_noexec = 0
12:24:08 :: vm.memory_failure_early_kill = 0
12:24:08 :: vm.memory_failure_recovery = 1
12:24:08 :: vm.min_free_kbytes = 45056
12:24:08 :: vm.min_slab_ratio = 5
12:24:08 :: vm.min_unmapped_ratio = 1
12:24:08 :: vm.mmap_min_addr = 32768
12:24:08 :: vm.mmap_rnd_bits = 33
12:24:08 :: vm.mmap_rnd_compat_bits = 16
12:24:08 :: vm.nr_hugepages = 0
12:24:08 :: vm.nr_hugepages_mempolicy = 0
12:24:08 :: vm.nr_overcommit_hugepages = 0
12:24:08 :: vm.numa_stat = 1
12:24:08 :: vm.numa_zonelist_order = Node
12:24:08 :: vm.oom_dump_tasks = 1
12:24:08 :: vm.oom_kill_allocating_task = 0
12:24:08 :: vm.overcommit_kbytes = 0
12:24:08 :: vm.overcommit_memory = 0
12:24:08 :: vm.overcommit_ratio = 50
12:24:08 :: vm.page-cluster = 3
12:24:08 :: vm.page_lock_unfairness = 5
12:24:08 :: vm.panic_on_oom = 0
12:24:08 :: vm.percpu_pagelist_high_fraction = 0
12:24:08 :: vm.stat_interval = 1
12:24:08 :: vm.swappiness = 60
12:24:08 :: vm.unprivileged_userfaultfd = 0
12:24:08 :: vm.user_reserve_kbytes = 131072
12:24:08 :: vm.vfs_cache_pressure = 100
12:24:08 :: vm.watermark_boost_factor = 15000
12:24:08 :: vm.watermark_scale_factor = 10
12:24:08 :: vm.zone_reclaim_mode = 0
12:24:08 :: 
[task check]
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Enable TCP SYN cookies &lt;span class="o"&gt;(&lt;/span&gt;net.ipv4.tcp_syncookies &lt;span class="o"&gt;=&lt;/span&gt; 1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* net\.ipv4\.tcp_syncookies \s* \= \s* 1 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Disable IP forwarding &lt;span class="o"&gt;(&lt;/span&gt;net.ipv4.ip_forward &lt;span class="o"&gt;=&lt;/span&gt; 0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* net\.ipv4\.ip_forward \s* \= \s* 0 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; False
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Enable reverse path filtering on all interfaces - 0 is acceptable when default is 2 &lt;span class="o"&gt;(&lt;/span&gt;net.ipv4.conf.all.rp_filter &lt;span class="o"&gt;=&lt;/span&gt; 0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* net\.ipv4\.conf\.all\.rp_filter \s* \= \s* [0|1|2] \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Enable strict reverse path filtering on default interface - must be 2 &lt;span class="k"&gt;for &lt;/span&gt;secure defaults &lt;span class="o"&gt;(&lt;/span&gt;net.ipv4.conf.default.rp_filter &lt;span class="o"&gt;=&lt;/span&gt; 2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* net\.ipv4\.conf\.default\.rp_filter \s* \= \s* 2 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Ignore ICMP redirects on all interfaces &lt;span class="o"&gt;(&lt;/span&gt;net.ipv4.conf.all.accept_redirects &lt;span class="o"&gt;=&lt;/span&gt; 0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* net\.ipv4\.conf\.all\.accept_redirects \s* \= \s* 0 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Ignore ICMP redirects on default interface &lt;span class="o"&gt;(&lt;/span&gt;net.ipv4.conf.default.accept_redirects &lt;span class="o"&gt;=&lt;/span&gt; 0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* net\.ipv4\.conf\.default\.accept_redirects \s* \= \s* 0 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; False
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Log martian packets &lt;span class="o"&gt;(&lt;/span&gt;net.ipv4.conf.all.log_martians &lt;span class="o"&gt;=&lt;/span&gt; 1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* net\.ipv4\.conf\.all\.log_martians \s* \= \s* 1 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; False
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Restrict access to kernel logs &lt;span class="o"&gt;(&lt;/span&gt;kernel.dmesg_restrict &lt;span class="o"&gt;=&lt;/span&gt; 1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* kernel\.dmesg_restrict \s* \= \s* 1 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Disable unprivileged BPF &lt;span class="o"&gt;(&lt;/span&gt;kernel.unprivileged_bpf_disabled &lt;span class="o"&gt;=&lt;/span&gt; 2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* kernel\.unprivileged_bpf_disabled \s* \= \s* 2 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Disable unprivileged user namespaces &lt;span class="o"&gt;(&lt;/span&gt;kernel.unprivileged_userns_clone &lt;span class="o"&gt;=&lt;/span&gt; 0&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* kernel\.unprivileged_userns_clone \s* \= \s* 0 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; False
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Restrict ptrace scope - 1 or 2 acceptable &lt;span class="o"&gt;(&lt;/span&gt;kernel.yama.ptrace_scope &lt;span class="o"&gt;=&lt;/span&gt; 1|2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* kernel\.yama\.ptrace_scope \s* \= \s* [1|2] \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Protect hardlinks against race conditions &lt;span class="o"&gt;(&lt;/span&gt;fs.protected_hardlinks &lt;span class="o"&gt;=&lt;/span&gt; 1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* fs\.protected_hardlinks \s* \= \s* 1 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Protect symlinks against race conditions &lt;span class="o"&gt;(&lt;/span&gt;fs.protected_symlinks &lt;span class="o"&gt;=&lt;/span&gt; 1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* fs\.protected_symlinks \s* \= \s* 1 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Protect FIFOs against opening &lt;span class="k"&gt;in &lt;/span&gt;sticky directories &lt;span class="o"&gt;(&lt;/span&gt;fs.protected_fifos &lt;span class="o"&gt;=&lt;/span&gt; 1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* fs\.protected_fifos \s* \= \s* 1 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Protect regular files against opening &lt;span class="k"&gt;in &lt;/span&gt;sticky directories &lt;span class="o"&gt;(&lt;/span&gt;fs.protected_regular &lt;span class="o"&gt;=&lt;/span&gt; 2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;stdout match &amp;lt;^^ \s* fs\.protected_regular \s* \= \s* 2 \s* $&lt;/span&gt;&lt;span class="nv"&gt;$&amp;gt;&lt;/span&gt; True
&lt;span class="go"&gt;=================
TASK CHECK FAIL
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sudoers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo cat&lt;/span&gt; /etc/sudoers | s6 &lt;span class="nt"&gt;--plg-run&lt;/span&gt; scc@check&lt;span class="o"&gt;=&lt;/span&gt;sudoers
&lt;span class="go"&gt;12:25:00 :: [task] - run plg scc@check=sudoers
12:25:00 :: [task] - run [scc], thing: scc@check=sudoers
[task run: task.bash - scc]
[task stdout]
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;This file MUST be edited with the &lt;span class="s1"&gt;'visudo'&lt;/span&gt; &lt;span class="nb"&gt;command &lt;/span&gt;as root.
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Please consider adding &lt;span class="nb"&gt;local &lt;/span&gt;content &lt;span class="k"&gt;in&lt;/span&gt; /etc/sudoers.d/ instead of
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;directly modifying this file.
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;See the man page &lt;span class="k"&gt;for &lt;/span&gt;details on how to write a sudoers file.
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;12:25:00 :: Defaults    env_reset
12:25:00 :: Defaults    mail_badpass
12:25:00 :: Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
12:25:00 :: Defaults    use_pty
12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;This preserves proxy settings from user environments of root
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;equivalent &lt;span class="nb"&gt;users&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;group &lt;span class="nb"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;Defaults:%sudo env_keep +&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http_proxy https_proxy ftp_proxy all_proxy no_proxy"&lt;/span&gt;
&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;This allows running arbitrary commands, but so does ALL, and it means
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;different sudoers have their choice of editor respected.
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;Defaults:%sudo env_keep +&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"EDITOR"&lt;/span&gt;
&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Completely harmless preservation of a user preference.
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;Defaults:%sudo env_keep +&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GREP_COLOR"&lt;/span&gt;
&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;While you shouldn&lt;span class="s1"&gt;'t normally run git as root, you need to with etckeeper
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="s1"&gt;Defaults:%sudo env_keep += "GIT_AUTHOR_* GIT_COMMITTER_*"
&lt;/span&gt;&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Per-user preferences&lt;span class="p"&gt;;&lt;/span&gt; root won&lt;span class="s1"&gt;'t have sensible values for them.
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="s1"&gt;Defaults:%sudo env_keep += "EMAIL DEBEMAIL DEBFULLNAME"
&lt;/span&gt;&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sudo scp"&lt;/span&gt; or &lt;span class="s2"&gt;"sudo rsync"&lt;/span&gt; should be able to use your SSH agent.
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;Defaults:%sudo env_keep +&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SSH_AGENT_PID SSH_AUTH_SOCK"&lt;/span&gt;
&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Ditto &lt;span class="k"&gt;for &lt;/span&gt;GPG agent
&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;Defaults:%sudo env_keep +&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GPG_AGENT_INFO"&lt;/span&gt;
&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Host &lt;span class="nb"&gt;alias &lt;/span&gt;specification
&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;User &lt;span class="nb"&gt;alias &lt;/span&gt;specification
&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Cmnd &lt;span class="nb"&gt;alias &lt;/span&gt;specification
&lt;span class="go"&gt;12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;User privilege specification
&lt;span class="go"&gt;12:25:00 :: root    ALL=(ALL:ALL) ALL
12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Members of the admin group may gain root privileges
&lt;span class="go"&gt;12:25:00 :: %admin ALL=(ALL) ALL
12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Allow members of group &lt;span class="nb"&gt;sudo &lt;/span&gt;to execute any &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;span class="go"&gt;12:25:00 :: %sudo   ALL=(ALL:ALL) ALL
12:25:00 :: 
&lt;/span&gt;&lt;span class="gp"&gt;12:25:00 :: #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;See sudoers&lt;span class="o"&gt;(&lt;/span&gt;5&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more information on &lt;span class="s2"&gt;"@include"&lt;/span&gt; directives:
&lt;span class="go"&gt;12:25:00 :: 
12:25:00 :: @includedir /etc/sudoers.d
12:25:00 :: 
[task check]
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt;passwordless sudo is disabled&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;Defaults requiretty is not set - unsecure tty handling&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;Defaults env_reset is set&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;Defaults secure_path may be insecure - "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;Defaults mail_badpass is set&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;Defaults logfile is not configured - sudo actions not logged&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;Defaults rootpw is not set - using user's own password&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;Defaults insults is not enabled&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;Defaults timestamp_timeout is not set - using default&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;unrestricted sudo access found - ALL=(ALL) ALL&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;no commented-out dangerous directives found&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;Defaults lecture is not configured&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="go"&gt;=================
TASK CHECK FAIL
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sshd
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sshd &lt;span class="nt"&gt;-T&lt;/span&gt; | s6 &lt;span class="nt"&gt;--plg-run&lt;/span&gt; scc@check&lt;span class="o"&gt;=&lt;/span&gt;sshd
&lt;span class="go"&gt;12:25:47 :: [task] - run plg scc@check=sshd
12:25:47 :: [task] - run [scc], thing: scc@check=sshd
[task run: task.bash - scc]
[task stdout]
12:25:47 :: port 22
12:25:47 :: addressfamily any
12:25:47 :: listenaddress [::]:22
12:25:47 :: listenaddress 0.0.0.0:22
12:25:47 :: usepam yes
12:25:47 :: logingracetime 120
12:25:47 :: x11displayoffset 10
12:25:47 :: maxauthtries 6
12:25:47 :: maxsessions 10
12:25:47 :: clientaliveinterval 0
12:25:47 :: clientalivecountmax 3
12:25:47 :: streamlocalbindmask 0177
12:25:47 :: permitrootlogin without-password
12:25:47 :: ignorerhosts yes
12:25:47 :: ignoreuserknownhosts no
12:25:47 :: hostbasedauthentication no
12:25:47 :: hostbasedusesnamefrompacketonly no
12:25:47 :: pubkeyauthentication yes
12:25:47 :: kerberosauthentication no
12:25:47 :: kerberosorlocalpasswd yes
12:25:47 :: kerberosticketcleanup yes
12:25:47 :: gssapiauthentication no
12:25:47 :: gssapicleanupcredentials yes
12:25:47 :: gssapikeyexchange no
12:25:47 :: gssapistrictacceptorcheck yes
12:25:47 :: gssapistorecredentialsonrekey no
12:25:47 :: gssapikexalgorithms gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1-
12:25:47 :: passwordauthentication no
12:25:47 :: kbdinteractiveauthentication no
12:25:47 :: printmotd no
12:25:47 :: printlastlog yes
12:25:47 :: x11forwarding yes
12:25:47 :: x11uselocalhost yes
12:25:47 :: permittty yes
12:25:47 :: permituserrc yes
12:25:47 :: strictmodes yes
12:25:47 :: tcpkeepalive yes
12:25:47 :: permitemptypasswords no
12:25:47 :: compression yes
12:25:47 :: gatewayports no
12:25:47 :: usedns no
12:25:47 :: allowtcpforwarding yes
12:25:47 :: allowagentforwarding yes
12:25:47 :: disableforwarding no
12:25:47 :: allowstreamlocalforwarding yes
12:25:47 :: streamlocalbindunlink no
12:25:47 :: fingerprinthash SHA256
12:25:47 :: exposeauthinfo no
12:25:47 :: pidfile /run/sshd.pid
12:25:47 :: modulifile /etc/ssh/moduli
12:25:47 :: xauthlocation /usr/bin/xauth
12:25:47 :: ciphers chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
12:25:47 :: macs umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
12:25:47 :: banner none
12:25:47 :: forcecommand none
12:25:47 :: chrootdirectory none
12:25:47 :: trustedusercakeys none
12:25:47 :: revokedkeys none
12:25:47 :: securitykeyprovider internal
12:25:47 :: authorizedprincipalsfile none
12:25:47 :: versionaddendum none
12:25:47 :: authorizedkeyscommand none
12:25:47 :: authorizedkeyscommanduser none
12:25:47 :: authorizedprincipalscommand none
12:25:47 :: authorizedprincipalscommanduser none
12:25:47 :: hostkeyagent none
12:25:47 :: kexalgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,sntrup761x25519-sha512@openssh.com,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
12:25:47 :: casignaturealgorithms ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,rsa-sha2-512,rsa-sha2-256
12:25:47 :: hostbasedacceptedalgorithms ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,rsa-sha2-512,rsa-sha2-256
12:25:47 :: hostkeyalgorithms ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,rsa-sha2-512,rsa-sha2-256
12:25:47 :: pubkeyacceptedalgorithms ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,rsa-sha2-512,rsa-sha2-256
12:25:47 :: loglevel INFO
12:25:47 :: syslogfacility AUTH
12:25:47 :: authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2
12:25:47 :: hostkey /etc/ssh/ssh_host_rsa_key
12:25:47 :: hostkey /etc/ssh/ssh_host_ecdsa_key
12:25:47 :: hostkey /etc/ssh/ssh_host_ed25519_key
12:25:47 :: acceptenv LANG
12:25:47 :: acceptenv LC_*
12:25:47 :: authenticationmethods any
12:25:47 :: subsystem sftp /usr/lib/openssh/sftp-server
12:25:47 :: maxstartups 10:30:100
12:25:47 :: persourcemaxstartups none
12:25:47 :: persourcenetblocksize 32:128
12:25:47 :: permittunnel no
12:25:47 :: ipqos lowdelay throughput
12:25:47 :: rekeylimit 0 0
12:25:47 :: permitopen any
12:25:47 :: permitlisten any
12:25:47 :: permituserenvironment no
12:25:47 :: pubkeyauthoptions none
12:25:47 :: 
[task check]
&lt;/span&gt;&lt;span class="gp"&gt;&amp;lt;port is valid (22)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;ListenAddress found ([::]:22)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;PermitRootLogin not set&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;PasswordAuthentication disabled&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;PubkeyAuthentication enabled&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;MaxAuthTries &amp;lt;= 6 (6)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;MaxSessions &amp;lt;= 10 (10)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;LoginGraceTime not found&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;empty passwords forbidden&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;X11Forwarding is yes&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;ClientAliveInterval is 0 (should be &amp;gt;&lt;/span&gt;0&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; False
&lt;span class="gp"&gt;&amp;lt;ClientAliveCountMax 3 (&amp;lt;=3)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;UseDNS disabled&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;strong cipher present&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;strong MAC present&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;DH KEX found&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;HostKey defined (/etc/ssh/ssh_host_rsa_key)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;SyslogFacility AUTH&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;LogLevel INFO&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;AllowUsers not set (open to all)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;AllowGroups not set&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="gp"&gt;&amp;lt;sftp subsystem defined (/usr/lib/openssh/sftp-server)&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;Banner file none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;True
&lt;span class="gp"&gt;&amp;lt;neither AllowUsers nor AllowGroups is set&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;False
&lt;span class="go"&gt;=================
TASK CHECK FAIL
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>security</category>
      <category>devops</category>
      <category>linux</category>
      <category>rakulang</category>
    </item>
    <item>
      <title>Dead Simple CI Introduction</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Sat, 14 Feb 2026 13:11:55 +0000</pubDate>
      <link>https://dev.to/melezhik/dead-simple-ci-introduction-1jh6</link>
      <guid>https://dev.to/melezhik/dead-simple-ci-introduction-1jh6</guid>
      <description>&lt;p&gt;&lt;a href="http://deadsimpleci.sparrowhub.io/doc/README" rel="noopener noreferrer"&gt;Dsci&lt;/a&gt; is a brand new kid on the cicd area. It allows use of general programming languages to create ci scenarios.&lt;/p&gt;

&lt;p&gt;——-&lt;/p&gt;

&lt;p&gt;Consider some imaginary case of building and deploying an application as docker container. So, logically we have two main stages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;build docker image from source code &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;deploy docker image using docker pull and docker run commands&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see how dsci could tackle such a scenario …&lt;/p&gt;

&lt;p&gt;——-&lt;/p&gt;

&lt;h1&gt;
  
  
  Pipeline file
&lt;/h1&gt;

&lt;p&gt;The main concept we start with is so called ‘pipeline file’.&lt;/p&gt;

&lt;p&gt;It’s just yaml file containing a list of jobs to be performed. Every job is executed on isolated docker container, execution logic is always sequential - one job, by another.&lt;/p&gt;

&lt;p&gt;This pattern yet simple however covers the majority of use cases:&lt;/p&gt;

&lt;p&gt;jobs.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy/&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, every element of job list is a job, where job has some unique identifier and path to location of job file.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conditional job logic
&lt;/h1&gt;

&lt;p&gt;Usually there are some conditions when and what ci scripts are triggered. Those conditions may be based on different criteria, but usually they depend on branch names.&lt;/p&gt;

&lt;p&gt;Dsci utilizes a special syntax to define those rules. Let’s say we only want to deploy if source branch is main, and perform build for all branches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy/&lt;/span&gt; 
     &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&amp;lt;ref&amp;gt; eq "refs/heads/main"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read more on job conditions on dsci documentation - &lt;a href="https://github.com/melezhik/DSCI/blob/main/job-cond.md" rel="noopener noreferrer"&gt;https://github.com/melezhik/DSCI/blob/main/job-cond.md&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Passing parameters to job
&lt;/h1&gt;

&lt;p&gt;To pass parameters to job, just use &lt;code&gt;params:&lt;/code&gt; key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/&lt;/span&gt;
     &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bar&lt;/span&gt;
       &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy/&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those parameters could be thought as overrides for default ones, however dsci allows more then that - pass results ( states ) from one job to another, see later.&lt;/p&gt;

&lt;h1&gt;
  
  
  Job file
&lt;/h1&gt;

&lt;p&gt;The next important building block of the hierarchy is so called “job file” defining main job logic.&lt;/p&gt;

&lt;p&gt;Job file needs to be named depending on language of choice, in our example we use Bash as it usually is enough for many use cases. But using other languages is also possible. If one needs more flexibility they may chose Python or Golang&lt;/p&gt;

&lt;p&gt;build/task.bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;config version&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;tag_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;.&lt;span class="nv"&gt;$version&lt;/span&gt;
docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; app:&lt;span class="nv"&gt;$tag_version&lt;/span&gt;
docker push repo/app:&lt;span class="nv"&gt;$tag_version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this simple example our job file is just a single task job. However if there is a need to split complex job into several tasks they may do so by using job.$ext file approach. This file needs to be named according language of choice. &lt;/p&gt;

&lt;p&gt;Let’s say we have three tasks - configure, build and test - incorporated into build job, we may run them one by one like this:&lt;/p&gt;

&lt;p&gt;build/job.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/bin/python
&lt;/span&gt;&lt;span class="nf"&gt;run_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;run_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;run_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we put those tasks under build/tasks/ directory like this:&lt;/p&gt;

&lt;p&gt;build/tasks/configure/task.bash&lt;br&gt;
build/tasks/build/tasks.bash&lt;br&gt;
build/tasks/tests/task.bash&lt;/p&gt;

&lt;p&gt;In this case we have modular setup of our ci job.  &lt;/p&gt;

&lt;p&gt;The neat thing about this DSL, dsci provides the same SDK for all supported programming languages.&lt;/p&gt;

&lt;p&gt;Read more about jobs and tasks on dsci documentation web site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://deadsimpleci.sparrowhub.io/doc/task" rel="noopener noreferrer"&gt;http://deadsimpleci.sparrowhub.io/doc/task&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://deadsimpleci.sparrowhub.io/doc/job" rel="noopener noreferrer"&gt;http://deadsimpleci.sparrowhub.io/doc/job&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Passing results between jobs
&lt;/h1&gt;

&lt;p&gt;Let’s make our last job example more realistic and return docker image tag dynamically created by build job back to deploy job. We may want to do so deploy jobs know what tag to pull before deploy. All we need is to add extra line to save the job state into internal dsci cache:&lt;/p&gt;

&lt;p&gt;build/task.bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;config version&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;tag_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;.&lt;span class="nv"&gt;$version&lt;/span&gt;
docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; app:&lt;span class="nv"&gt;$tag_version&lt;/span&gt;
docker push repo/app:&lt;span class="nv"&gt;$tag_version&lt;/span&gt;
update_state tag &lt;span class="nv"&gt;$tag_version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;update_state() is very handy function allowing to pass states between different tasks and jobs. It’s implemented for all supported languages.&lt;/p&gt;

&lt;p&gt;To pick up tag name in deploy job we can use already mentioned config() function:&lt;/p&gt;

&lt;p&gt;deploy/task.bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;span class="nv"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;config tag&lt;span class="si"&gt;)&lt;/span&gt;
docker pull repo/app@&lt;span class="nv"&gt;$tag&lt;/span&gt;
docker stop &lt;span class="nt"&gt;-t&lt;/span&gt; 1 container &lt;span class="o"&gt;||&lt;/span&gt; :
docker run &lt;span class="nt"&gt;-rm&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; container &lt;span class="nt"&gt;-td&lt;/span&gt; repo/app@&lt;span class="nv"&gt;$tag&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read more about job and tasks states on dsci documentation ( the links above ^^ )&lt;/p&gt;

&lt;h1&gt;
  
  
  Secrets
&lt;/h1&gt;

&lt;p&gt;Let’s modify build job example with pushing image to docker registry. To do a push we need to authenticate against a docker registry first. Dsci enables simple way to pass secrets to pipelines.&lt;/p&gt;

&lt;p&gt;This time let’s rewrite our job file on Python for convenience:&lt;/p&gt;

&lt;p&gt;build/job.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/bin/python
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="n"&gt;password&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nf"&gt;run_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then modify build task to handle password parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;config version&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;tag_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;.&lt;span class="nv"&gt;$version&lt;/span&gt;
docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; app:&lt;span class="nv"&gt;$tag_version&lt;/span&gt;
update_state tag &lt;span class="nv"&gt;$tag_version&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt; | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; your-username &lt;span class="nt"&gt;--password-stdin&lt;/span&gt;

docker push repo/app:&lt;span class="nv"&gt;$tag_version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see secrets passed into pipelines as environment variables.&lt;/p&gt;

&lt;p&gt;And unlike other task and jobs parameters they never saved in job reports or cache files.  &lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;h1&gt;
  
  
  Deployment on localhost
&lt;/h1&gt;

&lt;p&gt;By default dsci pipelines run inside some docker container, this fits situation when one needs run purely ci code - for example build and run some unit tests. CD part comes to play when build artifacts are ready for deploy. &lt;/p&gt;

&lt;p&gt;Dsci allows switch to deployment environment by using &lt;code&gt;localhost&lt;/code&gt; switcher:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build/&lt;/span&gt;
     &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bar&lt;/span&gt;
       &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.1.0&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
     &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy/&lt;/span&gt;
     &lt;span class="na"&gt;localhost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that case deployment occurs on VM running dsci orchestrator and which allows to restart docker container with new image version right on VM&lt;/p&gt;

&lt;p&gt;——-&lt;/p&gt;

&lt;p&gt;That is it. &lt;/p&gt;

&lt;p&gt;This simple but real life example shows how easy and one can write cicd pipelines using dsci framework and how flexible it is.&lt;/p&gt;

&lt;p&gt;Hopefully you like it. &lt;/p&gt;

&lt;p&gt;—-&lt;/p&gt;

&lt;p&gt;For comprehensive documentation and more information please visit dsci web site - &lt;a href="http://deadsimpleci.sparrowhub.io/doc/README" rel="noopener noreferrer"&gt;http://deadsimpleci.sparrowhub.io/doc/README&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>pipelines</category>
      <category>forgejo</category>
    </item>
    <item>
      <title>DTAP - super simple testing protocol for infrastructure audit</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Thu, 08 Jan 2026 12:54:15 +0000</pubDate>
      <link>https://dev.to/melezhik/dtap-super-simple-testing-protocol-for-infrastructure-audit-2l45</link>
      <guid>https://dev.to/melezhik/dtap-super-simple-testing-protocol-for-infrastructure-audit-2l45</guid>
      <description>&lt;p&gt;&lt;a href="http://doubletap.sparrowhub.io" rel="noopener noreferrer"&gt;DTAP&lt;/a&gt; is a new testing protocol allowing to test infrastructure with just a Bash scripts. Here is a quick example, let's test that &lt;code&gt;/etc/dhcp/&lt;/code&gt; directory and &lt;code&gt;/etc/dhcpcd.conf&lt;/code&gt; file exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;ls&lt;/span&gt; /etc/dhcp/ 2&amp;gt;&amp;amp;1 | dtap &lt;span class="nt"&gt;--box&lt;/span&gt; - &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--session&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--params&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/dhcp/ &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--check&lt;/span&gt; path-ok &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--desc&lt;/span&gt; &lt;span class="s2"&gt;"dhcp/ dir"&lt;/span&gt;

&lt;span class="nb"&gt;ls&lt;/span&gt; /etc/dhcpcd.conf  2&amp;gt;&amp;amp;1 | dtap &lt;span class="nt"&gt;--box&lt;/span&gt; - &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--session&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--params&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/dhcpcd.conf &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--check&lt;/span&gt; path-ok &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--desc&lt;/span&gt; &lt;span class="s2"&gt;"dhcpcd.conf file"&lt;/span&gt;

dtap  &lt;span class="nt"&gt;--report&lt;/span&gt;  &lt;span class="nt"&gt;--session&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DTAP report
session: 1767875428
===
dhcp/ dir ...... OK
dhcpcd.conf file ...... OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plain and simple&lt;/p&gt;




&lt;p&gt;As one can see test scripts are just plain Bash commands, no fancy YAML or even high level programming languages.&lt;/p&gt;

&lt;p&gt;Also DTAP follows WYSIWYG principle when we get exactly what we see, in a sense this is something we would do trying to check existence  of the mentioned directory and file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls /etc/dhcp/
ls /etc/dhcpcd.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if any errors occurr we will get exactly what we are asking for - output of &lt;code&gt;ls&lt;/code&gt; command which most of the Linux users probably are familiar with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;!&lt;/span&gt;/bin/bash
&lt;span class="nb"&gt;ls&lt;/span&gt;  /etc/does-not-exist 2&amp;gt;&amp;amp;1 | dtap &lt;span class="nt"&gt;--box&lt;/span&gt; - &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--session&lt;/span&gt; &lt;span class="nv"&gt;$session&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--params&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/does-not-exist &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--check&lt;/span&gt; path-ok &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--desc&lt;/span&gt; &lt;span class="s2"&gt;"/etc/does-not-exist dir"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DTAP report
session: 1767875841
===
/etc/does-not-exist dir ...... FAIL
[report]
15:37:22 :: [sparrowtask] - run sparrow task .@path=/etc/does-not-exist
15:37:22 :: [sparrowtask] - run [.], thing: .@path=/etc/does-not-exist
[task run: task.bash - .]
[task stdout]
15:37:23 :: ls: cannot access '/etc/does-not-exist': No such file or directory
[task check]
stdout match &amp;lt;^^ "/etc/does-not-exist"  $$&amp;gt; False
=================
TASK CHECK FAIL
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;How this works?&lt;/p&gt;

&lt;p&gt;There are two essentials primitives in DTAP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;boxes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;and - checks&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Box is an abstraction for everything we want to test - from web server to messages in syslog files. Boxes produces some output to be checked against check rules ( aka checks ). In the previous examples - boxe is just &lt;code&gt;ls&lt;/code&gt; command which output redirected to a certain check rule via &lt;code&gt;--box -&lt;/code&gt; notation ( meaning read box output from STDIN ). DTAP comes with some predefined boxes user can use them without writing any piece of code, but most of the time boxes - are something a user would write as a chain of Bash commands something likes that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt; 
  2&amp;gt;&amp;amp;1
  cmd1&lt;span class="p"&gt;;&lt;/span&gt;
  cmd2&lt;span class="p"&gt;;&lt;/span&gt;
  cmd3&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;# ...&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; | tap &lt;span class="nt"&gt;--box&lt;/span&gt; -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with a single script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt; /some/box/script.sh | tap &lt;span class="nt"&gt;--box&lt;/span&gt; -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checks are rules written on formal &lt;a href="https://github.com/melezhik/Sparrow6/blob/master/documentation/taskchecks.md" rel="noopener noreferrer"&gt;DSL&lt;/a&gt; and executed remotely on DTAP server, so users don't need to install anything, only small &lt;a href="http://doubletap.sparrowhub.io/install" rel="noopener noreferrer"&gt;tap binary&lt;/a&gt; written on golang that interacts with a server send output from boxes to a server and get results back. Checks DSL is based on regular expressions and is super flexible, allowing many things to do including extension by using many general programming languages. &lt;/p&gt;

&lt;p&gt;As an example if you look inside &lt;a href="https://github.com/melezhik/doubletap/blob/main/checks/path-ok/task.check" rel="noopener noreferrer"&gt;path-ok&lt;/a&gt; check that verifies file/directory existence you'll see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generator: &amp;lt;&amp;lt;OK
!bash
echo "regexp: ^^ \"$(config path)\"  \$\$"
OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;To list available checks just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tap &lt;span class="nt"&gt;--check_list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow double tap web site &lt;a href="http://doubletap.sparrowhub.io/checks" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to get details on using available checks.&lt;/p&gt;

&lt;p&gt;It's easy to create new checks and add them to DTAP distribution, if you are instead please let me know. There is quick start introduction  into check DSL could be found &lt;a href="https://git.resf.org/testing/sparrow_task_check_quick_start/src/branch/main" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Conclusion.&lt;/p&gt;

&lt;p&gt;DTAP is a new kid on the block, that allows to test infrastructure with using just a Bash yet very flexible and powerful. I encourage you to play with it, you can start with &lt;a href="http://doubletap.sparrowhub.io/install" rel="noopener noreferrer"&gt;installation&lt;/a&gt; guide&lt;/p&gt;




&lt;p&gt;Thanks for reading &lt;/p&gt;

</description>
      <category>testing</category>
      <category>inspec</category>
      <category>infrastructure</category>
      <category>devops</category>
    </item>
    <item>
      <title>raku-sparrow6 - swiss army knife for alpine linux</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Wed, 23 Jul 2025 14:30:07 +0000</pubDate>
      <link>https://dev.to/melezhik/raku-sparrow6-swiss-army-knife-for-alpine-linux-2ngh</link>
      <guid>https://dev.to/melezhik/raku-sparrow6-swiss-army-knife-for-alpine-linux-2ngh</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/melezhik/Sparrow6" rel="noopener noreferrer"&gt;Sparrow&lt;/a&gt; is a Rakulang based framework that allows to automate routine tasks, the beauty of it - one can use prepacked plugins available from public Sparrow repository - &lt;a href="https://sparrowhub.io" rel="noopener noreferrer"&gt;https://sparrowhub.io&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Sparrow framework
&lt;/h2&gt;

&lt;p&gt;Sparrow is installed as native Alpine package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apk add &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--no-cache&lt;/span&gt; &lt;span class="nt"&gt;--wait&lt;/span&gt; 120 &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--repository&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://dl-cdn.alpinelinux.org/alpine/edge/community &lt;span class="se"&gt;\&lt;/span&gt;
raku-sparrow6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set up plugins repository&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SP6_REPO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://sparrowhub.io/repo
s6 &lt;span class="nt"&gt;--index-update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Search alpine plugins
&lt;/h2&gt;

&lt;p&gt;Sparrowhub has a lot of plugins, to limit search to Alpine related plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;s6 &lt;span class="nt"&gt;--search&lt;/span&gt; alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are now not too many of them for Alpine, eventually I am going to add more, put in comments what sort of plugins one would like to see&lt;/p&gt;

&lt;h2&gt;
  
  
  Run plugin
&lt;/h2&gt;

&lt;p&gt;To run plugin, use Sparrow cli, you can also pass parameters to a plugin. For example, to validate APKBUILD file one can use &lt;code&gt;apkbuild-strict&lt;/code&gt; plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;s6 &lt;span class="nt"&gt;--plg-run&lt;/span&gt; apkbuild-strict@path&lt;span class="o"&gt;=&lt;/span&gt;/path/to/apkbuild/file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way Sparrow plugins could be run from terminal or get inlined into shell scripts&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It'd be great to hear feedback from (Alpine) users, what sort of tasks could be implemented by Sparrow&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Kudos to &lt;a href="https://pkgs.alpinelinux.org/packages?name=&amp;amp;branch=edge&amp;amp;repo=&amp;amp;arch=&amp;amp;maintainer=Celeste" rel="noopener noreferrer"&gt;Celeste&lt;/a&gt; - Alpine maintainer for raku-sparrow6 Alpine package creation &lt;/p&gt;

</description>
      <category>sparrow</category>
      <category>rakulang</category>
      <category>alpine</category>
      <category>linux</category>
    </item>
    <item>
      <title>Validating configuration files with Raku and Sparrow Task::Check DSL</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Thu, 30 Jan 2025 08:53:50 +0000</pubDate>
      <link>https://dev.to/melezhik/validating-config-files-with-raku-and-sparrow-taskcheck-dsl-1ekp</link>
      <guid>https://dev.to/melezhik/validating-config-files-with-raku-and-sparrow-taskcheck-dsl-1ekp</guid>
      <description>&lt;p&gt;In real world we have a lot of pure structured or structured in hard to parse formats configuration files:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/etc/default/nginx&lt;/code&gt;, &lt;code&gt;/etc/default/grub&lt;/code&gt;, &lt;code&gt;logrotate.conf&lt;/code&gt;, &lt;code&gt;sysctl.conf&lt;/code&gt; - to name a few. &lt;/p&gt;

&lt;p&gt;In configuration management it's not only important to maintain specific configurations but also validate those changes to make it sure we don't break things.&lt;/p&gt;

&lt;p&gt;Sparrow - is an automation tool written on Raku that allow to make such a validation by leveraging Task::Check DSL rules which underneath are just Raku regular expressions.&lt;/p&gt;

&lt;p&gt;In the rest of this post we take a look at real life example.&lt;/p&gt;




&lt;h1&gt;
  
  
  Grub
&lt;/h1&gt;

&lt;p&gt;Consider linux GRUB boot loader file &lt;code&gt;/etc/default/grub&lt;/code&gt; with following  configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRUB_DEFAULT=0
#GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=2
GRUB_DISTRIBUTOR=`lsb_release -i -s 2&amp;gt; /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="rootfstype=ext4 quiet splash acpi_osi="
GRUB_CMDLINE_LINUX=""
GRUB_ENABLE_CRYPTODISK=true

# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"

# Uncomment to disable graphical terminal (grub-pc only)
#GRUB_TERMINAL=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
#GRUB_GFXMODE=640x480

# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true

# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY="true"

# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"

GRUB_DISABLE_OS_PROBER="true"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Though configuration format is quite simple, based on VAR=value semantics, it still allows some freedom in specification. &lt;/p&gt;

&lt;p&gt;For example to enable variables we could use one of many forms - &lt;code&gt;yes/"yes"&lt;/code&gt;, &lt;code&gt;true/"true"&lt;/code&gt; and just &lt;code&gt;1&lt;/code&gt;. Another challenge is to check that some variable are disabled - they might be just commented or “switched off” via negation form, e.g. VAR=0,false,""&lt;/p&gt;




&lt;p&gt;As rigorous operations we want to validate a couple of things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Boot on crypted disks is supported by setting GRUB_ENABLE_CRYPTODISK to one of the values: &lt;code&gt;1,yes,true&lt;/code&gt; and optional quoted form - &lt;code&gt;"yes","true"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OS prober capability is disabled or in other words GRUB_DISABLE_OS_PROBER is not set by using any of forms - &lt;code&gt;1,yes,true,"yes","true"&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before go parsing let's create simple Raku program (Sparrow task), that dumps out configuration removing empty and commented lines, the whole output will be placed inside &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt; markers for visibility:&lt;/p&gt;

&lt;p&gt;task.raku&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!raku&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;validate config {&lt;/span&gt;&lt;span class="si"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;} ...&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;chomp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt; &lt;span class="sr"&gt;/\S+/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;@out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt; &lt;span class="sr"&gt;/^ \s* '#'/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's write verification scenario by creating rules in Sparrow::Task::Check DSL format:&lt;/p&gt;

&lt;p&gt;task.check&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;note: validate config

between: {'&amp;gt;&amp;gt;&amp;gt;'}  {'&amp;lt;&amp;lt;&amp;lt;'}

  note: allow to boot on crypted disks
  regexp: ^^ \s* "GRUB_ENABLE_CRYPTODISK=" (&amp;lt;[y 1 true]&amp;gt;  | '"true"' | '"yes"' )

  note: never allow to enable os prober
  !regexp: ^^ \s* "GRUB_DISABLE_OS_PROBER=" (&amp;lt;[y 1 true]&amp;gt; | '"true"' | '"yes"' )

end:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DSL code has there major parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;between: {'&amp;gt;&amp;gt;&amp;gt;'}  {'&amp;lt;&amp;lt;&amp;lt;'}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setting a context for a search in between &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; ... &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt; delimiter, this is an example of so called &lt;em&gt;search context modifiers&lt;/em&gt;, in this case - Range modifier. &lt;/p&gt;

&lt;p&gt;In other words this is precaution that we only search within specific boundaries of text output&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;regexp: ^^ \s* "GRUB_ENABLE_CRYPTODISK=" (&amp;lt;[y 1 true]&amp;gt;  | '"true"' | '"yes"' )&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verifying that we have &lt;code&gt;GRUB_ENABLE_CRYPTODISK&lt;/code&gt; set to one of values (y,1,true,"true","yes"). &lt;/p&gt;

&lt;p&gt;&lt;code&gt;regexp:&lt;/code&gt; marker means Raku regular expression is used for validation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;note: never allow to enable os prober
!regexp: ^^ \s* "GRUB_DISABLE_OS_PROBER=" (&amp;lt;[y 1 true]&amp;gt; | '"true"' | '"yes"' )&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verifying we DON'T(*) have &lt;code&gt;GRUB_ENABLE_CRYPTODISK&lt;/code&gt; set to one of values (y,1,true,"true","yes"), in other words that GRUB_ENABLE_CRYPTODISK is disabled. &lt;/p&gt;

&lt;p&gt;(*) &lt;code&gt;!&lt;/code&gt; sign before &lt;code&gt;regexp:&lt;/code&gt; marker means negation logic.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Note:&lt;/code&gt; expressions are human readable comments that are showed up in a  report to help us correlate every check to business logic&lt;/p&gt;

&lt;h1&gt;
  
  
  Test report
&lt;/h1&gt;

&lt;p&gt;Now let's run our script and get a result of test. As this is Sparrow scenario, we use &lt;code&gt;s6&lt;/code&gt; - Sparrow CLI runner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;
s6 &lt;span class="nt"&gt;--task-run&lt;/span&gt; .@path&lt;span class="o"&gt;=&lt;/span&gt;/etc/default/grub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;14:09:20 :: [sparrowtask] - run sparrow task .@path=/etc/default/grub
14:09:20 :: [sparrowtask] - run thing .
[task run: task.raku - .]
[task stdout]
14:09:21 :: validate config examples/grub ...
14:09:21 :: &amp;gt;&amp;gt;&amp;gt;
14:09:21 :: GRUB_CMDLINE_LINUX=""
14:09:21 :: GRUB_CMDLINE_LINUX_DEFAULT="rootfstype=ext4 quiet splash acpi_osi="
14:09:21 :: GRUB_DEFAULT=0
14:09:21 :: GRUB_DISABLE_OS_PROBER="true"
14:09:21 :: GRUB_DISTRIBUTOR=`lsb_release -i -s 2&amp;gt; /dev/null || echo Debian`
14:09:21 :: GRUB_ENABLE_CRYPTODISK=true
14:09:21 :: GRUB_HIDDEN_TIMEOUT_QUIET=true
14:09:21 :: GRUB_TIMEOUT=2
14:09:21 :: &amp;lt;&amp;lt;&amp;lt;
[task check]
# validate config
# allow to boot on crypted disks
stdout match (r) &amp;lt;^^ \s* "GRUB_ENABLE_CRYPTODISK=" (&amp;lt;[y 1 true]&amp;gt;  | '"true"' | '"yes"' )&amp;gt; True
# never allow to enable os prober
stdout match (r) &amp;lt;!^^ \s* "GRUB_DISABLE_OS_PROBER=" (&amp;lt;[y 1 true]&amp;gt; | '"true"' | '"yes"' )&amp;gt; False
=================
TASK CHECK FAIL

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;em&gt;PS for colorful report please click &lt;a href="https://pasteboard.co/grlUKxSkrGYf.jpg" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expectedly we have following results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GRUB_ENABLE_CRYPTODISK check passed&lt;/li&gt;
&lt;li&gt;GRUB_DISABLE_OS_PROBER fails &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pretty impressive results considering such a little amount of code has been written!&lt;/p&gt;




&lt;p&gt;Sparrow &lt;a href="https://github.com/melezhik/Sparrow6/blob/master/documentation/taskchecks.md" rel="noopener noreferrer"&gt;Task::Check&lt;/a&gt;s is comprehensive and super flexible tool allowing one to write validation scenarios for arbitrary data formats and complexity, check out documentation pages to know more.&lt;/p&gt;

&lt;p&gt;That is it. Thanks for reading &lt;/p&gt;

</description>
      <category>rakulang</category>
      <category>linux</category>
      <category>grub</category>
      <category>data</category>
    </item>
    <item>
      <title>Useful terminal plugins to build golang code</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Fri, 24 Jan 2025 09:16:01 +0000</pubDate>
      <link>https://dev.to/melezhik/useful-terminal-plugins-to-build-golang-code-gj0</link>
      <guid>https://dev.to/melezhik/useful-terminal-plugins-to-build-golang-code-gj0</guid>
      <description>&lt;p&gt;Recently, I've released 2 new Sparrow plugins to help build Golang code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sparrowhub.io/plugin/go-build/0.000001" rel="noopener noreferrer"&gt;go-build&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Simple golang code builder&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sparrowhub.io/plugin/go-format/0.000001" rel="noopener noreferrer"&gt;go-format&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Golang code formatter&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;They are simple yet useful, providing two essentials tools to build Golang code in terminal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Build code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Format code&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest of the post shows how to use the plugins&lt;/p&gt;




&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;

&lt;p&gt;To install plugins we need to use &lt;a href="https://github.com/melezhik/Tomtit" rel="noopener noreferrer"&gt;Tomtit&lt;/a&gt; task runner with profiles - preset of Raku scenarios that grouped by topics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; /to/you/source/code
tom &lt;span class="nt"&gt;--init&lt;/span&gt; &lt;span class="c"&gt;# initialize Tomtit for the first time&lt;/span&gt;
tom &lt;span class="nt"&gt;--profile&lt;/span&gt; go &lt;span class="c"&gt;# install go profile scenarios&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now once we've installed &lt;code&gt;go&lt;/code&gt; profile, we have an access to &lt;code&gt;go-build&lt;/code&gt;  and &lt;code&gt;go-format&lt;/code&gt; scenarios which are just a Raku wrappers to run mentioned plugins. Code is simple enough and editable to adjust your project specific needs&lt;/p&gt;

&lt;p&gt;Go-build scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

tom &lt;span class="nt"&gt;--cat&lt;/span&gt; go-build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!raku&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cmd/app/main.go&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
  &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cmd/cli/cli.go&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;


&lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;run&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;go-build&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go-format scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

tom &lt;span class="nt"&gt;--cat&lt;/span&gt; go-format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

task-run &lt;span class="s2"&gt;"go format"&lt;/span&gt;, &lt;span class="s2"&gt;"go-format"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Customization
&lt;/h1&gt;

&lt;p&gt;In case of &lt;code&gt;go-build&lt;/code&gt; scenario - adjust &lt;code&gt;path&lt;/code&gt; array with files to build for your project specific:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nano
tom &lt;span class="nt"&gt;--edit&lt;/span&gt; go-build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!raku&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cmd/app/app.go&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
  &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cmd/app2/app2.go&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;# the rest of the code stays the same &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Run
&lt;/h1&gt;

&lt;p&gt;To run plugins - use &lt;code&gt;tom&lt;/code&gt; cli runner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!bash
tom go-build
11:56:26 :: go build cmd/main.go
11:56:27 :: cmd/main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!bash
tom go-format
11:57:18 :: cmd/main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;That is it. &lt;/p&gt;

&lt;p&gt;Follow plugins &lt;a href="https://sparrowhub.io/search?q=%27go-%27" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to get familiar with plugins parameters.&lt;/p&gt;

&lt;p&gt;Thanks for reading &lt;/p&gt;

</description>
      <category>rakulang</category>
      <category>raku</category>
      <category>go</category>
    </item>
    <item>
      <title>Simple search in source code with Tomtit and Sparrow</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Thu, 23 Jan 2025 20:21:22 +0000</pubDate>
      <link>https://dev.to/melezhik/simple-find-in-source-code-with-tomtit-and-sparrow-312</link>
      <guid>https://dev.to/melezhik/simple-find-in-source-code-with-tomtit-and-sparrow-312</guid>
      <description>&lt;p&gt;Recently, I've released a simple Sparrow plugin called &lt;a href="https://sparrowhub.io/plugin/find/0.000007" rel="noopener noreferrer"&gt;find&lt;/a&gt; to search text in source code, which is based on find and grep core linux utilities.&lt;/p&gt;

&lt;p&gt;The rest of the document shows how to perform search in terminal by using &lt;a href="https://github.com/melezhik/Tomtit" rel="noopener noreferrer"&gt;Tomtit&lt;/a&gt; task runner.&lt;/p&gt;




&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;

&lt;p&gt;To install the plugin, we need to use Tomtit task runner with profiles - preset of Raku scenarios that grouped by topics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; /to/you/source/code
tom &lt;span class="nt"&gt;--init&lt;/span&gt; &lt;span class="c"&gt;# initialize Tomtit for the first time&lt;/span&gt;
tom &lt;span class="nt"&gt;--profile&lt;/span&gt; code &lt;span class="c"&gt;# install code profile scenarios&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now once we've installed &lt;code&gt;code&lt;/code&gt; profile scenarios (for now it's just a single one), we have an access to &lt;code&gt;search&lt;/code&gt; scenario which is just a Raku wrapper to do search with &lt;code&gt;find&lt;/code&gt; plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

tom &lt;span class="nt"&gt;--cat&lt;/span&gt; search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!raku&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;ext (go): &lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;

&lt;span class="nv"&gt;$ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;go&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;$ext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$search1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;search1: &lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$search2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;search2: &lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$exclude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;exclude: &lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;find [&lt;/span&gt;&lt;span class="si"&gt;$search1&lt;/span&gt;&lt;span class="s2"&gt;] [&lt;/span&gt;&lt;span class="si"&gt;$search2&lt;/span&gt;&lt;span class="s2"&gt;] !&lt;/span&gt;&lt;span class="si"&gt;$exclude&lt;/span&gt;&lt;span class="s2"&gt; in &lt;/span&gt;&lt;span class="si"&gt;$ext&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;

&lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;run&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;find &lt;/span&gt;&lt;span class="si"&gt;$search1&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;$search2&lt;/span&gt;&lt;span class="s2"&gt; in &lt;/span&gt;&lt;span class="si"&gt;$ext&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;find&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$ext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$search1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;search2&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$search2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;"",&lt;/span&gt;
  &lt;span class="s"&gt;exclude&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$exclude&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;"",&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic is following:&lt;/p&gt;

&lt;p&gt;‘search1’ filters results out by first string and then ‘search2’ filter is applied for final results, ‘ext’ defines files extension to search.&lt;/p&gt;

&lt;h1&gt;
  
  
  Customization
&lt;/h1&gt;

&lt;p&gt;Stub code shipped with Tomtit profile is good enough, we only need to change it a bit, to make default choice for file extenstion suitable for Raku project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nano
tom &lt;span class="nt"&gt;--edit&lt;/span&gt; search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!raku&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;ext (rakumod): &lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;

&lt;span class="nv"&gt;$ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rakumod&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;$ext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# ... the rest of the code is the same&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Search
&lt;/h1&gt;

&lt;p&gt;Now let's search files in my &lt;a href="https://github.com/melezhik/Tomtit" rel="noopener noreferrer"&gt;Tomtit&lt;/a&gt; repository. Say, I want to find all exported functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

tom search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;load configuration from /home/melezhik/projects/Tomtit/.tom/env/config.raku
ext (rakumod): 
search1: sub
search2: is export
exclude: 
find [sub] [is export] ! in rakumod
23:09:06 :: find [sub] [is export] [!] in *.rakumod
23:09:06 :: ===
23:09:06 :: find . -name *.rakumod -exec grep --color -H 'sub' {} \; | grep 'is export'
23:09:06 :: case2
23:09:06 :: ./lib/Tomtit/Completion.rakumod:sub complete () is export {
23:09:06 :: ./lib/Tomtit.rakumod:our sub check-if-init ( $dir ) is export {
23:09:06 :: ./lib/Tomtit.rakumod:our sub init ($dir) is export {
23:09:06 :: ./lib/Tomtit.rakumod:our sub load-conf () is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub tomtit-usage () is export  {
23:09:06 :: ./lib/Tomtit.rakumod:sub tomtit-help () is export  {
23:09:06 :: ./lib/Tomtit.rakumod:sub tomtit-clean ($dir) is export { 
23:09:06 :: ./lib/Tomtit.rakumod:sub scenario-last ($dir) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub scenario-run ($dir,$scenario,%args?) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub scenario-remove ($dir,$scenario) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub scenario-cat ($dir,$scenario,%args?) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub scenario-edit ($dir,$scenario) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub environment-edit ($dir,$env) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub environment-list ($dir) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub environment-set ($dir,$env) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub environment-show ($dir) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub environment-cat ($dir,$env,%args?) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub scenario-doc ($dir,$scenario) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub scenario-list ($dir) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub scenario-list-print ($dir) is export {
23:09:06 :: ./lib/Tomtit.rakumod:multi sub profile-list  is export {
23:09:06 :: ./lib/Tomtit.rakumod:multi sub profile-list($dir,$profile is copy)  is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub profile-install ($dir, $profile is copy, %args?) is export {
23:09:06 :: ./lib/Tomtit.rakumod:sub completion-install () is export {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;That is it. Follow plugin &lt;a href="https://sparrowhub.io/plugin/find/0.000007" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to get familiar with plugin parameters.&lt;/p&gt;

&lt;p&gt;Thanks for reading&lt;/p&gt;

</description>
      <category>search</category>
      <category>raku</category>
      <category>rakulang</category>
      <category>sparrow</category>
    </item>
    <item>
      <title>Developing a simple Sparrow plugin with Raku and Bash</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Mon, 20 Jan 2025 14:27:08 +0000</pubDate>
      <link>https://dev.to/melezhik/developing-a-simple-sparrow-plugin-with-raku-and-bash-51g0</link>
      <guid>https://dev.to/melezhik/developing-a-simple-sparrow-plugin-with-raku-and-bash-51g0</guid>
      <description>&lt;p&gt;Sparrow is very efficient in writing scripts to automate system management using Raku and Bash, in today's post I am going to show an example ...&lt;/p&gt;




&lt;h2&gt;
  
  
  Deploy configuration file and restart service upon changes
&lt;/h2&gt;

&lt;p&gt;Let's create a simple plugin that enable / disable some configuration flags in service configuration file and if any changes occur reload a service. Format of flags in configuration file is following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var=true|false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is an example of configuration file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;config.txt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;debug=true
sentry=false
tls=false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usually services are managed as systemd units, so &lt;code&gt;service reload&lt;/code&gt; could be used to reload service configuration.&lt;/p&gt;

&lt;p&gt;——&lt;/p&gt;

&lt;p&gt;Let’s get started and create root folder for the plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; service-config-reload
&lt;span class="nb"&gt;cd &lt;/span&gt;service-config-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now inside plugin root directory:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hook.raku&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!raku&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;orig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="nv"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;slurp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;orig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$cfg&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt; &lt;span class="sr"&gt;s/&amp;lt;?wb&amp;gt; "$f=" \S+ /$f=true/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;disable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$cfg&lt;/span&gt; &lt;span class="o"&gt;~~&lt;/span&gt; &lt;span class="sr"&gt;s/&amp;lt;?wb&amp;gt; "$f=" \S+ /$f=false/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;set_stdout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$cfg&lt;/span&gt; &lt;span class="ow"&gt;ne&lt;/span&gt; &lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;orig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;set_stdout&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;config changed&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
   &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="nv"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;spurt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cfg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nv"&gt;set_stdout&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;config updated&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
   &lt;span class="nv"&gt;run_task&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;service_restart&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="s"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;service&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p tasks/service_restart/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tasks/service_restart/task.bash&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;service &lt;span class="nv"&gt;$service&lt;/span&gt; reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In real life applications services might have a linter capability where before configuration is applied it's checked and if any error occur application of changes is terminated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; /usr/bin/&lt;span class="nv"&gt;$service&lt;/span&gt; &lt;span class="nt"&gt;--check&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;service &lt;span class="nv"&gt;$service&lt;/span&gt; reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Publish plugin
&lt;/h1&gt;

&lt;p&gt;Packaging scenario as a plugin will allow users to reuse it as a library.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sparrow.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"service-config-reload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deploy configuration file and restart service upon changes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"linux"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/melezhik/sparrow-plugins/tree/master/service-config-reload"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This last command will upload plugin to local Sparrow repository (see this &lt;a href="https://github.com/melezhik/Sparrow6/blob/master/documentation/repository.md#create-repository" rel="noopener noreferrer"&gt;doc&lt;/a&gt; for more details)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!bash&lt;/span&gt;

s6 &lt;span class="nt"&gt;--upload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use of plugins
&lt;/h2&gt;

&lt;p&gt;Anywhere in Raku scenario, just do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!raku&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Sparrow6::&lt;/span&gt;&lt;span class="nv"&gt;DSL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;run&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apply and reload&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;service-config-reload&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;txt&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;service&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;tls&lt;/span&gt; &lt;span class="nv"&gt;sentry&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# enable TLS and use of Sentry for production&lt;/span&gt;
   &lt;span class="s"&gt;disable&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# disable debug mode for production &lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;h1&gt;
  
  
  PS
&lt;/h1&gt;

&lt;p&gt;Source code of the plugin could be found here - &lt;a href="https://github.com/melezhik/sparrow-plugins/tree/master/service-config-reload" rel="noopener noreferrer"&gt;https://github.com/melezhik/sparrow-plugins/tree/master/service-config-reload&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sparrow</category>
      <category>raku</category>
      <category>bash</category>
      <category>linux</category>
    </item>
    <item>
      <title>Go pipelines with Raku interfaces</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Tue, 05 Nov 2024 20:47:34 +0000</pubDate>
      <link>https://dev.to/melezhik/go-pipelines-with-raku-interfaces-j7o</link>
      <guid>https://dev.to/melezhik/go-pipelines-with-raku-interfaces-j7o</guid>
      <description>&lt;p&gt;So, let's say you're golang developer and want pure Go to write some CICD task:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cat task.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, pipeline"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go is cool, but there is one thing that makes it difficult to use in high level scenarios - its verbosity. Passing parameters to go tasks and return them back to main scenario takes some efforts and a lot of boilerplate code. It'd be good to keep main code concise and easy to read. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://raku.org" rel="noopener noreferrer"&gt;Rakulang&lt;/a&gt; in other hand is perfect language when it comes to munge data in and out, due it's extreme flexibility and expressiveness. &lt;/p&gt;

&lt;p&gt;In this post I am going to show how to embed golang tasks into CICD pipelines, with a little help of Sparrow framework.&lt;/p&gt;




&lt;p&gt;Let's, first of all, modify our golang task code, new version will be:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cat task.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"fmt"&lt;/span&gt;
  &lt;span class="s"&gt;"github.com/melezhik/sparrowgo"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Params&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="n"&gt;Params&lt;/span&gt;

  &lt;span class="c"&gt;// sparrowgo takes care about passing &lt;/span&gt;
  &lt;span class="c"&gt;// input parameters from Raku to Go&lt;/span&gt;
  &lt;span class="n"&gt;sparrowgo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;// read params from pipeline&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task params: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;// return results back to pipeline &lt;/span&gt;
  &lt;span class="n"&gt;sparrowgo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Results&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello from Go"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All we've done here is utilized Sparrowgo package that "convert" golang task into Sparrow task with a benefits of passing and returning data from and to Rakulang.  &lt;/p&gt;




&lt;p&gt;Finally this how our pipeline will look like, now it's Raku part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!raku

my $s = task-run ".", %(
  :message&amp;lt;Hello from Raku&amp;gt;
);

say "Result: ", $s&amp;lt;Message&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;High level design.&lt;/p&gt;

&lt;p&gt;Now, once we have some prove of concept code in place, we can get a high level picture of what our pipeline system could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      [ Raku scenario to pass and handle data in and out ]
        \                    \                     \          
      task.go -&amp;gt; result -&amp;gt; task.go -&amp;gt; result -&amp;gt; task.go -&amp;gt; ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we have the best of two worlds - Raku to write scenarios with less of code and Golang to do all heaving lifting where performance and strict type checking is required. &lt;/p&gt;

</description>
      <category>rakulang</category>
      <category>go</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Sparky - composable user interfaces for internal services</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Mon, 01 Jul 2024 15:09:30 +0000</pubDate>
      <link>https://dev.to/melezhik/sparky-composable-user-interfaces-for-internal-services-3i7k</link>
      <guid>https://dev.to/melezhik/sparky-composable-user-interfaces-for-internal-services-3i7k</guid>
      <description>&lt;p&gt;Sparky recent releases have introduced a lot of features allowing to build user interfaces for internal web applications.&lt;/p&gt;




&lt;p&gt;In a nutshell &lt;a href="https://github.com/melezhik/sparky" rel="noopener noreferrer"&gt;Sparky&lt;/a&gt; is a web platform to run automation tasks, and Sparky equips you with a rich feature set to build a frontend to launch tasks with parameters.&lt;/p&gt;

&lt;h1&gt;
  
  
  HTML controls
&lt;/h1&gt;

&lt;p&gt;Let's brew some coffee, even though I've been trying to slow down on caffeine recently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;allow_manual_run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Flavor&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latte"&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;select&lt;/span&gt; 
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;espresso&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;amerikano&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;latte&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Topic&lt;/span&gt;  
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;milk"&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;select&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;milk&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;cream&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;cinnamon&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;multiple&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Step3&lt;/span&gt; 
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;boiled&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;water"&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;input&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple Sparky job definition will spin up a simple UI with 3 controls:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fful881r6w8tpa6k8hh39.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fful881r6w8tpa6k8hh39.jpeg" alt="UI" width="656" height="1176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Raku scenario those input parameters are handled like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$flavor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;Flavor&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$water&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;Step3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@topics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# tags() needs :array modifier&lt;/span&gt;
&lt;span class="c1"&gt;# as multiple choices are passed&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="nv"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;Topic&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;@topics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, huh? &lt;/p&gt;

&lt;p&gt;One more coffee, please! &lt;/p&gt;

&lt;h1&gt;
  
  
  Or maybe you like a tea?
&lt;/h1&gt;

&lt;p&gt;Another cool feature of Sparky is a multi scenario flows or group variables. Let's say you would like to give a choice of coffer &lt;em&gt;or&lt;/em&gt; tea, so instead of having 2 job definitions with different sets of variables, let's create just one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="c1"&gt;# tea vars&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Flavor&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;black"&lt;/span&gt; 
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;select&lt;/span&gt; 
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;black&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;green&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;tea&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Topic&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;milk"&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;select&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;milk&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;cream&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;tea&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;# coffee vars&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Flavor&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latte"&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;select&lt;/span&gt; 
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;espresso&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;amerikano&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;latte&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;coffee&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Topic&lt;/span&gt;  
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;milk"&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;select&lt;/span&gt;
    &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;milk&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;cream&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;cinnamon&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;coffee&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;multiple&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="c1"&gt;# common vars&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt;

    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Step3&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;boiled&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;water"&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;input&lt;/span&gt;
    &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;tea&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;coffee&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# every var&lt;/span&gt;
&lt;span class="c1"&gt;# in group vars&lt;/span&gt;
&lt;span class="c1"&gt;# is a separate&lt;/span&gt;
&lt;span class="c1"&gt;# scenario &lt;/span&gt;

&lt;span class="na"&gt;group_vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tea&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;coffee&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when the job gets run, we have a &lt;em&gt;choice&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmelezhik%2Fimages%2Fblob%2Fmaster%2FImage%252001.07.2024%2520at%252017.40.jpeg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmelezhik%2Fimages%2Fblob%2Fmaster%2FImage%252001.07.2024%2520at%252017.40.jpeg%3Fraw%3Dtrue" alt="UI2" width="658" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then (when click on proper link), let's enjoy some tea:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmelezhik%2Fimages%2Fblob%2Fmaster%2FImage%252001.07.2024%2520at%252017.42.jpeg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fmelezhik%2Fimages%2Fblob%2Fmaster%2FImage%252001.07.2024%2520at%252017.42.jpeg%3Fraw%3Dtrue" alt="UI3" width="852" height="962"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Sparky is a nice web console to build internal automation services with HTML and write automation scenarios with Raku. Thanks for reading.&lt;/p&gt;

</description>
      <category>ui</category>
      <category>html</category>
      <category>raku</category>
      <category>automation</category>
    </item>
    <item>
      <title>Sparky - hacking minikube with mini tool</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Fri, 14 Jun 2024 13:56:10 +0000</pubDate>
      <link>https://dev.to/melezhik/sparky-hacking-minikube-with-mini-tool-3jl8</link>
      <guid>https://dev.to/melezhik/sparky-hacking-minikube-with-mini-tool-3jl8</guid>
      <description>&lt;p&gt;TL; DR: How to deploy docker to minikube when one does not need anything fancy, but pure Raku.&lt;/p&gt;




&lt;p&gt;So, you have your own pet K8s cluster deployed as minikube and you want to play with it. You have few microservices to build and you don't want to bother with kubernetes low level commands at all.&lt;/p&gt;

&lt;p&gt;On the other hand, you setup is &lt;em&gt;complex enough&lt;/em&gt; to express it in a bunch of yaml files or kubectl commands. Here is an elegant way to handle this in pure Raku, and it's called Sparky ...&lt;/p&gt;




&lt;h1&gt;
  
  
  Show me the design
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      |-------------------------------------|
      | Sparky -&amp;gt; kubectl -&amp;gt; MiniKube       | 
      |                     /\  /\  /\      |
      |                     pod pod pod     |
      |-------------------------------------| 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the infrastructure part is simple - on the same host we install minikube and Sparky that underlying uses kubectl to deploy containers into k8s cluster.&lt;/p&gt;

&lt;h1&gt;
  
  
  Show me the code
&lt;/h1&gt;

&lt;p&gt;As usually Sparky job is a pure Raku code, but this time some plugins will be of use as well ...&lt;/p&gt;

&lt;p&gt;Sparky is integrated with - Sparrowhub - &lt;a href="https://sparrowhub.io" rel="noopener noreferrer"&gt;https://sparrowhub.io&lt;/a&gt; - repository of Sparrow plugins - useful building blocks for any sort of automation.&lt;/p&gt;

&lt;p&gt;Let's use a couple of them - k8s-deployment and k8s-pod-check to deploy and check Kubernetes pods. From Sparky point of view those are &lt;em&gt;just Raku functions&lt;/em&gt;, with some input parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;run&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dpl create&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;k8s-deployment&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;deployment_name&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;app_name&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nginx:1&lt;/span&gt;&lt;span class="mf"&gt;.14.2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="c1"&gt;# give it some time to allow all pods to start ...&lt;/span&gt;
&lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;run&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx pod check&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;k8s-pod-check&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;namespace&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;die&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nv"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the tutorial purpose we are going to deploy nginx server with 3 replicas, by using &lt;a href="https://sparrowhub.io/plugin/k8s-deployment/0.000004" rel="noopener noreferrer"&gt;k8s-deployment&lt;/a&gt; plugin.&lt;/p&gt;

&lt;p&gt;Let's give it a try.&lt;/p&gt;

&lt;h1&gt;
  
  
  First run
&lt;/h1&gt;

&lt;p&gt;And the very first deploy ... fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... some output ...

11:03:34 :: deployment.apps/nginx created
11:03:34 :: [repository] - installing k8s-pod-check, version 0.000012
11:03:34 :: [repository] - install Data::Dump to /home/astra/.sparrowdo/minikube/sparrow6/plugins/k8s-pod-check/raku-lib
All candidates are currently installed
No reason to proceed. Use --force-install to continue anyway
[task run: task.pl6 - nginx pod check]
[task stdout]
11:03:41 :: ${:die-on-check-fail(Bool::True), :name("nginx"), :namespace("default"), :num(3)}
11:03:41 :: ===========================
11:03:41 :: NAME                           READY   STATUS             RESTARTS         AGE
11:03:41 :: nginx-77d8468669-5gxbf         0/1     ErrImagePull       0                5s
11:03:41 :: nginx-77d8468669-c5vbl         0/1     ErrImagePull       0                5s
11:03:41 :: nginx-77d8468669-lhc54         0/1     ErrImagePull       0                5s
11:03:41 :: ===========================
11:03:41 :: nginx-77d8468669-5gxbf POD_NOT_OK
11:03:41 :: nginx-77d8468669-c5vbl POD_NOT_OK
11:03:41 :: nginx-77d8468669-lhc54 POD_NOT_OK
[task check]
stdout match &amp;lt;^^ 'nginx' \S+ \s+ POD_OK $$&amp;gt; False
---
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although Kubernetes deployment has been successfully created, further &lt;a href="https://sparrowhub.io/plugin/k8s-pod-check/0.000012" rel="noopener noreferrer"&gt;k8s-pod-check&lt;/a&gt; failed to verify that all pods are running. &lt;/p&gt;

&lt;p&gt;Use of &lt;code&gt;die-on-check-fail&lt;/code&gt; option made the job stops strait away after this point.&lt;/p&gt;

&lt;p&gt;The reason is in &lt;code&gt;ErrImagePull&lt;/code&gt; - nginx docker image is not accessible from within a minikube, which a known minkube DNS issue, which is easy to fix.&lt;/p&gt;

&lt;h1&gt;
  
  
  It's fixed!
&lt;/h1&gt;

&lt;p&gt;All we need to do is to upload nginx docker image  &lt;em&gt;manually&lt;/em&gt;, so that minukube will pick it up from a file cache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube image load nginx:1.14.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when have restarted the failed job we get this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... some output ...

11:05:42 :: deployment.apps/nginx unchanged
[task run: task.pl6 - nginx pod check]
[task stdout]
11:05:47 :: ${:die-on-check-fail(Bool::False), :name("nginx"), :namespace("default"), :num(3)}
11:05:47 :: ===========================
11:05:47 :: NAME                           READY   STATUS             RESTARTS         AGE
11:05:47 :: nginx-77d8468669-5gxbf         1/1     Running            0                2m10s
11:05:47 :: nginx-77d8468669-c5vbl         1/1     Running            0                2m10s
11:05:47 :: nginx-77d8468669-lhc54         1/1     Running            0                2m10s
11:05:47 :: ===========================
11:05:47 :: nginx-77d8468669-5gxbf POD_OK
11:05:47 :: nginx-77d8468669-c5vbl POD_OK
11:05:47 :: nginx-77d8468669-lhc54 POD_OK
[task check]
stdout match &amp;lt;^^ 'nginx' \S+ \s+ POD_OK $$&amp;gt; True
&amp;lt;3 pods are running&amp;gt; True
---
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last deployment has not changed (with is denoted by "deployment.apps/nginx unchanged" line), as we did not change anything, however minikube now is able to pick the recently uploaded docker image and all pods now are running.&lt;/p&gt;

&lt;p&gt;Congratulation with the very first successfully deployment to Kubernetes via Sparky!&lt;/p&gt;

&lt;h1&gt;
  
  
  Clean up
&lt;/h1&gt;

&lt;p&gt;In the end let's remove our test pods, by using k8s-deployment plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;run&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dpl delete&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;k8s-deployment&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;deployment_name&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Further thoughts
&lt;/h1&gt;

&lt;p&gt;This simple scenario is going to give us some ideas on how to deploy to Kubernetes in imperative way using pure Raku, I, personally like this approach better, as having a bunch of helm charts and yaml files seems overkill when one need just to deploy some none production code, however, as always YMMV, thanks for reading ...&lt;/p&gt;

</description>
      <category>k8s</category>
      <category>raku</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Sparky - simple and efficient alternative to Ansible</title>
      <dc:creator>Alexey Melezhik</dc:creator>
      <pubDate>Fri, 31 May 2024 13:22:49 +0000</pubDate>
      <link>https://dev.to/melezhik/sparky-simple-and-efficient-alternative-to-ansible-1fod</link>
      <guid>https://dev.to/melezhik/sparky-simple-and-efficient-alternative-to-ansible-1fod</guid>
      <description>&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqux8rwm2igz2ui5rt48e.png" alt="SparkyLogo" width="120" height="120"&gt;
&lt;/h2&gt;

&lt;p&gt;So, you have a hundred VMs you need to manage, and you have ... Ansible ? I should stop here, as this is a tool that is standard in configuration management nowadays, but I'd dare to continue and say there is a better alternative to it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But before we get into it, why am I so frustrated with Ansible? Here are my points:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;YAML based declarative DSL really stinks on complex tasks as it lacks the flexibility that imperative languages have.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;YAML is not even a programming language, and you gonna pay the price very soon.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To keep ansible code clean and simple, extra efforts are required, one need to refactor out all the complexity from YAML to python modules and this feels like "why I &lt;em&gt;even&lt;/em&gt; start using YAML DSL"?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ansible reports are frustrating as I always need to add these debug tasks to show real STDOUT/STDERR emitted from commands, where it should just work out of the box.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ansible ties me to the idea of "running on a host," where sometimes I need to run tasks not tied to hosts, yes, you can still use "ansible_connection=local" but this feels awkward.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Meet Sparky
&lt;/h1&gt;

&lt;p&gt;So, meet Sparky - elegant, efficient and all-battery included automation tool. It's written on powerful and modern &lt;a href="http://raku.org" rel="noopener noreferrer"&gt;Raku&lt;/a&gt; language, with &lt;a href="https://bulma.io" rel="noopener noreferrer"&gt;bulma&lt;/a&gt; css frontend and web sockets.&lt;/p&gt;

&lt;p&gt;To install Sparky - install &lt;a href="https://rakudo.org" rel="noopener noreferrer"&gt;Rakudo&lt;/a&gt; first and then install Sparky itself as a Raku module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://rakubrew.org/install-on-perl.sh | sh 
eval "$(~/.rakubrew/bin/rakubrew init Bash)" 
rakubrew download moar-2024.05
git clone https://github.com/melezhik/sparky.git
cd sparky/
# install Sparky and it's dependencies
zef install --/test .
# init sparky sqlite database
raku db-init.raku
# run sparky job runner
nohup sparkyd &amp;gt;~/.sparkyd.log &amp;lt; /dev/null &amp;amp;
# run sparky web console
cro run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple scenario gets it up and running; if you go to &lt;a href="http://127.0.0.1:4000" rel="noopener noreferrer"&gt;http://127.0.0.1:4000&lt;/a&gt; you'll see a nice Sparky web console. We use the console to run sparky jobs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrecpkwigt4o346zqvj8.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrecpkwigt4o346zqvj8.jpeg" alt="SparkyUI" width="800" height="744"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Show me the design
&lt;/h1&gt;

&lt;p&gt;So we have a control plane that would manage many hosts over ssh, using push mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         ---------------
         | CP , Sparky | 
         ---------------
              [ssh] 
       /   /    |    \    \
     host host host host host

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is pretty much what ansible does ...&lt;/p&gt;

&lt;h1&gt;
  
  
  Show me the code
&lt;/h1&gt;

&lt;p&gt;Now say, we have 5 NGINX servers we need to restart, let's drop a simple Sparky job to do this in pure &lt;a href="https://raku.org" rel="noopener noreferrer"&gt;Raku&lt;/a&gt; language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Sparky::&lt;/span&gt;&lt;span class="nv"&gt;JobApi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;Pipeline&lt;/span&gt; &lt;span class="nv"&gt;does&lt;/span&gt; &lt;span class="nn"&gt;Sparky::JobApi::&lt;/span&gt;&lt;span class="nv"&gt;Role&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;job&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;workers&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="nv"&gt;$j&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;queue:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;sparrowdo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;bootstrap&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx_{&lt;/span&gt;&lt;span class="si"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;}.local.domain&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
       &lt;span class="s"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="s"&gt;stage&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;child&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
         &lt;span class="s"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;
       &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt; 
   &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;service&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;restart&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nginx&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this scenario, Sparky will run five parallel jobs that restart nginx on five hosts. Simple and elegant.&lt;/p&gt;

&lt;p&gt;Moreover those five jobs will appear as five separate reports in Sparky UI …&lt;/p&gt;

&lt;h1&gt;
  
  
  Got interested?
&lt;/h1&gt;

&lt;p&gt;Of course, this is only a quick glance at Sparky architecture and features, things to cover further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Job orchestration (DAGs)&lt;/li&gt;
&lt;li&gt;Core DSL (pure Raku)&lt;/li&gt;
&lt;li&gt;Custom UIs&lt;/li&gt;
&lt;li&gt;Authentication (oauth2) and security access list&lt;/li&gt;
&lt;li&gt;Writing more sophisticated scenarios&lt;/li&gt;
&lt;li&gt;Extending Sparky with plugins by using many programming languages&lt;/li&gt;
&lt;li&gt;Installing Sparky with MySQL/Postgresql database storage (instead of sqlite) &lt;/li&gt;
&lt;li&gt;Using Sparky as CI server (SCM triggering and cron jobs)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;p&gt;Sparky project - &lt;a href="https://github.com/melezhik/sparky" rel="noopener noreferrer"&gt;https://github.com/melezhik/sparky&lt;/a&gt;&lt;/p&gt;

</description>
      <category>raku</category>
      <category>automation</category>
      <category>ansible</category>
    </item>
  </channel>
</rss>
