2 .\" Automatically generated by Pandoc 3.6.2
4 .TH "R7" "1" "Tue Jun 3 2025" "v0.2.0" "User Manual"
7 R7 is a configuration management framework made to configure nodes with
8 configuration files and related operations versioned in a central
10 To remain code versioning system agnostic, manual or automated
11 versioning is left to the user, via makefiles or triggered from r7
12 \f[CR]site\-config\f[R] configuration file \f[I](See below)\f[R].
14 The idea is to store hosts configurations in \f[CR]nodes/hostname\f[R]
15 directories that maps each host\[cq]s \f[CR]/etc\f[R] and to assign
16 those hosts to configuration groups containing the directives to install
17 the configuration and potential requirements.
19 \f[I]Nodes sub\-directories are host names understood by the ssh client
20 and configuration.\f[R]
22 \f[I]Currently, r7 requires valid ssh configuration and key files in the
23 repository \f[CI].ssh/\f[I] directory.\f[R]
25 \f[I]Repositories can be initialized with \f[CI]rset init\f[I] or
26 \f[CI]rset \-w path/to/new\-repository init\f[I], the user will then
27 have to provide valid configurations and keys for \f[CI].ssh/\f[I] in
28 the newly created directory.\f[R]
30 \f[I]See Technical Notes for dependencies and supported platforms.\f[R]
32 There is an example of r7 repository:
46 \&./.ssh/id_ed25519_r7
47 \&./.ssh/id_ed25519_r7.pub
51 There is an example of r7 site configuration (\f[CR]site\-config\f[R]
55 prefix install state doc
56 group common \[aq].*\[aq]
57 group test0 hostB hostC
62 There is an example of the deployment of that configuration within the
67 \- (ok) hostA:common::install_nothing
68 \- (ok) hostA:common::state_uname
69 \- (ok) hostA:common::doc_tutorial
70 \- (ok) hostB:common::install_nothing
71 \- (ok) hostB:common::state_uname
72 \- (ok) hostB:common::doc_tutorial
73 \- (ok) hostC:common::install_nothing
74 \- (ok) hostC:common::state_uname
75 \- (ok) hostC:common::doc_tutorial
76 \- (ok) hostB:test0::state_test
77 \- (ok) hostC:test0::state_test
80 In this example, everything goes fine, groups are executed on each
81 related nodes, note the \f[CR]\[aq].*\[aq]\f[R] matching all hosts
82 present in \f[CR]./nodes\f[R].
83 Groups are POSIX shell scripts that are a collection of functions.
85 There is the \f[CR]common\f[R] group:
88 install_nothing() \f[B]{\f[R]
89 echo Nothing installed
92 state_uname() \f[B]{\f[R]
96 doc_tutorial() \f[B]{\f[R]
97 echo \[dq]## Welcome to the R7 tutorial!\[dq]
101 And there is the \f[CR]test0\f[R] group:
104 state_test() \f[B]{\f[R]
109 Any function managed by \f[CR]r7\f[R] needs to be declared in the format
110 \f[CR]\[ha]PREFIX_NAME()\f[R].
112 Group files names can\[cq]t contain spaces, tabs or newlines, as well
113 for nodes \f[CR]dirnames\f[R].
114 \f[I]The `:' character is not recommended as well as it may reduce
115 readability of the interactive output.\f[R]
117 Called groups and node directories are copied to related nodes in
118 \f[CR]hostname:/tmp/r7/\f[R]:
121 /tmp/r7/hostA/ # Contents of test.org/nodes/hostA/
122 /tmp/r7/common.dir # Contents of test.org/groups/common.dir/
123 /tmp/r7/test.dir # Contents of test.org/groups/test.dir
126 Groups may have no \f[CR].dir\f[R] directory, in this case, nothing is
129 Once the group copy is done, functions are executed in the order of the
130 defined prefix (part of the \f[CR]site\-config\f[R] file shown before):
133 prefix install state doc
136 This means the functions matching \f[CR]\[ha]install.*()\f[R],
137 \f[CR]\[ha]state.*()\f[R] and \f[CR]\[ha]doc.*()\f[R] (the default
138 \f[CR]R7_PREFIX\f[R]) in the respective declaration order they\[cq]re
139 found in the related group file will be executed.
141 Site configurations are shell scripts sourced by r7 after it\[cq]s
142 environment is initialized, so \f[CR]prefix\f[R], \f[CR]group\f[R],
143 \f[CR]output\-dump\f[R], \f[CR]summary\f[R] are the functions or aliases
144 provided by r7 itself.
145 This allow for scripting from the \f[CR]site\-config\f[R] file.
146 Here \f[CR]output\-dump\f[R], and \f[CR]summary\f[R] are called to
147 output potential errors, diffs and permissions changes at the end of the
148 interactive output obtained by \f[CR]r7 run\-config\f[R].
149 If nothing happened, nothing is added to the output.
150 .SS Errors during remote execution of groups
151 In our previous example, we modify \f[CR]state_test\f[R] so the
152 \f[CR]test\f[R] fails.
155 state_test() \f[B]{\f[R]
160 And we re\-run the configuration to see what\[cq]s happening.
164 \- (ok) hostA:common::install_nothing
165 \- (ok) hostA:common::state_uname
166 \- (ok) hostA:common::doc_tutorial
167 \- (ok) hostB:common::install_nothing
168 \- (ok) hostB:common::state_uname
169 \- (ok) hostB:common::doc_tutorial
170 \- (ok) hostC:common::install_nothing
171 \- (ok) hostC:common::state_uname
172 \- (ok) hostC:common::doc_tutorial
173 \- (error 1) hostB:test0::state_test
174 \- (error 1) hostC:test0::state_test
175 \- (error 1) \- in hostB test0 state_test (1748622980)
176 \- (error 1) \- in hostC test0 state_test (1748622980)
179 The last two lines are part of the \f[CR]summary\f[R] output.
181 Let\[cq]s modify the \f[CR]state_test\f[R] function again to add some
182 verbosity to it\[cq]s output.
184 \f[I]Note that we also change the return value.\f[R]
187 state_test() \f[B]{\f[R]
189 false \f[B]||\f[R] \f[B]{\f[R]
196 This will produce the following summary:
199 \- (error 22) \- in hostB test0 state_test (1748622980)
204 \- (error 22) \- in hostC test0 state_test (1748622980)
210 Diffs and permissions changes are also displayed by the
211 \f[CR]summary\f[R] command.
212 When they\[cq]re are detected, the captured related output is shown.
213 .SS Repository initialisation
214 Using the \f[CR]init\f[R] command, we can specify the current or a
215 specified work directory to be created and act as an r7 repository.
217 \f[I]Automated versioning of outputs are currently let to the user, a
218 recommended place would be the end of the site configuration file.\f[R]
220 This command initializes a new directory called \f[CR]test.org\f[R]:
227 Once this step is done, it is required to:
229 Copy or initialize the ssh key to the \f[CR].ssh\f[R] folder in the
230 repository created in \f[CR].ssh/id_ed25519\-r7\f[R] and
231 \f[CR]./ssh/id_ed25519\-r7.pub\f[R]
233 Adjust the SSH client configuration file in the repository
234 \f[CR].ssh/config\f[R]
236 \f[I]Note that it is possible to import additional SSH configurations,
237 like the user one from the SSH configuration, but it is advised to keep
239 .SS SSH agent handling
240 The function \f[CR]unlock\f[R] can be used to set the SSH agent
241 environment, this will be required for any automated operation later
246 \&. $(command \-v r7) \f[I]# Sourcing r7\f[R]
248 tmux \f[B]||\f[R] screen
250 .SS Tmux configuration
253 set \-g update\-environment \-r
255 .SS Optional Shell configuration
256 This is useful for handling multiple tmux sessions.
259 \f[I]# Add this to the shell\[aq]s rc\f[R]
260 \f[B]if\f[R] [ \-z \[dq]$TMUX\[dq] ]\f[B];\f[R] \f[B]then\f[R]
261 \f[B]if\f[R] [ \-n \[dq]$SSH_TTY\[dq] ]\f[B];\f[R] \f[B]then\f[R]
262 \f[B]if\f[R] [ \-z \[dq]$SSH_AUTH_SOCK\[dq] ]\f[B];\f[R] \f[B]then\f[R]
263 export SSH_AUTH_SOCK=\[dq]$HOME/.ssh/.auth_socket\[dq]
265 \f[B]if\f[R] [ ! \-S \[dq]$SSH_AUTH_SOCK\[dq] ]\f[B];\f[R] \f[B]then\f[R]
266 eval $(ssh\-agent \-a $SSH_AUTH_SOCK) >/dev/null 2>&1
267 echo $SSH_AGENT_PID >$HOME/.ssh/.auth_pid
269 \f[B]if\f[R] [ \-z $SSH_AGENT_PID ]\f[B];\f[R] \f[B]then\f[R]
270 export SSH_AGENT_PID=$(cat $HOME/.ssh/.auth_pid)
272 ssh\-add \[dq]$SSH_ID\[dq] 2>/dev/null
277 For adding a new host, the simplest way is to have pre\-configured
278 \f[CR]authorized_keys\f[R] for the target user, it is then required to
279 add it to the \f[CR]known_hosts\f[R] file.
280 For that, it is possible to use r7 SSH functions:
283 \&. $(command \-v r7) \f[I]# Sourcing r7\f[R]
284 ssh\-accept\-new hostname
287 If resetting the target\[cq]s user \f[CR]authorized_keys\f[R] file is
288 needed, the following function can be used:
291 \&. $(command \-v r7) \f[I]# Sourcing r7\f[R]
292 ssh\-authorized\-keys\-reset hostname
295 \f[I]\f[BI]Warning:\f[I] This will resets the SSH authorized_keys file
296 for the target user (root, by default) and put the
297 \f[CI].ssh/id_ed25519\-r7.pub\f[I] in place.\f[R]
299 Once the host is accepted in the \f[CR]known_hosts\f[R] file, it\[cq]s
300 possible to import it automatically.
301 .SS Importing hosts configurations
302 Avoiding to import the configuration manually is possible with the
303 \f[CR]import\f[R] command:
309 Most common configuration files will be copied in a newly created
310 \f[CR]nodes/hostname\f[R] sub\-directory.
311 .SS Writing group files
312 Group files collects functions related to the configuration of the
313 operating system, networking, services, global and user configurations
314 packages installations and application deployments.
316 By specifying the execution prefix, the user determines the order of
317 execution of the functions declared in the group file.
320 service_A() \f[B]{\f[R]
325 service_B() \f[B]{\f[R]
330 state_A() \f[B]{\f[R]
335 echo \[dq]## Service A\[dq]
337 echo \[dq]\- [url](http://test.org/)\[dq]
342 \f[I]\f[BI]file\f[I]: \f[CI]groups/example1\f[I]\f[R]
344 With the default prefix, \f[CR]install\f[R], \f[CR]state\f[R],
345 \f[CR]doc\f[R], the function that will be executed are
346 \f[CR]state_A\f[R] and \f[CR]doc_A\f[R].
347 To test that group file with all the functions inside we can call r7 the
351 r7 \-P \[aq]service state doc\[aq] group example1 hostname
354 Or using the \f[CR]\-a\f[R] flag which will create a prefix
355 automatically with all functions present in the group file:
358 r7 \-a group example1 hostname
361 In a real situation, this example will have failing functions because
362 the \f[CR]service\f[R] command may not be found or the services named
363 \f[CR]A\f[R] or \f[CR]B\f[R] does not exist.
366 ! (error 127) tools0:example1::service_A
367 ! (error 127) tools0:example1::service_B
368 ! (error 127) tools0:example1::state_A
369 \- (ok) tools0:example1::doc_A
372 We could force the group execution to stop using a combination of the
373 \f[CR]\-e\f[R] flag and the \f[CR]error\f[R] group function.
376 service_A() \f[B]{\f[R]
377 service A enable \f[B]&&\f[R]
378 service A restart \f[B]||\f[R]
379 error unable to setup service A
382 service_B() \f[B]{\f[R]
383 service B enable \f[B]&&\f[R]
384 service B restart \f[B]||\f[R]
385 error unable to setup service B
388 state_A() \f[B]{\f[R]
393 echo \[dq]## Service A\[dq]
395 echo \[dq]\- [url](http://test.org/)\[dq]
400 \f[I]\f[BI]file:\f[I] \f[CI]groups/example2\f[I]\f[R]
402 Let\[cq]s run the updated example with the \f[CR]\-s\f[R] flag to
403 trigger the summary output.
407 r7 \-sea group example2 hostname
410 This will produce something like the following:
413 ! (error) tools0:example2::service_A
414 ! (exit) tools0:example2::service_A
415 \- (error 127) \- in tools0 example2 service_A (1748791986)
417 /bin/sh: <stdin>[155]: service: not found
418 :: 1748791986 tools0 ERROR unable to setup service A
420 .SS Cleaning functions
421 To remove a function from a group, we need to ensure that this function
422 returned 0 for the last execution.
425 state_function_to_remove() \f[B]{\f[R]
427 \f[I]# not used anymore\f[R]
432 This would prevent for seeing potential past errors caused by this
433 function in the summary output.
434 .SS Using the r7 install functions
435 The group library comes with the following functions that will allow
436 installation of files and triggering actions if necessary:
437 \f[CR]install\f[R], \f[CR]groupinstall\f[R], \f[CR]nodeinstall\f[R].
438 They are all shortcuts to an internal \f[CR]r7_install\f[R] function,
439 it\[cq]s just the wrappers changes directory to respectively
440 \f[CR]/tmp/r7\f[R], \f[CR]/tmp/r7/groupname.dir/\f[R] and
441 \f[CR]/tmp/r7/hostname/\f[R].
443 If we want to install files from the group directory we will use
447 install_program() \f[B]{\f[R]
448 groupinstall \-m 755 \-o root:bin my_program /usr/local/bin
452 \f[I]We are supposing to have the file
453 \f[CI]groups/example3.dir/my_program\f[I]\f[R]
455 And if it\[cq]s something from node, we should use:
458 install_program_config() \f[B]{\f[R]
459 nodeinstall \-m 644 \-o root:wheel my_config /etc
463 We can now chain the \f[CR]install\f[R] functions to configuration
464 checking and initialization of programs, services or network features
465 like in the following example, in which we install \f[CR]ntp.conf\f[R]
466 from the deployed node directory to \f[CR]/etc\f[R]:
469 service_ntpd() \f[B]{\f[R]
470 nodeinstall \-m 644 \-o root:wheel ntpd.conf /etc \f[B]&&\f[R]
471 ntpd \-n \f[B]&&\f[R]
472 rcctl enable ntpd \f[B]&&\f[R]
476 .SS Using the r7 node function
477 We may want to avoid executing a function or parts of it if the node has
478 no related files before executing the installation and actions handling
480 This can be done with the help of the \f[CR]node\f[R] function.
483 service_ntpd() \f[B]{\f[R]
484 node ntpd.conf \f[B]&&\f[R]
485 nodeinstall \-m 644 \-o root:wheel ntpd.conf /etc \f[B]&&\f[R]
486 ntpd \-n \f[B]&&\f[R]
487 rcctl enable ntpd \f[B]&&\f[R]
492 Here, \f[CR]node\f[R] will return \f[CR]31\f[R] if there is no file or
493 directory called \f[CR]ntpd.conf\f[R] inside the deployed node directory
494 (\f[CR]/tmp/r7/hostname\f[R]).
496 \f[CR]0\f[R], \f[CR]30\f[R] and \f[CR]31\f[R] exit codes are ignored
497 when r7 will search for execution errors.
498 This means \f[CR]30\f[R] and \f[CR]31\f[R] exit code are reserved to r7.
500 In other terms, this will update the NTP daemon configuration only if
501 \f[CR]ntpd.conf\f[R] is present in the node directory, otherwise it is
502 kept by default, which is the system provided default
503 \f[CR]ntpd.conf\f[R].
504 .SS Sourcing specific files
505 Here\[cq]s an example how to source additional shell from the deployed
506 node directory, or elsewhere:
509 service_sysrc() \f[B]{\f[R]
511 sysrc kld_list=\[dq]vmm if_tuntap if_bridge nmdm\[dq]
512 sysrc microcode_update_enable=YES
513 sysrc mountd_enable=YES
514 sysrc nfs_server_enable=YES
515 sysrc ntpdate_enable=YES
516 sysrc powerd_enable=YES
517 sysrc rcshutdown_timeout=900
518 sysrc rpcbind_enable=YES
519 sysrc sshd_enable=YES
521 nodesource sysrc.local
525 In this FreeBSD example, we configure the system RC globally with
526 \f[CR]service_sysrc\f[R] which apply, if \f[CR]sysrc.local\f[R] is found
527 in the root of the node directory, it\[cq]s sourcing in the current
528 scope via the help of \f[CR]nodesource sysrc.local\f[R].
530 The file \f[CR]nodes/hostname/sysrcl.local\f[R] contains the following:
533 sysrc ifconfig_igb0=DHCP
534 sysrc ifconfig_igb1=up
537 Inside the r7 release, a small example groups library can be found in
538 the \f[CR]groups\f[R] directory, that can also be browsed in the \c
539 .UR https://got.inda.re/?action=summary&path=r7.git
543 .SS System shell profile
544 Here we install the \f[CR]profile\f[R] file provided in the
545 \f[CR]groupname.dir\f[R] directory or the profile provided by the node
549 setup_profile() \f[B]{\f[R]
550 groupinstall \-m 644 \-o root:wheel profile /etc
551 node profile \f[B]&&\f[R]
552 nodeinstall \-m 644 \-o root:wheel profile /etc
556 Here we add new users:
559 setup_users() \f[B]{\f[R]
560 useradd user1 2>/dev/null \f[B]||\f[R] :
561 useradd user2 2>/dev/null \f[B]||\f[R] :
565 In the following example, we install a script and call it from a
566 dedicated user crontab.
569 mail_admins=admins\[at]test.org
571 install_myscript() \f[B]{\f[R]
572 groupinstall \-o root:bin \-m 755 myscript /usr/local/bin \f[B]&&\f[R]
573 useradd \-d /var/empty \-s /sbin/nologin _myscript
574 crontab \-u _myscript \- <<\-/
580 .SS Consulting the output
581 After the execution is done, the result are saved in the \f[CR]_run\f[R]
582 directory, \f[CR]output\-dump\f[R] needs to be called to produce the
583 current \f[CR]_output\f[R] structure.
585 The r7 \f[CR]output\f[R] command can then be used to show specific
586 output groups or functions:
592 Will show the whole output of the latest groups deployments.
594 This format can be used to match specific host, group or function:
597 r7 output [hostname [groupname [funcname]]]
603 $ r7 output tools0 OpenBSD state_packages\[rs]*
604 \- tools0 OpenBSD state_packages_upgrades
606 quirks\-7.103 signed on 2025\-05\-30T01:12:03Z
608 \- tools0 OpenBSD state_packages_repository
610 https://cdn.openbsd.org/pub/OpenBSD
613 \f[I]Note that the \f[CI]output\f[I] function arguments are using
614 shell\[cq]s case glob patterns.\f[R]
616 A \f[CR]R7_WORKDIR/.active_nodes\f[R] file is automatically created when
617 r7 tries to connect to a list of hosts via the \f[CR]group\f[R] command
619 This serves as a cache of available hosts reachable via SSH login (the
620 username is specified in the SSH configuration file).
622 To add a previously non\-available host, simply remove the file and use
623 \f[CR]group\f[R] (here via \f[CR]run\-config\f[R]):
630 \f[B]\f[BI]Usage:\f[B]\f[R]
633 r7 [options] [command [arguments...]]
637 \f[B]\-h\f[R] Show usage and exit
639 \f[B]\-d\f[R] Enable debug mode
641 \f[B]\-i\f[R] Specify the SSH identity file
643 \f[B]\-F\f[R] Specify the SSH client configuration file
645 \f[B]\-w\f[R] Set the work directory where \f[CR]./nodes\f[R] and
646 \f[CR]./groups\f[R] can be found
648 \f[B]\-r\f[R] Set the run directory (default: \f[CR]./_run\f[R])
650 \f[B]\-o\f[R] Set the output directory (default: \f[CR]./_output\f[R])
652 \f[B]\-c\f[R] Specify the site configuration file (default:
653 \f[CR]./site\-config\f[R])
655 \f[B]\-n\f[R] Enable dry run mode; prevents any modification on hosts
657 \f[B]\-e\f[R] Exit the group execution on the error function
659 \f[B]\-p\f[R] Run each host in parallel per group call
661 \f[B]\-O\f[R] Show output interactively
663 \f[B]\-P\f[R] Specify a prefix, can contain whole function names
665 \f[B]\-a\f[R] Select all available prefixes for a group command
667 \f[B]\-s\f[R] Apply output\-dump and summary after a group command
680 \f[B]run\-config\f[R]
682 Run the site configuration
687 Deploy specified group to hosts
690 \f[B]output\-dump\f[R]
692 Dump the run directory to the output directory
702 Produce a summary of errors and changes
705 \f[B]digraph\-host\f[R]
707 Produce a dot digraph for hosts
710 \f[B]digraph\-ssh\f[R]
712 Produce a dot digraph of SSH ID\[cq]s, users and nodes relations
717 Import TARGET host in the current nodes directory
722 Default command showing active nodes and summary
727 Initialize a new work directory
734 lw(9.7n) lw(31.4n) lw(29.0n).
762 Group selects all available prefix
769 Enable output\-dump and summary after group execution
776 Enable exit on error function
783 Enable group nodes parallel execution
790 Set the r7 group execution prefix
797 Show interactive output
804 Set the r7 repository path
809 R7_WORKDIR/site\-config
811 Set the r7 \f[CR]site\-config\f[R] path
818 Set the r7 output directory path
825 Set the SSH configuration directory path
830 R7_WORKDIR/.ssh/config
832 Set the SSH configuration file path
837 SSH_CONFIG_DIR/control
839 Set the SSH control dir path
844 R7_WORKDIR/.ssh/id_ed25519_r7
846 Set the SSH identity file
851 R7_WORKDIR/.ssh/known_hosts
853 Set the SSH known hosts file
860 Set the SSH connect timeout
864 Those variables are available during the execution of th group
865 file\[cq]s functions.
884 Current group name being executed
889 Cause the error function to exit if equals \f[CR]yes\f[R]
894 Contains the output of \f[CR]nodename\f[R]
899 Contains the output of \f[CR]nodedir\f[R]
904 Contains the output of \f[CR]groupdir\f[R]
908 Those functions are accessible during the execution of the group
909 file\[cq]s functions.
910 Non documented functions are reserved for internal use.
950 \f[B]\f[BI]Description:\f[B]\f[R] Append a trace containing the current
951 node name and \f[CR]trace_id\f[R]
959 \f[B]\f[BI]Description:\f[B]\f[R] Trace an error message that will
960 inform the user of an event in the summary output, exit the group
961 execution if \f[CR]\-e\f[R] is set
969 \f[B]\f[BI]Description:\f[B]\f[R] Returns true if the argument is an
970 existing file or directory inside \f[CR]/tmp/r7/$(nodename)\f[R], else,
973 \f[B]\f[BI]Usage:\f[B]\f[R]
976 node [filename\f[B]|\f[R]dirname]
979 \f[B]\f[BI]Description:\f[B]\f[R] Returns the small host name of the
982 \f[B]\f[BI]Usage:\f[B]\f[R]
988 \f[B]\f[BI]Description:\f[B]\f[R] Returns \f[CR]/tmp/r7/$(nodename)\f[R]
990 \f[B]\f[BI]Usage:\f[B]\f[R]
996 \f[B]\f[BI]Description:\f[B]\f[R] Returns
997 \f[CR]/tmp/r7/$groupname.dir\f[R]
999 \f[B]\f[BI]Usage:\f[B]\f[R]
1005 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to \f[CR]/tmp/r7\f[R]
1006 and install files if changed and sets mode and owner, returns true if
1007 the file changed, otherwise returns 30
1009 \f[B]\f[BI]Usage:\f[B]\f[R]
1012 install [\-o owner] [\-m mode] source destintaion
1015 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
1016 \f[CR].dir\f[R] directory in \f[CR]/tmp/r7\f[R] then performs like
1019 \f[B]\f[BI]Usage:\f[B]\f[R]
1022 groupinstall [\-o owner] [\-m mode] source destintaion
1025 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current node
1026 directory in \f[CR]/tmp/r7\f[R] then performs like \f[CR]install\f[R]
1028 \f[B]\f[BI]Usage:\f[B]\f[R]
1031 nodeinstall [\-o owner] [\-m mode] source destintaion
1034 \f[B]\f[BI]Description:\f[B]\f[R] Install directory calling
1035 \f[CR]install\f[R] for each file and checking for permissions changes.
1037 \f[B]\f[BI]Usage:\f[B]\f[R]
1040 installdir [\-o fileowner] [\-m filemode] [\-O dirowner] [\-O dirmode] source
1044 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
1045 directory then call installdir
1047 \f[B]\f[BI]Usage:\f[B]\f[R]
1050 groupinstalldir [\-o fileowner] [\-m filemode] [\-O dirowner] [\-O dirmode] source
1054 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
1055 directory then call installdir
1057 \f[B]\f[BI]Usage:\f[B]\f[R]
1060 nodeinstalldir [\-o fileowner] [\-m filemode] [\-O dirowner] [\-O dirmode] source
1064 \f[B]\f[BI]Description:\f[B]\f[R] Source a POSIX shell file in the
1067 \f[B]\f[BI]Usage:\f[B]\f[R]
1073 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
1074 directory then call fsource with the file name as argument, produces an
1075 error if filename is not found from the group directory
1077 \f[B]\f[BI]Usage:\f[B]\f[R]
1080 groupsource filename
1083 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
1084 directory then call node and fsource with the file name as argument
1085 without producing an error if the filename is not found
1087 \f[B]\f[BI]Usage:\f[B]\f[R]
1093 \f[B]\f[BI]Description:\f[B]\f[R] Template the files passed as arguments
1094 with the current environment or by sourcing a specified file
1096 \f[B]\f[BI]Usage:\f[B]\f[R]
1099 template [\-s sourcefile] [file...]
1102 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
1103 directory before calling template
1105 \f[B]\f[BI]Usage:\f[B]\f[R]
1108 grouptemplate [\-s sourcefile] [file...]
1111 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current node
1112 directory before calling template
1114 \f[B]\f[BI]Usage:\f[B]\f[R]
1117 nodetemplate [\-s sourcefile] [file...]
1120 Usable from the r7 \f[CR]site\-config\f[R] file or sourced in the
1121 current shell using:
1124 \&. $(command \-v r7)
1127 Each functions are declared with underscore names and aliased with
1129 Shorter aliases are also available, list all declared aliases with:
1135 Non documented functions are reserved for internal use.
1144 \f[B]\f[BI]Description:\f[B]\f[R] Default command showing active nodes
1145 and summary, ran when sourced
1147 \f[B]\f[BI]Usage:\f[B]\f[R]
1153 \f[B]\f[BI]Description:\f[B]\f[R] Shows the command line help
1155 \f[B]\f[BI]Usage:\f[B]\f[R]
1172 ssh\-authorized\-keys\-reset
1176 ssh\-control\-master\-clean
1182 ssh\-authorized\-keys
1188 \f[B]\f[BI]Description:\f[B]\f[R] Resets the SSH agent environment and
1189 issues ssh\-add for SSH_IDENTITY_FILE
1191 \f[B]\f[BI]Usage:\f[B]\f[R]
1197 \f[B]\f[BI]Description:\f[B]\f[R] r7 openrsync, rsync, scp wrapper;
1198 selected in order of availability
1200 \f[B]\f[BI]Usage:\f[B]\f[R]
1206 \f[B]\f[BI]Description:\f[B]\f[R] r7 SSH wrapper; behaves like the
1207 standard OpenSSH command
1209 \f[B]\f[BI]Usage:\f[B]\f[R]
1215 \f[B]\f[BI]Description:\f[B]\f[R] r7 SSH with debug connection mode for
1218 \f[B]\f[BI]Usage:\f[B]\f[R]
1223 .SS ssh\-known\-hosts
1224 \f[B]\f[BI]Description:\f[B]\f[R] Calls ssh\-keygen to dump the SSH
1227 \f[B]\f[BI]Usage:\f[B]\f[R]
1232 .SS ssh\-authorized\-keys\-reset
1233 \f[B]\f[BI]Description:\f[B]\f[R] Resets SSH authorized_keys on the
1236 \f[B]\f[BI]Usage:\f[B]\f[R]
1239 ssh\-authorized\-keys\-reset HOST
1241 .SS ssh\-accept\-new
1242 \f[B]\f[BI]Description:\f[B]\f[R] Adds a new host entry in the SSH
1245 \f[B]\f[BI]Usage:\f[B]\f[R]
1248 ssh\-accept\-new HOST
1250 .SS ssh\-control\-master\-clean
1251 \f[B]\f[BI]Description:\f[B]\f[R] Cleans the SSH control master
1254 \f[B]\f[BI]Usage:\f[B]\f[R]
1257 ssh\-control\-master\-clean
1260 \f[B]\f[BI]Description:\f[B]\f[R] Searches nodes for authorized_keys_*
1261 and returns a list of users
1263 \f[B]\f[BI]Usage:\f[B]\f[R]
1269 \f[B]\f[BI]Description:\f[B]\f[R] Returns sorted SSH IDs
1271 \f[B]\f[BI]Usage:\f[B]\f[R]
1276 .SS ssh\-authorized\-keys
1277 \f[B]\f[BI]Description:\f[B]\f[R] Returns the list of authorized_keys
1280 \f[B]\f[BI]Usage:\f[B]\f[R]
1283 ssh\-authorized\-keys
1286 \f[B]\f[BI]Description:\f[B]\f[R] Returns SSH IDs along with matching
1287 key file and host name
1289 \f[B]\f[BI]Usage:\f[B]\f[R]
1294 .SS Deployment functions
1308 group\-functions\-all
1314 \f[B]\f[BI]Description:\f[B]\f[R] Returns a list of available nodes
1316 \f[B]\f[BI]Usage:\f[B]\f[R]
1322 \f[B]\f[BI]Description:\f[B]\f[R] Returns a list of active nodes by
1323 detecting SSH availability (a login is done), writes
1324 \f[CR]R7_WORKDIR/.active_nodes\f[R] containing the available hosts
1326 \f[B]\f[BI]Usage:\f[B]\f[R]
1332 \f[B]\f[BI]Description:\f[B]\f[R] Executes \f[CR]R7_SITE_CONFIG\f[R] in
1333 the loaded environment
1335 \f[B]\f[BI]Usage:\f[B]\f[R]
1341 \f[B]\f[BI]Description:\f[B]\f[R] Returns a list of active nodes
1342 matching a list of grep REGEXES
1344 \f[B]\f[BI]Usage:\f[B]\f[R]
1350 \f[B]\f[BI]Description:\f[B]\f[R] Applies GROUPNAME functions (in prefix
1351 order) to the provided MEMBERS list
1353 \f[B]\f[BI]Usage:\f[B]\f[R]
1356 group GROUPNAME MEMBERS
1358 .SS group\-functions
1359 \f[B]\f[BI]Description:\f[B]\f[R] Returns a list of functions found in
1360 the specified GROUPNAME
1362 \f[B]\f[BI]Usage:\f[B]\f[R]
1365 group\-functions GROUPNAME
1367 .SS group\-functions\-all
1368 \f[B]\f[BI]Description:\f[B]\f[R] Returns a list of all group functions
1369 found in the current \f[CR]R7_WORKDIR/groups\f[R] directory with the
1370 \f[CR]group_name::function_name\f[R] format
1372 \f[B]\f[BI]Usage:\f[B]\f[R]
1375 group\-functions\-all
1378 \f[B]\f[BI]Description:\f[B]\f[R] Sets the current PREFIX for matching
1379 function names, can match for the whole unique name in the group, for
1380 executing one specified function only
1382 \f[B]\f[BI]Usage:\f[B]\f[R]
1387 .SS Text output functions
1411 \f[B]\f[BI]Description:\f[B]\f[R] Dumps R7_RUNDIR to R7_OUTPUTDIR
1413 \f[B]\f[BI]Usage:\f[B]\f[R]
1419 \f[B]\f[BI]Description:\f[B]\f[R] Returns a list of outputs from the
1422 \f[B]\f[BI]Usage:\f[B]\f[R]
1428 \f[B]\f[BI]Description:\f[B]\f[R] Returns a list of current dumped
1429 functions exit status codes
1431 \f[B]\f[BI]Usage:\f[B]\f[R]
1436 .SS output\-duration
1437 \f[B]\f[BI]Description:\f[B]\f[R] Returns a list of durations of
1440 \f[B]\f[BI]Usage:\f[B]\f[R]
1446 \f[B]\f[BI]Description:\f[B]\f[R] Shows the dumped output matching HOST,
1447 GROUPNAME, and FUNCTION (or any if unspecified)
1449 \f[B]\f[BI]Usage:\f[B]\f[R]
1452 output HOST GROUPNAME FUNCTION
1455 \f[B]\f[BI]Description:\f[B]\f[R] Returns the latest execution trace_id
1457 \f[B]\f[BI]Usage:\f[B]\f[R]
1463 \f[B]\f[BI]Description:\f[B]\f[R] Returns the diffs from the latest
1466 \f[B]\f[BI]Usage:\f[B]\f[R]
1471 .SS output\-permissions
1472 \f[B]\f[BI]Description:\f[B]\f[R] Returns the latest permission changes
1474 \f[B]\f[BI]Usage:\f[B]\f[R]
1480 \f[B]\f[BI]Description:\f[B]\f[R] Returns the latest errors detected
1482 \f[B]\f[BI]Usage:\f[B]\f[R]
1488 \f[B]\f[BI]Description:\f[B]\f[R] Produces a summary of errors, diffs,
1489 and permission outputs
1491 \f[B]\f[BI]Usage:\f[B]\f[R]
1500 digraph\-ssh\-id\-hosts
1504 \f[B]\f[BI]Description:\f[B]\f[R] Returns a directed graph (in DOT
1505 format) showing relations among groups, functions, and nodes
1507 \f[B]\f[BI]Usage:\f[B]\f[R]
1512 .SS digraph\-ssh\-id\-hosts
1513 \f[B]\f[BI]Description:\f[B]\f[R] Returns a directed graph (in DOT
1514 format) of relations between SSH IDs and hosts
1516 \f[B]\f[BI]Usage:\f[B]\f[R]
1519 digraph\-ssh\-id\-hosts
1525 \f[B]\f[BI]Description:\f[B]\f[R] Retunrs a report page with the content
1526 of \f[CR]README.md\f[R] in HTML format
1528 \f[B]\f[BI]Usage:\f[B]\f[R]
1539 \f[B]\f[BI]Description:\f[B]\f[R] Import configuration files from a
1542 \f[B]\f[BI]Usage:\f[B]\f[R]
1551 Supported shells are ksh93, oksh, yash and bash
1553 Supported target platforms are POSIX compatible systems
1556 \f[CR]/bin/sh\f[R] or compatible must be set for the user\[cq]s shell
1557 (which is usually the case by default)
1559 \f[CR]/tmp\f[R] must be writable by the user
1562 Supported control node platforms are supposed to be POSIX compatible
1563 systems but currently limited to BSD\[cq]s, Darwin and GNU/Linux
1566 Dependencies are awk, OpenSSH and column
1568 Optional dependencies are openrsync, rsync, column, graphviz and pandoc
1571 The r7 importer supports the following platforms:
1613 The provided group library is shared as additional examples WITH NO
1614 WARRANTIES of the documentation and contain the following third\-party
1615 files under the ISC License.
1616 Copyright information are indicated in the LICENSE section of related
1619 \f[CR]pf\-badhost.sh\f[R]
1621 \f[CR]unbound\-adblock.sh\f[R]
1623 \f[CR]http\-ban.sh\f[R]
1625 The project is shared under the terms of the ISC license.
1626 Any version previous \f[CR]0.1.0\f[R] needs to be considered obsolete
1627 and should not be redistributed.
1628 History in the GIT repository is kept for transparency purpose only.
1630 Below is a copy of the applicable license:
1635 Copyright 2025 xs <xs\[at]inda.re>
1637 Permission to use, copy, modify, and/or distribute this software for any
1638 purpose with or without fee is hereby granted, provided that the above
1639 copyright notice and this permission notice appear in all copies.
1641 THE SOFTWARE IS PROVIDED \[dq]AS IS\[dq] AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1642 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
1643 FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1644 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1645 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1646 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1647 PERFORMANCE OF THIS SOFTWARE.