Commit Diff


commit - 622e6949f90df00caf7d792a15f19f6b56d33125
commit + 8e44e3d49ed6238ddfe3dc214d2fa2015e6df797
blob - 49df62ba5478f1493bfdc4cc476e6f55e404812c
blob + 9728e84212cead97ddd44cd086e6b37ff4436204
--- Makefile
+++ Makefile
@@ -16,15 +16,13 @@
 .POSIX:
 PREFIX:=/usr/local
 SHELLS=ksh93 ksh yash sh
-UTILITY_VERSION=0.1.6
+UTILITY_VERSION=0.2.0
 UTILITY=$(PWD)/r7
 # To use the test suite, please edit or use environment for SSH parameters
 # SSH_ID=/path/to/.ssh/id_ed25519
 # SSH_TEST_NODES=nodeA nodeB
-.DEFAULT: all
+.DEFAULT: all all: tests
 
-all: tests
-
 release: r7.1
 	make tests
 	whoami
@@ -193,8 +191,10 @@ workdir2-ssh: workdir2-init
 		echo 'state_hello() { echo Hey! ; }' > groups/heyo && \
 		echo 'dummy_hello() { echo Heyo! ; }' >> groups/heyo && \
 		echo 'group heyo $(SSH_TEST_NODES)' >> site-config && export R7_DEBUG=yes && \
+		. $(UTILITY) && \
+			prefix install state doc dummy && \
 			digraph_host && \
-			run_config && \
+			 run_config && \
 			output_dump && \
 			output | grep Hey! && \
 			output && \
@@ -257,7 +257,6 @@ workdir2-source: workdir2-init
 	rm -fr testdir/workdir2/_run
 	cp testdir/source testdir/workdir2/groups/
 	mkdir testdir/workdir2/groups/source.dir
-	echo : > testdir/workdir2/groups/source.dir/my-source
 	for node in $(SSH_TEST_NODES); do \
 		echo myvar=3333 > "testdir/workdir2/nodes/$$node/my-source" ; \
 	done
@@ -277,7 +276,7 @@ workdir2-importer: workdir2-init
 			. $(UTILITY) && import "$$node"; \
 		done
 	cd testdir/workdir2/ && . $(UTILITY) && import notfound || :
-	find testdir/workdir2/nodes | grep sshd_config
+	find testdir/workdir2/nodes | grep hosts
 	find testdir/workdir2/nodes
 	@echo _________________________________________________________
 
@@ -290,8 +289,14 @@ workdir3-init:
 	test -d testdir/workdir3
 	cd testdir/workdir3 && $R | wc -c | grep -q 0
 	cd testdir/workdir3 && \
-		cp "$(SSH_ID)" .ssh/id_ed25519_r7 && \
-		cp "$(SSH_ID).pub" .ssh/id_ed25519_r7.pub && \
+		cp .ssh/config .sshtmp && \
+		echo 'Host test-haiku-b5' > .ssh/config && \
+		echo '	User user' >> .ssh/config && \
+		echo >>.ssh/.config && \
+		cat .sshtmp >>.ssh/config && \
+		sleep 1 && \
+		cp -p "$(SSH_ID)" .ssh/id_ed25519_r7 && \
+		cp -p "$(SSH_ID).pub" .ssh/id_ed25519_r7.pub && \
 		. $(UTILITY) && for node in $(SSH_TEST_NODES); do \
 			mkdir "nodes/$$node" && \
 			ssh_accept_new "$$node"; \
blob - 39b3cd51e6bd3df38183f45f8f1afda3ed2bbdcd
blob + f0c090dcd606bced6e8e6289f315a43435b403f7
--- README.md
+++ README.md
@@ -3,8 +3,8 @@
 ### Introduction
 
 R7 is a configuration management framework made to configure nodes with
-configuration files and related operations versionned in a central repository.
-To remain code versionning system agnostic, manual or automated versionning is
+configuration files and related operations versioned in a central repository.
+To remain code versioning system agnostic, manual or automated versioning is
 left to the user, via makefiles or triggered from r7 `site-config` configuration
 file _(See below)_.
 
@@ -13,10 +13,10 @@ maps each host's `/etc` and to assign those hosts to c
 containing the directives to install the configuration and potential
 requirements.
 
-_Nodes sub-directories are hostnames understood by the ssh client and
+_Nodes sub-directories are host names understood by the ssh client and
 configuration._
 
-_Currently, r7 requires valid ssh configuration and keyfiles in the repository
+_Currently, r7 requires valid ssh configuration and key files in the repository
 `.ssh/` directory._
 
 _Repositories can be initialized with `rset init` or `rset -w
@@ -53,7 +53,7 @@ output-dump
 summary
 ```
 
-There is an exemple of the deployment of that configuration within the r7
+There is an example of the deployment of that configuration within the r7
 repository:
 
 ```
@@ -102,8 +102,8 @@ state_test() {
 Any function managed by `r7` needs to be declared in the format `^PREFIX_NAME()`.
 
 Group files names can't contain spaces, tabs or newlines, as well for nodes
-dirnames. _The ':' character is not recommanded as well as it may reduce
-lisibility of the interactive output._
+`dirnames`. _The ':' character is not recommended as well as it may reduce
+readability of the interactive output._
 
 Called groups and node directories are copied to related nodes in `hostname:/tmp/r7/`:
 
@@ -122,12 +122,12 @@ This means the functions matching `^install.*()`, `^st
 (the default `R7_PREFIX`) in the respective declaration order they're found in the
 related group file will be executed.
 
-Site confiurations are shell scripts sourced by r7 after it's environment is
+Site configurations are shell scripts sourced by r7 after it's environment is
 initialized, so `prefix`, `group`, `output-dump`, `summary` are the functions or
 aliases provided by r7 itself. This allow for scripting from the `site-config`
 file. Here `output-dump`, and `summary` are called to output potential errors,
 diffs and permissions changes at the end of the interactive output obtained by
-`r7 run-config`. If nothing catched happened, nothing is added to the output.
+`r7 run-config`. If nothing happened, nothing is added to the output.
 
 ### Errors during remote execution of groups
 
@@ -139,7 +139,7 @@ state_test() {
 }
 ```
 
-And we re-run the configuration to see what's happenning.
+And we re-run the configuration to see what's happening.
 
 ```
 $ r7 run-config
@@ -195,10 +195,10 @@ they're are detected, the captured related output is s
 
 ### Repository initialisation
 
-Using the `init` command, we can specify the current or a specifed
+Using the `init` command, we can specify the current or a specified
 work directory to be created and act as an r7 repository.
 
-_Automated versionning of outputs are currently let to the user, a recommended
+_Automated versioning of outputs are currently let to the user, a recommended
 place would be the end of the site configuration file._
 
 This command initializes a new directory called `test.org`:
@@ -215,12 +215,12 @@ Once this step is done, it is required to:
 
 - Adjust the SSH client configuration file in the repository `.ssh/config`
 
-_Note that it is possible to import additionnal SSH configurations, like the user
+_Note that it is possible to import additional SSH configurations, like the user
 one from the SSH configuration, but it is advised to keep them separate._
 
 ### SSH agent handling
 
-The function `unlock` can be used to set the SSH agent environement, this will
+The function `unlock` can be used to set the SSH agent environment, this will
 be required for any automated operation later done by r7:
 
 ```sh
@@ -230,8 +230,37 @@ unlock
 tmux || screen
 ```
 
-_***Warning:*** Unlock will terminate any running `ssh-agent` instances._
 
+#### Tmux configuration
+
+```
+set -g update-environment -r
+```
+
+#### Optional Shell configuration
+
+This is useful for handling multiple tmux sessions.
+
+```sh
+# Add this to the shell's rc
+if [ -z "$TMUX" ]; then
+    if [ -n "$SSH_TTY" ]; then
+	if [ -z "$SSH_AUTH_SOCK" ]; then
+	    export SSH_AUTH_SOCK="$HOME/.ssh/.auth_socket"
+	fi
+	if [ ! -S "$SSH_AUTH_SOCK" ]; then
+	    eval $(ssh-agent -a $SSH_AUTH_SOCK) >/dev/null 2>&1
+	    echo $SSH_AGENT_PID >$HOME/.ssh/.auth_pid
+	fi
+	if [ -z $SSH_AGENT_PID ]; then
+	    export SSH_AGENT_PID=$(cat $HOME/.ssh/.auth_pid)
+	fi
+	ssh-add "$SSH_ID" 2>/dev/null
+    fi
+fi
+```
+
+
 ### Adding new hosts
 
 For adding a new host, the simplest way is to have pre-configured
@@ -261,8 +290,6 @@ automatically.
 
 ### Importing hosts configurations
 
-_This feature currently only support OpenBSD._
-
 Avoiding to import the configuration manually is possible with the `import`
 command:
 
@@ -275,7 +302,7 @@ Most common configuration files will be copied in a ne
 
 ### Writing group files
 
-Group files collects fonctions related to the configuration of the operating
+Group files collects functions related to the configuration of the operating
 system, networking, services, global and user configurations packages
 installations and application deployments.
 
@@ -307,7 +334,7 @@ doc_A() {
 
 _**file**: `groups/example1`_
 
-With the default prefix, `install`, `state`, `doc`, the fonction that will be
+With the default prefix, `install`, `state`, `doc`, the function that will be
 executed are `state_A` and `doc_A`. To test that group file with all the
 functions inside we can call r7 the following way:
 
@@ -467,7 +494,7 @@ which is the system provided default `ntpd.conf`.
 
 ### Sourcing specific files
 
-Here's an example how to source additionnal shell from the deployed node
+Here's an example how to source additional shell from the deployed node
 directory, or elsewhere:
 
 ```sh
@@ -579,7 +606,7 @@ $ r7 output tools0 OpenBSD state_packages\*
 	https://cdn.openbsd.org/pub/OpenBSD
 ```
 
-_Note that the `output` function arguments are using shell's case globbing patterns._
+_Note that the `output` function arguments are using shell's case glob patterns._
 
 ### Active nodes
 
@@ -762,7 +789,7 @@ node [filename|dirname]
 ### nodename
 
 ***Description:***
-Returns the small hostname of the current host
+Returns the small host name of the current host
 
 ***Usage:***
 ```sh
@@ -837,7 +864,7 @@ destination
 ### groupinstalldir
 
 ***Description:***
-Change directory to the current group directoy then call installdir
+Change directory to the current group directory then call installdir
 
 ***Usage:***
 ```sh
@@ -848,7 +875,7 @@ destination
 ### nodeinstalldir
 
 ***Description:***
-Change directory to the current group directoy then call installdir
+Change directory to the current group directory then call installdir
 
 ***Usage:***
 ```sh
@@ -856,7 +883,7 @@ nodeinstalldir [-o fileowner] [-m filemode] [-O dirown
 destination
 ```
 
-### source
+### fsource
 
 ***Description:***
 Source a POSIX shell file in the current execution
@@ -864,7 +891,7 @@ Source a POSIX shell file in the current execution
 ***Usage:***
 
 ```sh
-source filename
+fsource filename
 ```
 
 ### groupsource
@@ -1095,7 +1122,7 @@ ssh-authorized-keys
 ### ssh-ids-hosts
 
 ***Description:***
-Returns SSH IDs along with matching keyfile and hostname
+Returns SSH IDs along with matching key file and host name
 
 ***Usage:***
 ```sh
@@ -1376,18 +1403,40 @@ import HOST
 
 ## Technical notes
 
-- Supported shells are ksh93, oksh, yash and bash.
-- Supported platforms are OpenBSD, FreeBSD, NetBSD and GNU/Linux.
-- Dependencies are awk, OpenSSH and column
-- Optional dependencies are openrsync, rsync, column, graphviz and pandoc.
-- Busybox support is planned.
-- The HTML output is a work in progress.
+- Supported shells are ksh93, oksh, yash and bash
+- Supported target platforms are POSIX compatible systems
+    - `/bin/sh` or compatible must be set for the user's shell (which is
+      usually the case by default)
+    - `/tmp` must be writable by the user
+- Supported control node platforms are supposed to be POSIX compatible systems
+  but currently limited to BSD's, Darwin and GNU/Linux
+    - Dependencies are awk, OpenSSH and column
+    - Optional dependencies are openrsync, rsync, column, graphviz and pandoc
+- The r7 importer supports the following platform:
+    - Alpine Linux
+    - Archlinux
+    - Crux
+    - Debian
+    - DragonFlyBSD
+    - FreeBSD
+    - Gentoo
+    - Guix
+    - Haiku
+    - Minix
+    - NetBSD
+    - Omnios
+    - OpenBSD
+    - OpenSUSE
+    - QNX
+    - Rocky Linux
+    - Salix
+    - Void Linux
 
 ---
 
 ## License
 
-The provided group library is shared as additionnal examples WITH NO WARRANTIES of the
+The provided group library is shared as additional examples WITH NO WARRANTIES of the
 documentation and contain the following third-party files under the ISC License.
 Copyright information are indicated in the LICENSE section of related files.
 
blob - 9f95a199b0e44884ab0abb31a98fb72849d7f9ff
blob + 09356f5a57f7039c794727aa88d5d7f9e89b5e44
--- r7
+++ r7
@@ -20,11 +20,15 @@
 # Global configuration
 # ====================
 
+: "${ZSH_VERSION:=}"
+R7_DEBUG=no
 VERSION=0.2.0
+_init_pwd="$PWD"
 
 # shellcheck disable=SC2031
 _init_env() {
 	_debug _INIT_ENV
+	cd "$_init_pwd" || _fail "Unable to cd to '$_init_pwd'"
 
 	# Here is the default configuration
 	: "${R7_DEBUG:=no}"
@@ -35,7 +39,7 @@ _init_env() {
 	: "${R7_PARALLEL:=no}"
 	: "${R7_PREFIX:=install state doc}"
 	: "${R7_SHOWOUTPUT:=no}"
-	: "${R7_WORKDIR:=$PWD}"
+	: "${R7_WORKDIR:=$_init_pwd}"
 	: "${R7_SITE_CONFIG:=$R7_WORKDIR/site-config}"
 	: "${R7_OUTPUTDIR:=$R7_WORKDIR/_output}"
 	: "${SSH_CONFIG_DIR:=$R7_WORKDIR/.ssh}"
@@ -243,7 +247,7 @@ _main() {
 		digraph_ssh_id_hosts
 		;;
 	html) html "$@" ;;
-	'') info ;;
+	'') cd "$R7_WORKDIR" && info ;;
 	*)
 		case $0 in
 		-) exit 33 ;;
@@ -309,15 +313,6 @@ Host *
 	StrictHostKeyChecking yes
 	User root
 	UserKnownHostsFile $R7_WORKDIR/.ssh/known_hosts
-
-Host alpha
-	Hostname 10.10.0.1
-
-Host beta
-	Hostname 10.10.0.2
-
-Host gamma
-	Hostname 10.10.0.3
 eof
 	fi
 	touch "${SSH_IDENTITY_FILE}" "${SSH_IDENTITY_FILE}.pub"
@@ -337,7 +332,7 @@ ssh() (
 alias ssh-debug=ssh_debug
 ssh_debug() {
 	_debug "SSH $*"
-	ssh -vvv "$@" :
+	ssh -vvv "$@"
 }
 
 alias ssh-known-hosts=ssh_known_hosts
@@ -359,7 +354,7 @@ ssh_authorized_keys_reset() {
 
 alias ssh-accept-new=ssh_accept_new
 ssh_accept_new() {
-	ssh -o StrictHostKeyChecking=accept-new "$@" :
+	ssh -F "$SSH_CONFIG_FILE" -o StrictHostKeyChecking=accept-new "$@" :
 }
 
 alias ssh-control-master-clean=ssh_control_master_clean
@@ -401,7 +396,6 @@ ssh_ids_hosts() {
 }
 
 unlock() {
-	pkill ssh-agent
 	eval "$(ssh-agent)"
 	ssh-add "$SSH_IDENTITY_FILE"
 }
@@ -432,7 +426,8 @@ copy() (
 	_debug "COPY $1 $2 USE SCP"
 	dir=${dir:-/tmp/r7}
 	ssh "$node" rm -fr "$dir/$1" 2>/dev/null
-	/usr/bin/scp "-oConnectTimeout=$SSH_CONNECT_TIMEOUT" -qF "$SSH_CONFIG_FILE" -r "$1" "$2"
+	scp "-oConnectTimeout=$SSH_CONNECT_TIMEOUT" -qF "$SSH_CONFIG_FILE" -r "$1" "$2" && return 0
+	_fail "Unable to copy '$1' to '$2'."
 )
 
 # Deployment functions
@@ -486,12 +481,12 @@ _deploy() (
 	nodedir="nodes/$target"
 	test "$R7_DRYRUN" = yes || {
 		if test -d "$stem.dir"; then
-			ssh "$target" 'test -d /tmp/r7 || { umask 027; mkdir -p /tmp/r7; }'
+			ssh "$target" /bin/sh -c 'umask 027; mkdir -p /tmp/r7'
 			copy "$stem.dir" "$target:/tmp/r7" || return 3
 		fi
 		if test -d "$nodedir"; then
 			test -f /tmp/r7/"$trace_id.$target" || {
-				ssh "$target" 'test -d /tmp/r7 || { umask 027; mkdir -p /tmp/r7; }'
+				ssh "$target" /bin/sh -c 'umask 027; mkdir -p /tmp/r7'
 				copy "$nodedir" "$target:/tmp/r7" || return 3
 			}
 		fi
@@ -592,6 +587,7 @@ _call() (
 )
 
 _payload() (
+	echo "hostname=$target"
 	echo "trace_id=$trace_id"
 	echo "groupname=$new_name"
 	echo "exitonerror=$R7_GROUP_EXITONERROR"
@@ -624,20 +620,7 @@ _payload() (
 		groupdir() (
 			echo "/tmp/r7/$groupname.dir"
 		)
-		_presource() {
-			test $# -gt 0 || {
-				error missing source argument
-				return 2
-			}
-			source "$(test -f "$1" && printf %s "$PWD/${1##"$PWD"}")"
-		}
-		nodesource() { 
-			node "$1" && cd "$(nodedir)" && _presource "$1"
-		}
-		groupsource() { 
-			cd "$(groupdir)" && _presource "$1"
-		}
-		source() {
+		_source() {
 			if sh -n "$1"; then
 				trace SOURCE "$1"
 				. "$1"
@@ -646,6 +629,19 @@ _payload() (
 				return 2
 			fi
 		}
+		fsource() {
+			test $# -gt 0 || {
+				error missing source argument
+				return 2
+			}
+			_source "$(test -f "$1" && printf %s "$PWD/${1##"$PWD"}")"
+		}
+		nodesource() { 
+			node "$1" && cd "$(nodedir)" && fsource "$1"
+		}
+		groupsource() { 
+			cd "$(groupdir)" && _fsource "$1"
+		}
 		install() ( cd /tmp/r7 && r7_install "$@" ; )
 		groupinstall() ( cd "$(groupdir)" && r7_install "$@" ; )
 		nodeinstall() ( cd "$(nodedir)" && r7_install "$@" ; )
@@ -783,7 +779,7 @@ _payload() (
 			done
 			shift $((OPTIND - 1))
 			set -a
-			test -n "$source" && sh -n "$source" && . "./$source"
+			test -n "$source" && sh -n "$source" && set -a && . "./$source" && set +a
 			for file; do
 				sh > "${file%%.tpl}" <<-.
 					cat <<-..
@@ -801,6 +797,7 @@ _payload() (
 		nodedir=$(nodedir)
 		groupdir=$(groupdir)
 		trace CONNECTED $(date +%s)
+		exec 1>&2
 	eof
 	cat "$1"
 	_debug "PREFIX $R7_PREFIX"
@@ -817,6 +814,7 @@ _payload() (
 
 # shellcheck disable=SC2086,SC2030
 _collect() (
+	set +u
 	tee -a "$1" | while read -r line; do
 		set -- $line
 		case $line in
@@ -1249,15 +1247,10 @@ html() {
 
 # Importers
 # =========
-# TODO: WIP
 
 import() {
 	cd "$R7_WORKDIR" || _fail "Unable to cd to '$R7_WORKDIR'"
 	target=$1
-	etc_ssh_files_to_import='
-		ssh/sshd_config
-		ssh/ssh_config
-	'
 	if test -n "$target"; then
 		echo >&2 "-> Importing target host: $target"
 		case $(ssh "$target" uname) in
@@ -1267,6 +1260,9 @@ import() {
 		FreeBSD) _FreeBSD_import ;;
 		NetBSD) _NetBSD_import ;;
 		DragonFly) _DragonFly_import ;;
+		Haiku) _Haiku_import ;;
+		QNX) _QNX_import ;;
+		Minix) _Minix_import ;;
 		*)
 			_error "Platform unsupported or host unavailable."
 			return 3
@@ -1294,11 +1290,12 @@ _import_copy() (
 			-a "$src" "$dst" && return 0
 	}
 	_debug "IMPORT $1 $2 USE SCP"
-	scp -r "$target:$src" "$dst" && return 0
+	scp "-oConnectTimeout=$SSH_CONNECT_TIMEOUT" -qF "$SSH_CONFIG_FILE" -r "$src" "$dst" && return 0
 	_fail "IMPORT $1 $2 FAILED"
 )
 
-_import_ssh_authorized_keys() {
+_import_ssh_authorized_keys_old() (
+	set +e
 	other_users=$(
 		ssh "$target" getent passwd | awk -F: '$3 >= 1000 { print $1 }' |
 			grep -v nobody
@@ -1311,11 +1308,29 @@ _import_ssh_authorized_keys() {
 		ssh "$target" test -f "$authorized_keys" || continue
 		mkdir -p "nodes/$target/ssh/"
 		echo >&2 "--> Importing $authorized_keys"
-		#_import_copy "root@$target:$authorized_keys" "nodes/$target/ssh/authorized_keys_$user"
-		scp "root@$target:$authorized_keys" "nodes/$target/ssh/authorized_keys_$user"
+		_import_copy "$target:$authorized_keys" "nodes/$target/ssh/authorized_keys_$user"
 	done
-}
+)
 
+_import_ssh_authorized_keys() (
+	set +e
+	other_users=$(
+		ssh "$target" cat /etc/passwd | awk -F: '$3 >= 1000 { print	$1 }' | grep -v nobody
+	)
+	for user in root $other_users; do
+		home=$(
+			ssh "$target" cat /etc/passwd | awk -F: -v user="$user" '$1 == user { print $6 }'
+		)
+		authorized_keys="$home/.ssh/authorized_keys"
+		if ! ssh -n "$target" test -f "$authorized_keys"; then
+			continue
+		fi
+		mkdir -p "nodes/$target/ssh/"
+		echo >&2 "--> Importing $authorized_keys for user='$user'"
+		_import_copy "$target:$authorized_keys" "nodes/$target/ssh/authorized_keys_$user"
+	done
+)
+
 _import_etc_if_exists() {
 	mkdir -p nodes/"$target"
 	echo >&2 "--> Importing /etc"
@@ -1326,7 +1341,11 @@ _import_etc_if_exists() {
 }
 
 _import_etc_ssh_if_exists() {
-	mkdir -p nodes/"$target"
+	etc_ssh_files_to_import='
+		ssh/sshd_config
+		ssh/ssh_config
+	'
+	mkdir -p nodes/"$target/ssh"
 	echo >&2 "--> Importing /etc/ssh"
 	for file in $etc_ssh_files_to_import; do
 		ssh "$target" test -f "'/etc/$file'" &&
@@ -1335,54 +1354,136 @@ _import_etc_ssh_if_exists() {
 }
 
 _import_modprobe() {
-	mkdir -p nodes/"$target"
-	echo >&2 "--> Importing /etc/modprobe.d"
-	for file in $etc_modprobe_files_to_import; do
-		ssh "$target" test -f "'/etc/modprobe.d/$file'" &&
-			_import_copy "$target:/etc/modprobe.d/$file" "nodes/$target/modprobe.d"
-	done
+	if ssh "$target" test -d /etc/modprobe.d; then
+		_content=$(ssh "$target" ls -A /etc/modprobe.d/)
+		test -z "$_content" && return 0
+		echo >&2 "--> Importing /etc/modprobe.d"
+		mkdir -p nodes/"$target/modprobe.d"
+		_import_copy "$target:/etc/modprobe.d/*" "nodes/$target/modprobe.d"
+	fi
 }
 
+_QNX_import() {
+	etc_files_to_import='
+		build.date
+	'
+	_import_etc_if_exists
+	echo >&2 "--> Importing /etc/settings"
+	mkdir -p "nodes/$target/settings"
+	_import_copy "$target:/etc/settings" "nodes/$target/settings"
+	echo >&2 "--> Importing /system/etc/ssh"
+	mkdir -p "nodes/$target/ssh"
+	_import_copy "$target:/system/etc/ssh/sshd_config" "nodes/$target/ssh"
+	_import_ssh_authorized_keys
+}
+
+_Minix_import() {
+	etc_files_to_import='
+		fstab
+		inet.conf
+		profile
+		resolv.conf
+		shells
+		rc.conf
+	'
+	_import_etc_if_exists
+	echo >&2 "--> Importing /usr/pkg/etc/ssh"
+	mkdir -p nodes/"$target/ssh"
+	_import_copy "$target:/usr/pkg/etc/ssh/sshd_config" "nodes/$target/ssh"
+	_import_copy "$target:/usr/pkg/etc/ssh/ssh_config" "nodes/$target/ssh"
+	echo >&2 "--> Importing /usr/pkg/etc/pkgin"
+	mkdir -p nodes/"$target/pkgin"
+	_import_copy "$target:/usr/pkg/etc/pkgin/repositories.conf" "nodes/$target/pkgin"
+}
+
+_Haiku_import() {
+	etc_files_to_import='
+		inputrc
+		profile
+	'
+	_import_etc_if_exists
+	_import_copy "$target:/boot/system/settings/network/hosts" "nodes/$target/"
+	_import_copy "$target:/boot/system/settings/network/resolv.conf" "nodes/$target/"
+	_import_copy "$target:/boot/system/settings/package-repositories" "nodes/$target/"
+	echo >&2 "--> Importing /boot/system/settings/ssh"
+	mkdir -p "nodes/$target/ssh"
+	_import_copy "$target:/boot/system/settings/ssh/sshd_config" "nodes/$target/ssh"
+	_import_copy "$target:/boot/system/settings/ssh/ssh_config" "nodes/$target/ssh"
+	_import_copy "$target:/boot/home/config/settings/ssh/authorized_keys" \
+		"nodes/$target/ssh/authorized_keys_user"
+}
+
 _Linux_import() {
-	etc_modprobe_files_to_import='
-		modprobe.d/*.conf
-	'
 	if _Linux_is_debian_based; then
 		_Linux_import_debian
 	elif _Linux_is_rhel_based; then
 		_Linux_import_rhel
+	elif _Linux_is_suse_based; then
+		_Linux_import_suse
 	elif _Linux_is_gentoo_based; then
 		_Linux_import_gentoo
+	elif _Linux_is_arch_based; then
+		_Linux_import_arch
+	elif _Linux_is_artix; then
+		_Linux_import_artix
 	elif ssh "$target" "grep -q 'ID=alpine' /etc/os-release"; then
 		_Linux_import_alpine
+	elif ssh "$target" "grep -q 'ID=crux' /etc/os-release"; then
+		_Linux_import_crux
+	elif ssh "$target" "grep -q 'ID=\"void\"' /etc/os-release"; then
+		_Linux_import_void
+	elif ssh "$target" "grep -q 'ID=guix' /etc/os-release"; then
+		_Linux_import_guix
 	else
 		echo >&2 "Unsupported Linux distribution."
 	fi
 }
 
 _Linux_is_debian_based() (
-	ssh "$target" "grep -q 'ID=debian' /etc/os-release || grep -q 'ID_LIKE=.*debian' /etc/os-release || \
-                   grep -qiE 'Debian|Ubuntu|Linux Mint' /etc/issue || \
-                   test -f /etc/debian_version || test -d /etc/apt || command -v apt-get >/dev/null 2>&1"
+	ssh "$target" "grep -q 'ID=debian' /etc/os-release || \
+	   grep -q 'ID_LIKE=.*debian' /etc/os-release || \
+	   grep -qiE 'Debian|Ubuntu|Linux Mint' /etc/issue || \
+	   test -f /etc/debian_version || test -d /etc/apt || command -v apt-get >/dev/null 2>&1" 2>/dev/null
 )
 
 _Linux_is_rhel_based() (
-	ssh "$target" "grep -qE 'ID=\"?(rhel|fedora|centos|ol|scientific)\"?' /etc/os-release || \
-                   grep -qE 'ID_LIKE=\"?.*(rhel|fedora).*\"?' /etc/os-release || \
-                   grep -qiE 'Red Hat|CentOS|Fedora|Scientific Linux|Oracle Linux|openSUSE|SUSE' /etc/issue || \
-                   grep -qiE 'Red Hat|CentOS|Fedora|Scientific Linux|Oracle Linux|openSUSE|SUSE' /etc/redhat-release || \
-                   test -f /etc/redhat-release || test -f /etc/system-release || test -f /etc/centos-release || \
-                   test -f /etc/fedora-release || test -f /etc/oracle-release || \
-                   (test -f /etc/os-release && grep -qi 'rhel' /etc/os-release) || test -d /etc/yum.repos.d"
+	ssh "$target" "grep -qiE 'ID=\"?(rhel|fedora|centos|ol|scientific|rocky|eurolinux)\"?' /etc/os-release || \
+		grep -qiE 'ID_LIKE=\"?.*(rhel|fedora).*\"?' /etc/os-release || \
+		grep -qiE 'Red Hat|CentOS|Fedora|Scientific Linux|Oracle Linux' /etc/issue || \
+		test -f /etc/redhat-release || test -f /etc/system-release || test -f /etc/centos-release || \
+		test -f /etc/fedora-release || test -f /etc/oracle-release || \
+		(test -f /etc/os-release && grep -qi 'rhel' /etc/os-release) || test -d /etc/yum.repos.d" 2>/dev/null
 )
 
 _Linux_is_gentoo_based() (
 	ssh "$target" "test -f /etc/gentoo-release || \
-               grep -q 'ID=gentoo' /etc/os-release || \
-               grep -qi 'Gentoo' /etc/issue || \
-               command -v emerge >/dev/null 2>&1"
+		grep -q 'ID=gentoo' /etc/os-release || \
+		grep -q 'ID=funtoo' /etc/os-release || \
+		grep -qi 'Gentoo' /etc/issue || \
+		command -v emerge >/dev/null 2>&1" 2>/dev/null
 )
 
+_Linux_is_suse_based() (
+	ssh "$target" "test -f /etc/os-release && grep -Eqi \
+		'suse|opensuse' /etc/os-release || \
+		command -v zypper >/dev/null || \
+		command -v yast2 >/dev/null" 2>/dev/null
+)
+
+_Linux_is_arch_based() (
+	ssh "$target" "test -f /etc/os-release && grep -Eqi \
+		'arch|manjaro|endeavouros|arcolinux|parabola' /etc/os-release || \
+		command -v pacman >/dev/null || \
+		command -v makepkg >/dev/null" 2>/dev/null
+)
+
+_Linux_is_artix() (
+	ssh "$target" "test -f /etc/os-release && grep -Eqi \
+		'artix|hyperbola' /etc/os-release || \
+		command -v pacman >/dev/null || \
+		command -v makepkg >/dev/null" 2>/dev/null
+)
+
 _Linux_import_gentoo() {
 	etc_files_to_import='
 		crontab
@@ -1399,7 +1500,6 @@ _Linux_import_gentoo() {
 		nsswitch.conf
 		pam.conf
 		profile
-		resolv.conf
 		shells
 		sudo.conf
 		sudoers
@@ -1407,6 +1507,9 @@ _Linux_import_gentoo() {
 	'
 	_import_etc_if_exists
 	_import_etc_ssh_if_exists
+	echo >&2 "--> Importing /etc/portage"
+	mkdir -p "nodes/$target/portage"
+	_import_copy "$target:/etc/portage/" "nodes/$target/portage/"
 	_import_ssh_authorized_keys
 	_import_modprobe
 }
@@ -1432,6 +1535,9 @@ _Linux_import_alpine() {
 	'
 	_import_etc_if_exists
 	_import_etc_ssh_if_exists
+	echo >&2 "--> Importing /etc/apk"
+	mkdir -p "nodes/$target/apk"
+	_import_copy "$target:/etc/apk/repositories" "nodes/$target/apk/"
 	_import_ssh_authorized_keys
 	_import_modprobe
 }
@@ -1458,6 +1564,9 @@ _Linux_import_rhel() {
 	'
 	_import_etc_if_exists
 	_import_etc_ssh_if_exists
+	echo >&2 "--> Importing /etc/yum.repos.d"
+	mkdir -p "nodes/$target/yum.repos.d"
+	_import_copy "$target:/etc/yum.repos.d/" "nodes/$target/yum.repos.d/"
 	_import_ssh_authorized_keys
 	_import_modprobe
 }
@@ -1473,7 +1582,6 @@ _Linux_import_debian() {
 		issue
 		locale.gen
 		machine-id
-		motd
 		nsswitch.conf
 		pam.conf
 		profile
@@ -1483,11 +1591,122 @@ _Linux_import_debian() {
 		sudoers
 	'
 	_import_etc_if_exists
+	echo >&2 "--> Importing /etc/apt"
+	mkdir -p "nodes/$target/apt"
+	_import_copy "$target:/etc/apt/sources.list" "nodes/$target/apt"
+	_import_copy "$target:/etc/apt/sources.list.d" "nodes/$target/apt"
+	echo >&2 "--> Importing /etc/network"
+	mkdir -p "nodes/$target/network/"
+	_import_copy "$target:/etc/network/interfaces" "nodes/$target/network/"
+	_import_copy "$target:/etc/network/interfaces.d" "nodes/$target/network/"
 	_import_etc_ssh_if_exists
 	_import_ssh_authorized_keys
 	_import_modprobe
+
 }
 
+_Linux_import_suse() {
+	etc_files_to_import='
+		fstab
+		hosts
+		profile
+		sudo.conf
+		sudoers
+		sysctl.conf
+		environment
+		exports
+		chrony.conf
+	'
+	_import_etc_if_exists
+	_import_etc_ssh_if_exists
+	_import_ssh_authorized_keys
+	_import_modprobe
+}
+
+_Linux_import_arch() {
+	etc_files_to_import='
+		environment
+		hostname
+		profile
+		arch-release
+		issue
+		hosts
+		pacman.conf
+		sudo.conf
+		sudoers
+		fstab
+	'
+	_import_etc_if_exists
+	_import_etc_ssh_if_exists
+	_import_ssh_authorized_keys
+	_import_modprobe
+}
+
+_Linux_import_artix() {
+	_Linux_import_arch
+}
+
+_Linux_import_guix() {
+	etc_files_to_import='
+		config.scm
+		environment
+		fstab
+		hostname
+		hosts
+		issue
+		nsswitch.conf
+		profile
+		resolv.conf
+		shells
+		sudoers
+	'
+	_import_etc_if_exists
+	_import_etc_ssh_if_exists
+	_import_ssh_authorized_keys
+}
+
+_Linux_import_void() {
+	etc_files_to_import='\
+		fstab
+		dhcpcd.conf
+		environment
+		hosts
+		profile
+		rc.conf
+		nsswitch.conf
+		shells
+		sudoers
+		sudo.conf
+		sysctl.conf
+		resolv.conf
+	'
+	_import_etc_if_exists
+	_import_etc_ssh_if_exists
+	_import_ssh_authorized_keys
+	_import_modprobe
+}
+
+_Linux_import_crux() {
+	etc_files_to_import='
+		crontab
+		hosts
+		resolv.conf
+		environment
+		fstab
+		locale.gen
+		hosts
+		profile
+		rc.conf
+		rc.local
+		syslog.conf
+		sysctl.conf
+	'
+	_import_etc_if_exists
+	_import_etc_ssh_if_exists
+	_import_ssh_authorized_keys
+	_import_modprobe
+}
+
 _SunOS_import() {
 	etc_files_to_import='
 		crontab
@@ -1515,6 +1734,65 @@ _SunOS_import() {
 	_import_ssh_authorized_keys
 }
 
+_FreeBSD_import() {
+	etc_files_to_import='
+		crontab
+		fbtab
+		fstab
+		hostname
+		hosts
+		login.conf
+		nsswitch.conf
+		ntp.conf
+		profile
+		resolv.conf
+		shells
+		sysctl.conf
+		syslog.conf
+	'
+	_import_etc_if_exists
+	echo >&2 "--> Importing /etc/pkg"
+	_import_copy "$target:/etc/pkg" "nodes/$target/"
+	_import_etc_ssh_if_exists
+	_import_ssh_authorized_keys
+}
+
+_DragonFly_import() {
+	etc_files_to_import='
+		crontab
+		fstab
+		hosts
+		login.conf
+		pf.conf
+		resolv.conf
+		shells
+		sysctl.conf
+		syslog.conf
+	'
+	_import_etc_if_exists
+	_import_etc_ssh_if_exists
+	_import_ssh_authorized_keys
+}
+
+_NetBSD_import() {
+	etc_files_to_import='
+		fstab
+		hosts
+		locate.conf
+		pf.conf
+		resolv.conf
+		shells
+		sysctl.conf
+		syslog.conf
+		usermgmt.conf
+		wscons.conf
+		rc.local
+	'
+	_import_etc_if_exists
+	_import_etc_ssh_if_exists
+	_import_ssh_authorized_keys
+}
+
 _OpenBSD_import() {
 	etc_files_to_import='
 		acme-client.conf
@@ -1533,18 +1811,15 @@ _OpenBSD_import() {
 		mygate
 		myname
 		newsyslog.conf
+		syslog.conf
 		ntpd.conf
 		pf.conf
 		resolv.conf
 		sysctl.conf
 		unwind.conf
 		usermgt.conf
+		rc.conf.local
 	'
-	etc_mail_files_to_import='
-		mail/aliases
-		mail/smtpd.conf
-		mail/spamd.conf
-	'
 	etc_ssh_files_to_import='
 		ssh/sshd_config
 		ssh/ssh_config
@@ -1580,6 +1855,11 @@ _OpenBSD_import_etc_if_exists() {
 }
 
 _OpenBSD_import_etc_mail_if_exists() {
+	etc_mail_files_to_import='
+		mail/aliases
+		mail/smtpd.conf
+		mail/spamd.conf
+	'
 	mkdir -p nodes/"$target"
 	echo >&2 "--> Importing /etc/mail"
 	for file in $etc_mail_files_to_import; do
@@ -1602,7 +1882,7 @@ _OpenBSD_import_unbound_if_enabled() {
 
 _OpenBSD_import_nsd_if_enabled() {
 	ssh "$target" rcctl check nsd >/dev/null && {
-		echo >&2 "--> Import /var/nsd"
+		echo >&2 "--> Importing /var/nsd"
 		for file in $var_nsd_files; do
 			prefix=${file%%/*}
 			mkdir -p "nodes/$target/nsd/$prefix"
@@ -1620,69 +1900,13 @@ _OpenBSD_import_postgresql_if_installed() {
 			mkdir -p "nodes/$target/postgresql/$prefix"
 			_import_copy "$target:/var/postgresql/$file" "nodes/$target/postgresql/$prefix/"
 		done
-		echo >&2 "-- Importing /etc/login.conf.d/postgresql"
+		echo >&2 "--> Importing /etc/login.conf.d/postgresql"
 		mkdir -p "nodes/$target/login.conf.d"
 		_import_copy "$target:/etc/login.conf.d/postgresql" "nodes/$target/login.conf.d/"
 		return 0
 	}
 }
 
-_FreeBSD_import() {
-	etc_files_to_import='
-		crontab
-		fbtab
-		fstab
-		hostname
-		hosts
-		login.conf
-		nsswitch.conf
-		ntp.conf
-		profile
-		resolv.conf
-		shells
-		sysctl.conf
-		syslog.conf
-	'
-	_import_ssh_authorized_keys
-	_import_etc_if_exists
-	_import_etc_ssh_if_exists
-}
-
-_NetBSD_import() {
-	etc_files_to_import='
-		fstab
-		hosts
-		locate.conf
-		pf.conf
-		resolv.conf
-		shells
-		sysctl.conf
-		syslog.conf
-		usermgmt.conf
-		wscons.conf
-	'
-	_import_ssh_authorized_keys
-	_import_etc_if_exists
-	_import_etc_ssh_if_exists
-}
-
-_DragonFly_import() {
-	etc_files_to_import='
-		crontab
-		fstab
-		hosts
-		login.conf
-		pf.conf
-		resolv.conf
-		shells
-		sysctl.conf
-		syslog.conf
-	'
-	_import_ssh_authorized_keys
-	_import_etc_if_exists
-	_import_etc_ssh_if_exists
-}
-
 # Main
 # ====
 
blob - 3e6d7688489b3ea53dcb1daaad648fe01cb119c3
blob + 61ca652ae438392a6480c60875b088254b303d5c
--- r7.1
+++ r7.1
@@ -1,14 +1,14 @@
 '\" t
 .\" Automatically generated by Pandoc 3.6.2
 .\"
-.TH "R7" "1" "Tue Jun 3 2025" "v0.1.6" "User Manual"
+.TH "R7" "1" "Tue Jun 3 2025" "v0.2.0" "User Manual"
 .SS Tutorial
 .SS Introduction
 R7 is a configuration management framework made to configure nodes with
-configuration files and related operations versionned in a central
+configuration files and related operations versioned in a central
 repository.
-To remain code versionning system agnostic, manual or automated
-versionning is left to the user, via makefiles or triggered from r7
+To remain code versioning system agnostic, manual or automated
+versioning is left to the user, via makefiles or triggered from r7
 \f[CR]site\-config\f[R] configuration file \f[I](See below)\f[R].
 .PP
 The idea is to store hosts configurations in \f[CR]nodes/hostname\f[R]
@@ -16,10 +16,10 @@ directories that maps each host\[cq]s \f[CR]/etc\f[R] 
 those hosts to configuration groups containing the directives to install
 the configuration and potential requirements.
 .PP
-\f[I]Nodes sub\-directories are hostnames understood by the ssh client
+\f[I]Nodes sub\-directories are host names understood by the ssh client
 and configuration.\f[R]
 .PP
-\f[I]Currently, r7 requires valid ssh configuration and keyfiles in the
+\f[I]Currently, r7 requires valid ssh configuration and key files in the
 repository \f[CI].ssh/\f[I] directory.\f[R]
 .PP
 \f[I]Repositories can be initialized with \f[CI]rset init\f[I] or
@@ -59,7 +59,7 @@ output\-dump
 summary
 .EE
 .PP
-There is an exemple of the deployment of that configuration within the
+There is an example of the deployment of that configuration within the
 r7 repository:
 .IP
 .EX
@@ -110,9 +110,9 @@ Any function managed by \f[CR]r7\f[R] needs to be decl
 \f[CR]\[ha]PREFIX_NAME()\f[R].
 .PP
 Group files names can\[cq]t contain spaces, tabs or newlines, as well
-for nodes dirnames.
-\f[I]The `:' character is not recommanded as well as it may reduce
-lisibility of the interactive output.\f[R]
+for nodes \f[CR]dirnames\f[R].
+\f[I]The `:' character is not recommended as well as it may reduce
+readability of the interactive output.\f[R]
 .PP
 Called groups and node directories are copied to related nodes in
 \f[CR]hostname:/tmp/r7/\f[R]:
@@ -138,7 +138,7 @@ This means the functions matching \f[CR]\[ha]install.*
 \f[CR]R7_PREFIX\f[R]) in the respective declaration order they\[cq]re
 found in the related group file will be executed.
 .PP
-Site confiurations are shell scripts sourced by r7 after it\[cq]s
+Site configurations are shell scripts sourced by r7 after it\[cq]s
 environment is initialized, so \f[CR]prefix\f[R], \f[CR]group\f[R],
 \f[CR]output\-dump\f[R], \f[CR]summary\f[R] are the functions or aliases
 provided by r7 itself.
@@ -146,7 +146,7 @@ This allow for scripting from the \f[CR]site\-config\f
 Here \f[CR]output\-dump\f[R], and \f[CR]summary\f[R] are called to
 output potential errors, diffs and permissions changes at the end of the
 interactive output obtained by \f[CR]r7 run\-config\f[R].
-If nothing catched happened, nothing is added to the output.
+If nothing happened, nothing is added to the output.
 .SS Errors during remote execution of groups
 In our previous example, we modify \f[CR]state_test\f[R] so the
 \f[CR]test\f[R] fails.
@@ -157,7 +157,7 @@ state_test() \f[B]{\f[R]
 \f[B]}\f[R]
 .EE
 .PP
-And we re\-run the configuration to see what\[cq]s happenning.
+And we re\-run the configuration to see what\[cq]s happening.
 .IP
 .EX
 $ r7 run\-config
@@ -212,9 +212,9 @@ Diffs and permissions changes are also displayed by th
 When they\[cq]re are detected, the captured related output is shown.
 .SS Repository initialisation
 Using the \f[CR]init\f[R] command, we can specify the current or a
-specifed work directory to be created and act as an r7 repository.
+specified work directory to be created and act as an r7 repository.
 .PP
-\f[I]Automated versionning of outputs are currently let to the user, a
+\f[I]Automated versioning of outputs are currently let to the user, a
 recommended place would be the end of the site configuration file.\f[R]
 .PP
 This command initializes a new directory called \f[CR]test.org\f[R]:
@@ -233,12 +233,12 @@ repository created in \f[CR].ssh/id_ed25519\-r7\f[R] a
 Adjust the SSH client configuration file in the repository
 \f[CR].ssh/config\f[R]
 .PP
-\f[I]Note that it is possible to import additionnal SSH configurations,
+\f[I]Note that it is possible to import additional SSH configurations,
 like the user one from the SSH configuration, but it is advised to keep
 them separate.\f[R]
 .SS SSH agent handling
 The function \f[CR]unlock\f[R] can be used to set the SSH agent
-environement, this will be required for any automated operation later
+environment, this will be required for any automated operation later
 done by r7:
 .IP
 .EX
@@ -247,9 +247,32 @@ cd test.org
 unlock
 tmux \f[B]||\f[R] screen
 .EE
-.PP
-\f[I]\f[BI]\f[B]Warning:\f[BI]\f[I] Unlock will terminate any running
-\f[CI]ssh\-agent\f[I] instances.\f[R]
+.SS Tmux configuration
+.IP
+.EX
+set \-g update\-environment \-r
+.EE
+.SS Optional Shell configuration
+This is useful for handling multiple tmux sessions.
+.IP
+.EX
+\f[I]# Add this to the shell\[aq]s rc\f[R]
+\f[B]if\f[R] [ \-z \[dq]$TMUX\[dq] ]\f[B];\f[R] \f[B]then\f[R]
+    \f[B]if\f[R] [ \-n \[dq]$SSH_TTY\[dq] ]\f[B];\f[R] \f[B]then\f[R]
+    \f[B]if\f[R] [ \-z \[dq]$SSH_AUTH_SOCK\[dq] ]\f[B];\f[R] \f[B]then\f[R]
+        export SSH_AUTH_SOCK=\[dq]$HOME/.ssh/.auth_socket\[dq]
+    \f[B]fi\f[R]
+    \f[B]if\f[R] [ ! \-S \[dq]$SSH_AUTH_SOCK\[dq] ]\f[B];\f[R] \f[B]then\f[R]
+        eval $(ssh\-agent \-a $SSH_AUTH_SOCK) >/dev/null 2>&1
+        echo $SSH_AGENT_PID >$HOME/.ssh/.auth_pid
+    \f[B]fi\f[R]
+    \f[B]if\f[R] [ \-z $SSH_AGENT_PID ]\f[B];\f[R] \f[B]then\f[R]
+        export SSH_AGENT_PID=$(cat $HOME/.ssh/.auth_pid)
+    \f[B]fi\f[R]
+    ssh\-add \[dq]$SSH_ID\[dq] 2>/dev/null
+    \f[B]fi\f[R]
+\f[B]fi\f[R]
+.EE
 .SS Adding new hosts
 For adding a new host, the simplest way is to have pre\-configured
 \f[CR]authorized_keys\f[R] for the target user, it is then required to
@@ -276,8 +299,6 @@ for the target user (root, by default) and put the
 Once the host is accepted in the \f[CR]known_hosts\f[R] file, it\[cq]s
 possible to import it automatically.
 .SS Importing hosts configurations
-\f[I]This feature currently only support OpenBSD.\f[R]
-.PP
 Avoiding to import the configuration manually is possible with the
 \f[CR]import\f[R] command:
 .IP
@@ -288,7 +309,7 @@ r7 import hostname
 Most common configuration files will be copied in a newly created
 \f[CR]nodes/hostname\f[R] sub\-directory.
 .SS Writing group files
-Group files collects fonctions related to the configuration of the
+Group files collects functions related to the configuration of the
 operating system, networking, services, global and user configurations
 packages installations and application deployments.
 .PP
@@ -321,7 +342,7 @@ doc_A() \f[B]{\f[R]
 \f[I]\f[BI]file\f[I]: \f[CI]groups/example1\f[I]\f[R]
 .PP
 With the default prefix, \f[CR]install\f[R], \f[CR]state\f[R],
-\f[CR]doc\f[R], the fonction that will be executed are
+\f[CR]doc\f[R], the function that will be executed are
 \f[CR]state_A\f[R] and \f[CR]doc_A\f[R].
 To test that group file with all the functions inside we can call r7 the
 following way:
@@ -481,7 +502,7 @@ In other terms, this will update the NTP daemon config
 kept by default, which is the system provided default
 \f[CR]ntpd.conf\f[R].
 .SS Sourcing specific files
-Here\[cq]s an example how to source additionnal shell from the deployed
+Here\[cq]s an example how to source additional shell from the deployed
 node directory, or elsewhere:
 .IP
 .EX
@@ -590,7 +611,7 @@ $ r7 output tools0 OpenBSD state_packages\[rs]*
 .EE
 .PP
 \f[I]Note that the \f[CI]output\f[I] function arguments are using
-shell\[cq]s case globbing patterns.\f[R]
+shell\[cq]s case glob patterns.\f[R]
 .SS Active nodes
 A \f[CR]R7_WORKDIR/.active_nodes\f[R] file is automatically created when
 r7 tries to connect to a list of hosts via the \f[CR]group\f[R] command
@@ -955,7 +976,7 @@ returns 31
 node [filename\f[B]|\f[R]dirname]
 .EE
 .SS nodename
-\f[B]\f[BI]Description:\f[B]\f[R] Returns the small hostname of the
+\f[B]\f[BI]Description:\f[B]\f[R] Returns the small host name of the
 current host
 .PP
 \f[B]\f[BI]Usage:\f[B]\f[R]
@@ -1021,7 +1042,7 @@ destination
 .EE
 .SS groupinstalldir
 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
-directoy then call installdir
+directory then call installdir
 .PP
 \f[B]\f[BI]Usage:\f[B]\f[R]
 .IP
@@ -1031,7 +1052,7 @@ destination
 .EE
 .SS nodeinstalldir
 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
-directoy then call installdir
+directory then call installdir
 .PP
 \f[B]\f[BI]Usage:\f[B]\f[R]
 .IP
@@ -1039,14 +1060,14 @@ directoy then call installdir
 nodeinstalldir [\-o fileowner] [\-m filemode] [\-O dirowner] [\-O dirmode] source
 destination
 .EE
-.SS source
+.SS fsource
 \f[B]\f[BI]Description:\f[B]\f[R] Source a POSIX shell file in the
 current execution
 .PP
 \f[B]\f[BI]Usage:\f[B]\f[R]
 .IP
 .EX
-source filename
+fsource filename
 .EE
 .SS groupsource
 \f[B]\f[BI]Description:\f[B]\f[R] Change directory to the current group
@@ -1263,7 +1284,7 @@ ssh\-authorized\-keys
 .EE
 .SS ssh\-ids\-hosts
 \f[B]\f[BI]Description:\f[B]\f[R] Returns SSH IDs along with matching
-keyfile and hostname
+key file and host name
 .PP
 \f[B]\f[BI]Usage:\f[B]\f[R]
 .IP
@@ -1527,21 +1548,69 @@ import HOST
    *   *   *   *   *
 .SS Technical notes
 .IP \[bu] 2
-Supported shells are ksh93, oksh, yash and bash.
+Supported shells are ksh93, oksh, yash and bash
 .IP \[bu] 2
-Supported platforms are OpenBSD, FreeBSD, NetBSD and GNU/Linux.
+Supported target platforms are POSIX compatible systems
+.RS 2
 .IP \[bu] 2
+\f[CR]/bin/sh\f[R] or compatible must be set for the user\[cq]s shell
+(which is usually the case by default)
+.IP \[bu] 2
+\f[CR]/tmp\f[R] must be writable by the user
+.RE
+.IP \[bu] 2
+Supported control node platforms are supposed to be POSIX compatible
+systems but currently limited to BSD\[cq]s, Darwin and GNU/Linux
+.RS 2
+.IP \[bu] 2
 Dependencies are awk, OpenSSH and column
 .IP \[bu] 2
-Optional dependencies are openrsync, rsync, column, graphviz and pandoc.
+Optional dependencies are openrsync, rsync, column, graphviz and pandoc
+.RE
 .IP \[bu] 2
-Busybox support is planned.
+The r7 importer supports the following platform:
+.RS 2
 .IP \[bu] 2
-The HTML output is a work in progress.
+Alpine Linux
+.IP \[bu] 2
+Archlinux
+.IP \[bu] 2
+Crux
+.IP \[bu] 2
+Debian
+.IP \[bu] 2
+DragonFlyBSD
+.IP \[bu] 2
+FreeBSD
+.IP \[bu] 2
+Gentoo
+.IP \[bu] 2
+Guix
+.IP \[bu] 2
+Haiku
+.IP \[bu] 2
+Minix
+.IP \[bu] 2
+NetBSD
+.IP \[bu] 2
+Omnios
+.IP \[bu] 2
+OpenBSD
+.IP \[bu] 2
+OpenSUSE
+.IP \[bu] 2
+QNX
+.IP \[bu] 2
+Rocky Linux
+.IP \[bu] 2
+Salix
+.IP \[bu] 2
+Void Linux
+.RE
 .PP
    *   *   *   *   *
 .SS License
-The provided group library is shared as additionnal examples WITH NO
+The provided group library is shared as additional examples WITH NO
 WARRANTIES of the documentation and contain the following third\-party
 files under the ISC License.
 Copyright information are indicated in the LICENSE section of related