Blob


1 ## Tutorial
3 ### Introduction
5 R7 is a configuration management framework made to configure nodes with
6 configuration files and related operations versionned in a central repository.
7 To remain code versionning system agnostic, manual or automated versionning is
8 left to the user, via makefiles or triggered from r7 `site-config` configuration
9 file _(See below)_.
11 The idea is to store hosts configurations in `nodes/hostname` directories that
12 maps each host's `/etc` and to assign those hosts to configuration groups
13 containing the directives to install the configuration and potential
14 requirements.
16 _Nodes sub-directories are hostnames understood by the ssh client and
17 configuration._
19 _Currently, r7 requires valid ssh configuration and keyfiles in the repository
20 `.ssh/` directory._
22 _Repositories can be initialized with `rset init` or `rset -w
23 path/to/new-repository init`, the user will then have to provide valid
24 configurations and keys for `.ssh/` in the newly created directory._
26 _See [Technical Notes](#technical-notes) for dependencies and supported
27 platforms._
29 There is an example of r7 repository:
31 ./nodes/
32 ./nodes/hostA
33 ./nodes/hostB
34 ./nodes/hostC
35 ./groups/
36 ./groups/common
37 ./groups/test0
38 ./groups/common.dir
39 ./groups/test0.dir
40 ./.ssh/
41 ./.ssh/config
42 ./.ssh/id_ed25519_r7
43 ./.ssh/id_ed25519_r7.pub
44 ./site-config
46 There is an example of r7 site configuration (`site-config` file):
48 ```sh
49 prefix install state doc
50 group common '.*'
51 group test0 hostB hostC
52 output-dump
53 summary
54 ```
56 There is an exemple of the deployment of that configuration within the r7
57 repository:
59 ```
60 $ r7 run-config
61 - (ok) hostA:common::install_nothing
62 - (ok) hostA:common::state_uname
63 - (ok) hostA:common::doc_tutorial
64 - (ok) hostB:common::install_nothing
65 - (ok) hostB:common::state_uname
66 - (ok) hostB:common::doc_tutorial
67 - (ok) hostC:common::install_nothing
68 - (ok) hostC:common::state_uname
69 - (ok) hostC:common::doc_tutorial
70 - (ok) hostB:test0::state_test
71 - (ok) hostC:test0::state_test
72 ```
74 In this example, everything goes fine, groups are executed on each related
75 nodes, note the `'.*'` matching all hosts present in `./nodes`. Groups are POSIX
76 shell scripts that are a collection of functions.
78 There is the `common` group:
80 ```sh
81 install_nothing() {
82 echo Nothing installed
83 }
85 state_uname() {
86 uname -a
87 }
89 doc_tutorial() {
90 echo "## Welcome to the R7 tutorial!"
91 }
92 ```
94 And there is the `test0` group:
96 ```sh
97 state_test() {
98 test 1 -eq 1
99 }
100 ```
102 Any function managed by `r7` needs to be declared in the format `^PREFIX_NAME()`.
104 Group files names can't contain spaces, tabs or newlines, as well for nodes
105 dirnames. _The ':' character is not recommanded as well as it may reduce
106 lisibility of the interactive output._
108 Called groups and node directories are copied to related nodes in `hostname:/tmp/r7/`:
110 /tmp/r7/hostA/ # Contents of test.org/nodes/hostA/
111 /tmp/r7/common.dir # Contents of test.org/groups/common.dir/
112 /tmp/r7/test.dir # Contents of test.org/groups/test.dir
114 Groups may have no `.dir` directory, in this case, nothing is copied.
116 Once the group copy is done, functions are executed in the order of the defined
117 prefix (part of the `site-config` file shown before):
119 prefix install state doc
121 This means the functions matching `^install_.*()`, `^state_.*()` and `^doc_.*()`
122 (the default `R7_PREFIX`) in the respective declaration order they're found in the
123 related group file will be executed.
125 Site confiurations are shell scripts sourced by r7 after it's environment is
126 initialized, so `prefix`, `group`, `output-dump`, `summary` are the functions or
127 aliases provided by r7 itself. This allow for scripting from the `site-config`
128 file. Here `output-dump`, and `summary` are called to output potential errors,
129 diffs and permissions changes at the end of the interactive output obtained by
130 `r7 run-config`. If nothing catched happened, nothing is added to the output.
132 ### Errors during remote execution of groups
134 In our previous example, we modify `state_test` so the `test` fails.
136 ```sh
137 state_test() {
138 test 1 -eq 2
140 ```
142 And we re-run the configuration to see what's happenning.
144 ```
145 $ r7 run-config
146 - (ok) hostA:common::install_nothing
147 - (ok) hostA:common::state_uname
148 - (ok) hostA:common::doc_tutorial
149 - (ok) hostB:common::install_nothing
150 - (ok) hostB:common::state_uname
151 - (ok) hostB:common::doc_tutorial
152 - (ok) hostC:common::install_nothing
153 - (ok) hostC:common::state_uname
154 - (ok) hostC:common::doc_tutorial
155 - (error 1) hostB:test0::state_test
156 - (error 1) hostC:test0::state_test
157 - (error 1) - in hostB test0 state_test (1748622980)
158 - (error 1) - in hostC test0 state_test (1748622980)
159 ```
162 The last two lines are part of the `summary` output.
164 Let's modify the `state_test` function again to add some verbosity to it's
165 output.
167 _Note that we also change the return value._
169 ```sh
170 state_test() {
171 echo something
172 false || {
173 echo >&2 failed
174 return 22
177 ```
179 This will produce the following summary:
181 ```
182 - (error 22) - in hostB test0 state_test (1748622980)
184 something
185 failed
187 - (error 22) - in hostC test0 state_test (1748622980)
189 something
190 failed
191 ```
193 Diffs and permissions changes are also displayed by the `summary` command. When
194 they're are detected, the captured related output is shown.
196 ### Repository initialisation
198 Using the `init` command, we can specify the current or a specifed
199 work directory to be created and act as an r7 repository.
201 _Automated versionning of outputs are currently let to the user, a recommended
202 place would be the end of the site configuration file._
204 This command initializes a new directory called `test.org`:
206 ```sh
207 r7 -w test.org init
208 cd test.org
209 ```
211 Once this step is done, it is required to:
213 - Copy or initialize the ssh key to the `.ssh` folder in the repository created
214 in `.ssh/id_ed25519-r7` and `./ssh/id_ed25519-r7.pub`
216 - Adjust the SSH client configuration file in the repository `.ssh/config`
218 _Note that it is possible to import additionnal SSH configurations, like the user
219 one from the SSH configuration, but it is advised to keep them separate._
221 ### SSH agent handling
223 The function `unlock` can be used to set the SSH agent environement, this will
224 be required for any automated operation later done by r7:
226 ```sh
227 cd test.org
228 . $(command -v r7) # Sourcing r7
229 unlock
230 tmux || screen
231 ```
233 _***Warning:*** Unlock will terminate any running `ssh-agent` instances._
235 ### Adding new hosts
237 For adding a new host, the simplest way is to have pre-configured
238 `authorized_keys` for the target user, it is then required to add it to the
239 `known_hosts` file. For that, it is possible to use r7 SSH functions:
241 ```sh
242 . $(command -v r7) # Sourcing r7
243 ssh-accept-new hostname
245 ```
247 If resetting the target's user `authorized_keys` file is needed, the following
248 function can be used:
250 ```sh
251 . $(command -v r7) # Sourcing r7
252 ssh-authorized-keys-reset hostname
253 ```
255 _**Warning:** This will resets the SSH authorized_keys file for the target user
256 (root, by default) and put the `.ssh/id_ed25519-r7.pub` in place._
259 Once the host is accepted in the `known_hosts` file, it's possible to import it
260 automatically.
262 ### Importing hosts configurations
264 _This feature currently only support OpenBSD._
266 Avoiding to import the configuration manually is possible with the `import`
267 command:
269 ```sh
270 r7 import hostname
271 ```
273 Most common configuration files will be copied in a newly created
274 `nodes/hostname` sub-directory.
276 ### Writing group files
278 Group files collects fonctions related to the configuration of the operating
279 system, networking, services, global and user configurations packages
280 installations and application deployments.
282 By specifying the execution prefix, the user determines the order of execution
283 of the functions declared in the group file.
285 ```sh
286 service_A() {
287 service A enable
288 service A restart
291 service_B() {
292 service B enable
293 service B restart
296 state_A() {
297 service A status
300 doc_A() {
301 echo "## Service A"
302 echo
303 echo "- [url](http://test.org/)"
304 echo
306 ```
308 _**file**: `groups/example1`_
310 With the default prefix, `install`, `state`, `doc`, the fonction that will be
311 executed are `state_A` and `doc_A`. To test that group file with all the
312 functions inside we can call r7 the following way:
314 ```sh
315 r7 -P 'service state doc' group example1 hostname
316 ```
318 Or using the `-a` flag which will create a prefix automatically with all
319 functions present in the group file:
321 ```sh
322 r7 -a group example1 hostname
323 ```
325 In a real situation, this example will have failing functions because the
326 `service` command may not be found or the services named `A` or `B` does not
327 exist.
329 ```
330 ! (error 127) tools0:example1::service_A
331 ! (error 127) tools0:example1::service_B
332 ! (error 127) tools0:example1::state_A
333 - (ok) tools0:example1::doc_A
334 ```
336 We could force the group execution to stop using a combination of the `-e` flag
337 and the `error` group function.
339 ```sh
340 service_A() {
341 service A enable &&
342 service A restart ||
343 error unable to setup service A
346 service_B() {
347 service B enable &&
348 service B restart ||
349 error unable to setup service B
352 state_A() {
353 service A status
356 doc_A() {
357 echo "## Service A"
358 echo
359 echo "- [url](http://test.org/)"
360 echo
362 ```
364 _**file:** `groups/example2`_
366 Let's run the updated example with the `-s` flag to trigger the summary output.
368 ```sh
369 rm -fr _output
370 r7 -sea group example2 hostname
371 ```
373 This will produce something like the following:
375 ```
376 ! (error) tools0:example2::service_A
377 ! (exit) tools0:example2::service_A
378 - (error 127) - in tools0 example2 service_A (1748791986)
380 /bin/sh: <stdin>[155]: service: not found
381 :: 1748791986 tools0 ERROR unable to setup service A
383 ```
385 ### Using the r7 install functions
387 The group library comes with the following functions that will allow
388 installation of files and triggering actions if necessary: `install`,
389 `groupinstall`, `nodeinstall`. They are all shortcuts to an internal
390 `r7_install` function, it's just the wrappers changes directory to respectively
391 `/tmp/r7`, `/tmp/r7/groupname.dir/` and `/tmp/r7/hostname/`.
393 If we want to install files from the group directory we will use something like:
396 ```sh
397 install_program() {
398 groupinstall -m 755 -o root:bin my_program /usr/local/bin
400 ```
402 _We are supposing to have the file `groups/example3.dir/my_program`_
404 And if it's something from node, we should use:
406 ```sh
407 install_program_config() {
408 nodeinstall -m 644 -o root:wheel my_config /etc
410 ```
412 We can now chain the `install` functions to configuration checking and
413 initialization of programs, services or network features like in the following
414 example, in which we install `ntp.conf` from the deployed node directory to
415 `/etc`:
417 ```sh
418 service_ntpd() {
419 nodeinstall -m 644 -o root:wheel ntpd.conf /etc &&
420 ntpd -n &&
421 rcctl enable ntpd &&
422 rcctl restart ntpd
424 ```
426 ### Using the r7 node function
428 We may want to avoid executing a function or parts of it if the node has no
429 related files before executing the installation and actions handling parts. This
430 can be done with the help of the `node` function.
432 ```sh
433 service_ntpd() {
434 node ntpd.conf &&
435 nodeinstall -m 644 -o root:wheel ntpd.conf /etc &&
436 ntpd -n &&
437 rcctl enable ntpd &&
438 rcctl restart ntpd
440 ```
442 Here, `node` will return `31` if there is no file or directory called
443 `ntpd.conf` inside the deployed node directory (`/tmp/r7/hostname`).
445 `0`, `30` and `31` exit codes are ignored when r7 will search for execution
446 errors. This means `30` and `31` exit code are reserved to r7.
448 In other terms, this will update the NTP daemon configuration only if
449 `ntpd.conf` is present in the node directory, otherwise it is kept by default,
450 which is the system provided default `ntpd.conf`.
452 ### Sourcing specific files
454 Here's an example how to source additionnal shell from the deployed node
455 directory, or elsewhere:
457 ```sh
458 service_sysrc() {
459 sysrc dumpdev=NO
460 sysrc kld_list="vmm if_tuntap if_bridge nmdm"
461 sysrc microcode_update_enable=YES
462 sysrc mountd_enable=YES
463 sysrc nfs_server_enable=YES
464 sysrc ntpdate_enable=YES
465 sysrc powerd_enable=YES
466 sysrc rcshutdown_timeout=900
467 sysrc rpcbind_enable=YES
468 sysrc sshd_enable=YES
469 sysrc zfs_enable=YES
470 nodesource sysrc.local
473 ```
475 In this FreeBSD example, we configure the system RC globally with
476 `service_sysrc` which apply, if `sysrc.local` is found in the root of the node
477 directory, it's sourcing in the current scope via the help of `nodesource
478 sysrc.local`.
480 The file `nodes/hostname/sysrcl.local` contains the following:
482 ```sh
483 sysrc ifconfig_igb0=DHCP
484 sysrc ifconfig_igb1=up
485 ```
487 ### Other examples
489 Inside the r7 release, a small example groups library can be found in the
490 `groups` directory, that can also be browsed in the
491 [repository](https://got.inda.re/?action=summary&path=r7.git).
493 #### System shell profile
495 Here we install the `profile` file provided in the `groupname.dir` directory or
496 the profile provided by the node directory:
498 ```sh
499 setup_profile() {
500 groupinstall -m 644 -o root:wheel profile /etc
501 node profile &&
502 nodeinstall -m 644 -o root:wheel profile /etc
504 ```
506 #### Users
508 Here we add new users:
510 ```sh
511 setup_users() {
512 useradd user1 2>/dev/null || :
513 useradd user2 2>/dev/null || :
515 ```
517 #### Crontab
519 In the following example, we install a script and call it from a dedicated user crontab.
521 ```sh
522 mail_admins=admins@test.org
524 install_myscript() {
525 groupinstall -o root:bin -m 755 myscript /usr/local/bin &&
526 useradd -d /var/empty -s /sbin/nologin _myscript
527 crontab -u _myscript - <<-/
528 MAILTO=$mail_admins
529 */5 * * * * myscript
532 ```
534 ### Consulting the output
536 After the execution is done, the result are saved in the `_run` directory,
537 `output-dump` needs to be called to produce the current `_output` structure.
539 The r7 `output` command can then be used to show specific output groups or functions:
541 ```sh
542 r7 output
543 ```
545 Will show the whole output of the latest groups deployments.
547 This format can be used to match specific host, group or function:
549 ```sh
550 r7 output [hostname [groupname [funcname]]]
551 ```
553 For example:
555 ```sh
556 $ r7 output tools0 OpenBSD state_packages\*
557 - tools0 OpenBSD state_packages_upgrades
559 quirks-7.103 signed on 2025-05-30T01:12:03Z
561 - tools0 OpenBSD state_packages_repository
563 https://cdn.openbsd.org/pub/OpenBSD
564 ```
566 _Note that the `output` function arguments are using shell's case globbing patterns._
568 ## r7 command line
570 ***Usage:***
571 ```sh
572 r7 [options] [command [arguments...]]
573 ```
575 ### Options
577 - **-h**
578 Show usage and exit
580 - **-d**
581 Enable debug mode
583 - **-i**
584 Specify the SSH identity file
586 - **-F**
587 Specify the SSH client configuration file
589 - **-w**
590 Set the work directory where `./nodes` and `./groups` can be found
592 - **-r**
593 Set the run directory (default: `./_run`)
595 - **-o**
596 Set the output directory (default: `./_output`)
598 - **-c**
599 Specify the site configuration file (default: `./site-config`)
601 - **-n**
602 Enable dry run mode; prevents any modification on hosts
604 - **-e**
605 Exit the group execution on the error function
607 - **-p**
608 Run each host in parallel per group call
610 - **-O**
611 Show output interactively
613 - **-P**
614 Specify a prefix
616 - **-a**
617 Select all available prefixes for a group command
619 - **-s**
620 Apply output-dump and summary after a group command
622 ### Commands
624 | Name | Description |
625 | ---- | ----------- |
626 | **run-config** | Run the site configuration |
627 | **group** | Deploy specified group to hosts |
628 | **output-dump** | Dump the run directory to the output directory |
629 | **output** | Consult the output |
630 | **summary** | Produce a summary of errors and changes |
631 | **digraph-host** | Produce a dot digraph for hosts |
632 | **digraph-ssh** | Produce a dot digraph of SSH ID's, users and nodes relations |
633 | **import** | Import TARGET host in the current nodes directory |
634 | **info** | Default command showing active nodes and summary |
635 | **init** | Initialize a new work directory |
637 ## Environment
639 | Name | Default value | Description |
640 | ---- | ------------- | ------------|
641 | R7_DEBUG | no | Enable debug mode |
642 | R7_DRYRUN | no | Enable dry-run mode |
643 | R7_GROUP_ALLPREFIX | no | Group selects all available prefix |
644 | R7_GROUP_SUMMARY | no | Enable output-dump and summary after group execution |
645 | R7_GROUP_EXITONERROR | no | Enable exit on error function |
646 | R7_PARALLEL | no | Enable group nodes parallel execution |
647 | R7_PREFIX | install state doc | Set the r7 group execution prefix |
648 | R7_SHOWOUTPUT | no | Show interactive output |
649 | R7_WORKDIR | PWD | Set the r7 repository path |
650 | R7_SITE_CONFIG | R7_WORKDIR/site-config | Set the r7 `site-config` path |
651 | R7_OUTPUTDIR | R7_WORKDIR/_output | Set the r7 output directory path |
652 | SSH_CONFIG_DIR | R7_WORKDIR/.ssh | Set the SSH configuration directory path |
653 | SSH_CONFIG_FILE | R7_WORKDIR/.ssh/config | Set the SSH configuration file path |
654 | SSH_CONTROL_DIR | SSH_CONFIG_DIR/control | Set the SSH control dir path |
655 | SSH_IDENTITY_FILE | R7_WORKDIR/.ssh/id_ed25519_r7 | Set the SSH identity file |
656 | SSH_KNOWN_HOSTS | R7_WORKDIR/.ssh/known_hosts | Set the SSH known hosts file |
657 | SSH_CONNECT_TIMEOUT | 3 | Set the SSH connect timeout |
660 ## Group variables
662 Those variables are available during the execution of th group file's functions.
664 | Name | Description |
665 | ---- | ----------- |
666 | trace_id | Current run trace ID |
667 | groupname | Current group name being executed |
668 | exitonerror | Cause the error function to exit if equals `yes` |
669 | nodename | Contains the output of `nodename` |
670 | nodedir | Contains the output of `nodedir` |
671 | groupdir | Contains the output of `groupdir` |
674 ## Group functions
676 Those functions are accessible during the execution of the group file's functions.
677 Non documented functions are reserved for internal use.
679 1. [trace](#trace)
680 2. [error](#error)
681 3. [node](#node)
682 4. [nodename](#nodename)
683 5. [nodedir](#nodedir)
684 6. [groupdir](#groupdir)
685 7. [install](#install)
686 8. [groupinstall](#groupinstall)
687 9. [nodeinstall](#nodeinstall)
688 10. [installdir](#installdir)
689 11. [groupinstalldir](#groupinstalldir)
690 12. [nodeinstalldir](#nodeinstalldir)
691 13. [source](#source)
692 14. [groupsource](#groupsource)
693 15. [nodesource](#groupsource)
695 ---
697 ### trace
699 ***Description:***
700 Append a trace containing the current node name and `trace_id`
702 **Usage:**
703 ```sh
704 trace [string...]
705 ```
707 ### error
709 ***Description:***
710 Trace an error message that will inform the user of an event in the summary
711 output, exit the group execution if `-e` is set
713 **Usage:**
714 ```sh
715 error [string...]
716 ```
718 ### node
720 ***Description:***
721 Returns true if the argument is an existing file or directory inside `/tmp/r7/$(nodename)`, else, returns 31
723 ***Usage:***
724 ```sh
725 node [filename|dirname]
726 ```
728 ### nodename
730 ***Description:***
731 Returns the small hostname of the current host
733 ***Usage:***
734 ```sh
735 nodename
736 ```
738 ### nodedir
740 ***Description:***
741 Returns `/tmp/r7/$(nodename)`
743 ***Usage:***
744 ```sh
745 nodename
746 ```
748 ### groupdir
750 ***Description:***
751 Returns `/tmp/r7/$groupname.dir`
753 ***Usage:***
754 ```sh
755 groupdir
756 ```
758 ### install
760 ***Description:***
761 Change directory to `/tmp/r7` and install files if changed and sets mode and
762 owner, returns true if the file changed, otherwise returns 30
764 ***Usage:***
765 ```sh
766 install [-o owner] [-m mode] source destintaion
767 ```
769 ### groupinstall
771 ***Description:***
772 Change directory to the current group `.dir` directory in `/tmp/r7` then
773 performs like `install`
775 ***Usage:***
776 ```sh
777 groupinstall [-o owner] [-m mode] source destintaion
778 ```
780 ### nodeinstall
782 ***Description:***
783 Change directory to the current node directory in `/tmp/r7` then
784 performs like `install`
786 ***Usage:***
787 ```sh
788 nodeinstall [-o owner] [-m mode] source destintaion
789 ```
791 ### installdir
793 ***Description:***
794 Install directory calling `install` for each file and checking for permissions
795 changes.
797 ***Usage:***
798 ```sh
799 installdir [-o fileowner] [-m filemode] [-O dirowner] [-O dirmode] source
800 destination
801 ```
803 ### groupinstalldir
805 ***Description:***
806 Change directory to the current group directoy then call installdir
808 ***Usage:***
809 ```sh
810 groupinstalldir [-o fileowner] [-m filemode] [-O dirowner] [-O dirmode] source
811 destination
812 ```
814 ### nodeinstalldir
816 ***Description:***
817 Change directory to the current group directoy then call installdir
819 ***Usage:***
820 ```sh
821 nodeinstalldir [-o fileowner] [-m filemode] [-O dirowner] [-O dirmode] source
822 destination
823 ```
825 ### source
827 ***Description:***
828 Source a POSIX shell file in the current execution
830 ***Usage:***
832 ```sh
833 source filename
834 ```
836 ### groupsource
838 ***Description:***
839 Change directory to the current group directory then call source with the file
840 name as argument, produces an error if filename is not found from the group
841 directory
843 ```sh
844 groupsource filename
845 ```
847 ### nodesource
849 ***Description:***
850 Change directory to the current group directory then call node and source with the file
851 name as argument without producing an error if the filename is not found
853 ```sh
854 nodesource filename
855 ```
857 # r7 library
859 Usable from the r7 `site-config` file or sourced in the current shell using:
861 ```sh
862 . $(command -v r7)
863 ```
865 Each functions are declared with underscore names and aliased with dashes.
866 Shorter aliases are also available, list all declared aliases with:
868 ```sh
869 alias
870 ```
872 Non documented functions are reserved for internal use.
874 ## Interface
876 1. [info](#info)
877 2. [usage](#usage)
879 ---
881 ### info
883 ***Description:***
884 Default command showing active nodes and summary, ran when sourced
886 ***Usage:***
887 ```sh
888 info
889 ```
891 ### usage
893 ***Description:***
894 Shows the command line help
896 ***Usage:***
897 ```sh
898 usage
899 ```
901 ## SSH functions
903 1. [unlock](#unlock)
904 2. [copy](#copy)
905 3. [ssh](#ssh)
906 4. [ssh-debug](#ssh-debug)
907 5. [ssh-known-hosts](#ssh-known-hosts)
908 6. [ssh-authorized-keys-reset](#ssh-authorized-keys-reset)
909 7. [ssh-accept-new](#ssh-accept-new)
910 8. [ssh-control-master-clean](#ssh-control-master-clean)
911 9. [ssh-users](#ssh-users)
912 10. [ssh-ids](#ssh-ids)
913 11. [ssh-authorized-keys](#ssh-authorized-keys)
914 12. [ssh-ids-hosts](#ssh-ids-hosts)
916 ---
918 ### unlock
920 ***Description:***
921 Resets the SSH agent environment and issues ssh-add for SSH_IDENTITY_FILE
923 ***Usage:***
924 ```sh
925 unlock
926 ```
928 ### copy
930 ***Description:***
931 r7 openrsync, rsync, scp wrapper; selected in order of availability
933 ***Usage:***
934 ```sh
935 copy SRC DST
936 ```
938 ### ssh
940 ***Description:***
941 r7 SSH wrapper; behaves like the standard OpenSSH command
943 ***Usage:***
944 ```sh
945 ssh OPTION HOST
946 ```
948 ### ssh-debug
950 ***Description:***
951 r7 SSH with debug connection mode for a specific HOST
953 ***Usage:***
954 ```sh
955 ssh-debug HOST
956 ```
958 ### ssh-known-hosts
960 ***Description:***
961 Calls ssh-keygen to dump the SSH known_hosts file
963 ***Usage:***
964 ```sh
965 ssh-known-hosts
966 ```
968 ### ssh-authorized-keys-reset
970 ***Description:***
971 Resets SSH authorized_keys on the specified HOST
973 ***Usage:***
974 ```sh
975 ssh-authorized-keys-reset HOST
976 ```
978 ### ssh-accept-new
980 ***Description:***
981 Adds a new host entry in the SSH known_hosts file
983 ***Usage:***
984 ```sh
985 ssh-accept-new HOST
986 ```
988 ### ssh-control-master-clean
990 ***Description:***
991 Cleans the SSH control master directory
993 ***Usage:***
994 ```sh
995 ssh-control-master-clean
996 ```
998 ### ssh-users
1000 ***Description:***
1001 Searches nodes for authorized_keys_* and returns a list of users
1003 ***Usage:***
1004 ```sh
1005 ssh-users
1006 ```
1008 ### ssh-ids
1010 ***Description:***
1011 Returns sorted SSH IDs
1013 ***Usage:***
1014 ```sh
1015 ssh-ids
1016 ```
1018 ### ssh-authorized-keys
1020 ***Description:***
1021 Returns the list of authorized_keys from nodes
1023 ***Usage:***
1024 ```sh
1025 ssh-authorized-keys
1026 ```
1028 ### ssh-ids-hosts
1030 ***Description:***
1031 Returns SSH IDs along with matching keyfile and hostname
1033 ***Usage:***
1034 ```sh
1035 ssh-ids-hosts
1036 ```
1038 ## Deployment functions
1040 1. [nodes](#nodes)
1041 2. [nodes-active](#nodes-active)
1042 3. [run-config](#run-config)
1043 4. [members](#members)
1044 5. [group](#group)
1045 6. [group-functions](#group-functions)
1046 7. [prefix](#prefix)
1048 ---
1050 ### nodes
1052 ***Description:***
1053 Returns a list of available nodes
1055 ***Usage:***
1056 ```sh
1057 nodes
1058 ```
1060 ### nodes-active
1062 ***Description:***
1063 Returns a list of active nodes by detecting SSH availability
1065 ***Usage:***
1066 ```sh
1067 nodes-active
1068 ```
1070 ### run-config
1072 ***Description:***
1073 Executes `R7_SITE_CONFIG` in the loaded environment
1075 ***Usage:***
1076 ```sh
1077 run-config
1078 ```
1080 ### members
1082 ***Description:***
1083 Returns a list of active nodes matching a list of grep REGEXES
1085 ***Usage:***
1086 ```sh
1087 members REGEXES
1088 ```
1090 ### group
1092 ***Description:***
1093 Applies GROUPNAME functions (in prefix order) to the provided MEMBERS list
1095 ***Usage:***
1096 ```sh
1097 group GROUPNAME MEMBERS
1098 ```
1100 ### group-functions
1102 ***Description:***
1103 Returns a list of functions found in the specified GROUPNAME
1105 ***Usage:***
1106 ```sh
1107 group-functions GROUPNAME
1108 ```
1110 ### prefix
1112 ***Description:***
1113 Sets the current PREFIX for matching function names
1115 ***Usage:***
1116 ```sh
1117 prefix PREFIX
1118 ```
1120 ## Text output functions
1122 1. [output-dump](#output-dump)
1123 2. [output-latest](#output-latest)
1124 3. [output-status](#output-status)
1125 4. [output-duration](#output-duration)
1126 5. [output](#output)
1127 6. [output-diffs](#output-diffs)
1128 7. [output-permissions](#output-permissions)
1129 8. [output-errors](#output-errors)
1130 9. [summary](#summary)
1131 10. [trace-id-last](#trace-id-last)
1133 ---
1135 ### output-dump
1137 ***Description:***
1138 Dumps R7_RUNDIR to R7_OUTPUTDIR
1140 ***Usage:***
1141 ```sh
1142 output-dump
1143 ```
1145 ### output-latest
1147 ***Description:***
1148 Returns a list of outputs from the latest run
1150 ***Usage:***
1151 ```sh
1152 output-latest
1153 ```
1155 ### output-status
1157 ***Description:***
1158 Returns a list of current dumped functions exit status codes
1160 ***Usage:***
1161 ```sh
1162 output-status
1163 ```
1165 ### output-duration
1167 ***Description:***
1168 Returns a list of durations of executed groups
1170 ***Usage:***
1171 ```sh
1172 output-duration
1173 ```
1175 ### output
1177 ***Description:***
1178 Shows the dumped output matching HOST, GROUPNAME, and FUNCTION (or any if unspecified)
1180 ***Usage:***
1181 ```sh
1182 output HOST GROUPNAME FUNCTION
1183 ```
1185 ### trace-id-last
1187 ***Description:***
1188 Returns the latest execution trace_id
1190 ***Usage:***
1191 ```sh
1192 trace-id-last
1193 ```
1195 ### output-diffs
1197 ***Description:***
1198 Returns the diffs from the latest execution
1200 ***Usage:***
1201 ```sh
1202 output-diffs
1203 ```
1205 ### output-permissions
1207 ***Description:***
1208 Returns the latest permission changes
1210 ***Usage:***
1211 ```sh
1212 output-permissions
1213 ```
1215 ### output-errors
1217 ***Description:***
1218 Returns the latest errors detected
1220 ***Usage:***
1221 ```sh
1222 output-errors
1223 ```
1225 ### summary
1227 ***Description:***
1228 Produces a summary of errors, diffs, and permission outputs
1230 ***Usage:***
1231 ```sh
1232 summary
1233 ```
1235 ## Digraph output
1237 1. [digraph-host](#digraph-host)
1238 2. [digraph-ssh-id-hosts](#digraph-ssh-id-hosts)
1240 ---
1242 ### digraph-host
1244 ***Description:***
1245 Returns a directed graph (in DOT format) showing relations among groups, functions, and nodes
1247 ***Usage:***
1248 ```sh
1249 digraph-host
1250 ```
1252 ### digraph-ssh-id-hosts
1254 ***Description:***
1255 Returns a directed graph (in DOT format) of relations between SSH IDs and hosts
1257 ***Usage:***
1258 ```sh
1259 digraph-ssh-id-hosts
1260 ```
1262 ## HTML output
1264 1. [html](#html)
1266 ### html
1268 ***Description:***
1269 Retunrs a report page with the content of `README.md` in HTML format
1271 ***Usage:***
1272 ```sh
1273 html
1274 ```
1276 ---
1278 ## Node importing
1280 1. [import](#import)
1282 ### import
1284 ***Description:***
1285 Import configuration files from a target host
1287 ***Usage:***
1288 ```sh
1289 import HOST
1290 ```
1292 ---
1294 ## Technical notes
1296 - Supported shells are ksh93, oksh, yash and bash.
1298 - Supported platforms are OpenBSD, FreeBSD, NetBSD and GNU/Linux.
1300 - Busybox support is planned.
1302 - Optional dependencies are openrsync, rsync, column, graphviz and pandoc.
1304 - The HTML output is a work in progress.
1306 ---
1308 ## License
1310 The provided group library is shared as additionnal examples of the
1311 documentation and contain the following third-party files under the ISC License.
1312 Copyright information are indicated in the LICENSE section of related files.
1314 - `pf-badhost.sh`
1315 - `unbound-adblock.sh`
1316 - `http-ban.sh`
1318 The project is shared under the terms of the ISC license. Any version previous
1319 `0.1.0` needs to be considered obsolete and should not be redistributed. History
1320 in the GIT repository is kept for transparency purpose only.
1322 Below is a copy of the applicable license:
1324 ISC License
1326 Copyright 2025 xs <xs@inda.re>
1328 Permission to use, copy, modify, and/or distribute this software for any
1329 purpose with or without fee is hereby granted, provided that the above
1330 copyright notice and this permission notice appear in all copies.
1332 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1333 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
1334 FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1335 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1336 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1337 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1338 PERFORMANCE OF THIS SOFTWARE.