sshrc, utiliser vos fichiers de configuration dans des sessions SSH
sshrc apporte une réponse à 2 problématiques :
- Vous souhaitez pouvoir utiliser votre configuration locale aux petits oignons (alias, fonctions, variables d’environnement, bashrc, vimrc, inputrc, screenrc, etc.) lorsque vous êtes connectés sur les pc/serveurs que vous administrez. Cependant vous désirez ne pas toucher aux fichiers de configuration de ces pc/serveurs car vous ne pouvez pas (contexte professionnel) ou vous ne voulez pas. De plus plusieurs personnes se connectent au(x) même(s) compte(s), il faut respecter l’usage de chacun et ne pas imposer vos fichiers de configuration aux autres
- Au contraire vous avez décidé d’utiliser vos fichiers de configuration (aussi appelés dotfiles) mais passer sur X pc/serveurs pour modifier un de vos fichiers de configuration ça vous gonfle et vous trouvez la gestion de configuration (Ansible, Puppet, Git + liens symboliques…) trop lourde pour si peu
Alors sshrc est fait pour vous. Sur votre poste vous allez créer un fichier ~/.sshrc
dans lequel vous allez exporter/sourcer votre configuration personnalisée et un dossier ~./sshrc.d
où vous allez placer vos fichiers de configuration (.bashrc, .vimrc, .inputrc, etc.). Au lieu de vous connecter sur ces pc/serveurs avec la commande ssh, vous allez vous connecter avec la commande sshrc (no stress c’est propre). Un dossier /tmp/.cascador.sshrc.XXXX
unique (XXXX généré aléatoirement) sera créé sur l’hôte distant, votre configuration personnalisée sera envoyée dedans (avec openssl) puis chargée. A la déconnexion ce dossier sera supprimé.
sshrc est un script shell sous licence MIT aisément maintenable, compréhensible et lisible. Il nécessite comme prérequis openssl sur l’hôte local et distant. Il existe également moshrc pour Mosh. Voici le code source.
#!/usr/bin/env bash function sshrc() { local SSHHOME=${SSHHOME:=~} if [ -f $SSHHOME/.sshrc ]; then local files=.sshrc if [ -d $SSHHOME/.sshrc.d ]; then files="$files .sshrc.d" fi SIZE=$(tar cfz - -h -C $SSHHOME $files | wc -c) if [ $SIZE -gt 65536 ]; then echo >&2 $'.sshrc.d and .sshrc files must be less than 64kb\\ncurrent size: '$SIZE' bytes' exit 1 fi if [ -z "$CMDARG" -a ! -e ~/.sshrc.d/.hushlogin ]; then WELCOME_MSG=" if [ ! -e ~/.hushlogin ]; then if [ -e /etc/motd ]; then cat /etc/motd; fi if [ -e /etc/update-motd.d ]; then run-parts /etc/update-motd.d/ 2>/dev/null; fi last -F \\$USER 2>/dev/null | grep -v 'still logged in' | head -n1 | awk '{print \\"Last login:\\",\\$4,\\$5,\\$6,\\$7,\\$8,\\"from\\",\\$3;}' fi " else WELCOME_MSG="" fi ssh -t "$DOMAIN" $SSHARGS " command -v openssl >/dev/null 2>&1 || { echo >&2 \\"sshrc requires openssl to be installed on the server, but it's not. Aborting.\\"; exit 1; } $WELCOME_MSG export SSHHOME=\\$(mktemp -d -t .$(whoami).sshrc.XXXX) export SSHRCCLEANUP=\\$SSHHOME trap \\"rm -rf \\$SSHRCCLEANUP; exit\\" 0 echo $'"$(cat "$0" | openssl enc -base64)"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/sshrc chmod +x \\$SSHHOME/sshrc echo $'"$( cat << 'EOF' | openssl enc -base64 if [ -r /etc/profile ]; then source /etc/profile; fi if [ -r ~/.bash_profile ]; then source ~/.bash_profile elif [ -r ~/.bash_login ]; then source ~/.bash_login elif [ -r ~/.profile ]; then source ~/.profile fi export PATH=$PATH:$SSHHOME source $SSHHOME/.sshrc; EOF )"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/sshrc.bashrc echo $'"$( cat << 'EOF' | openssl enc -base64 #!/usr/bin/env bash exec bash --rcfile <(echo ' [ -r /etc/profile ] && source /etc/profile if [ -r ~/.bash_profile ]; then source ~/.bash_profile elif [ -r ~/.bash_login ]; then source ~/.bash_login elif [ -r ~/.profile ]; then source ~/.profile fi source '$SSHHOME'/.sshrc; export PATH=$PATH:'$SSHHOME' ') "$@" EOF )"' | tr -s ' ' $'\\n' | openssl enc -base64 -d > \\$SSHHOME/bashsshrc chmod +x \\$SSHHOME/bashsshrc echo $'"$(tar czf - -h -C $SSHHOME $files | openssl enc -base64)"' | tr -s ' ' $'\\n' | openssl enc -base64 -d | tar mxzf - -C \\$SSHHOME export SSHHOME=\\$SSHHOME echo \\"$CMDARG\\" >> \\$SSHHOME/sshrc.bashrc bash --rcfile \\$SSHHOME/sshrc.bashrc " else echo "No such file: $SSHHOME/.sshrc" >&2 exit 1 fi } function sshrc_parse() { while [[ -n $1 ]]; do case $1 in -b | -c | -D | -E | -e | -F | -I | -i | -L | -l | -m | -O | -o | -p | -Q | -R | -S | -W | -w ) SSHARGS="$SSHARGS $1 $2"; shift ;; -* ) SSHARGS="$SSHARGS $1" ;; *) if [ -z "$DOMAIN" ]; then DOMAIN="$1" else local SEMICOLON=$([[ "$@" = *[![:space:]]* ]] && echo '; ') CMDARG="$@$SEMICOLON exit" return; fi ;; esac shift done if [ -z $DOMAIN ]; then ssh $SSHARGS; exit 1; fi } command -v openssl >/dev/null 2>&1 || { echo >&2 "sshrc requires openssl to be installed locally, but it's not. Aborting."; exit 1; } sshrc_parse "$@" sshrc
Prise en main
On ne s’embête pas avec Git, on se contente de copier sshrc et le placer dans /usr/local/bin
.
wget https://raw.githubusercontent.com/Russell91/sshrc/master/sshrc && chmod +x sshrc && sudo mv sshrc /usr/local/bin/ touch ~/.sshrc && mkdir -p ~/.sshrc.d
Voici mon fichier ~/.sshrc
actuel. Dans le dossier ~/.sshrc.d
j’ai mes .bashrc, .inputrc, .vimrc.
export EDITOR=vim export INPUTRC=$SSHHOME/.sshrc.d/.inputrc export LESS='-FRXi' export LESS_TERMCAP_mb=$'\\E[01;31m' export LESS_TERMCAP_md=$'\\E[01;31m' export LESS_TERMCAP_me=$'\\E[0m' export LESS_TERMCAP_so=$'\\E[01;44;33m' export LESS_TERMCAP_se=$'\\E[0m' export LESS_TERMCAP_us=$'\\E[01;32m' export LESS_TERMCAP_ue=$'\\E[0m' export VIMINIT="let \\$MYVIMRC='$SSHHOME/.sshrc.d/.vimrc' | source \\$MYVIMRC" source $SSHHOME/.sshrc.d/.bashrc if [[ -f ${SSHHOME}/.sshrc.d/.bash_aliases ]]; then source ${SSHHOME}/.sshrc.d/.bash_aliases ; fi if [[ -f ${SSHHOME}/.sshrc.d/.bash_functions ]]; then source ${SSHHOME}/.sshrc.d/.bash_functions ; fi
On se connecte ensuite à un serveur comme ceci sshrc root@blog-libre.org
. Pour retrouver le répertoire sshrc echo $SSHHOME
et s’y déplacer cd $SSHHOME; ls -a
.
Je vous invite à taper « dotfile sshrc » dans votre moteur de recherche préféré pour avoir d’autres exemples : 1, 2, 3, 4, 5.
Deux points négatifs
Il n’est pas possible d’envoyer plus de 64 Ko de fichiers de configuration compressés avec sshrc. Première réaction la peur puis après quelques tests, j’arrive à passer 1 Mo sans problème, le mot important à retenir : compressés. Cependant ça reste un problème important pour certains, on peut citer les plugins Vim par exemple. Dans ce cas l’auteur conseille de copier les fichiers dans un obscur dossier sur le serveur et d’utiliser sshrc pour automatiquement sourcer ces configurations au login.
On a vu que sshrc était bien conçu et propre, il crée un dossier /tmp/.cascador.sshrc.XXXX
unique qu’il supprime à la déconnexion. Cependant pour certains cas, vous serez obligés de « sortir » de ce dossier. Pour nano il n’est pas possible d’exporter un fichier de configuration, il lit seulement /etc/nanorc et ~/.nanorc, il ne possède pas d’option permettant de préciser où se situe (ailleurs) nanorc. On est donc obligé d’aller placer .nanorc dans ~/. Certains font une copie, d’autres créent un lien symbolique, c’est plus propre. Il faut gérer la suppression de ce fichier (on peut modifier trap \\"rm -rf \\$SSHRCCLEANUP; exit\\" 0
entre autres solutions) mais si une autre personne se connecte sous le même compte que vous, il va charger ce fichier de configuration… et puis vous touchez aux fichiers de configuration du pc/serveur (/root/.nanorc pourrait déjà exister par exemple).
Quelques conseils
N’oubliez pas que les fichiers de configuration de votre pc sont probablement différents de ceux de vos serveurs. Typiquement je suis sur Xubuntu et j’administre des serveurs Debian, les versions des paquets sont différentes, les fichiers de configuration également. Je vous invite à copier les fichiers de configuration à partir de vos serveurs dans ~/.sshrc.d
puis les modifier.
N’hésitez pas à abuser de if [ "$(hostname)" == "jessie1" ]; then source ${SSHHOME}/.sshrc.d/.bashrc_jessie1 ; fi
afin de gérer finement vos dotfiles par serveur.
Vous pouvez créer des liens symboliques au lieu de copier certains fichiers de configuration dans ~/.sshrc.d
. Personnellement j’ai fait ln -s ~/.inputrc ~/.sshrc.d/.inputrc
pour inputrc. Ça me permet ainsi d’avoir mes raccourcis claviers personnalisés en fonction du poste sur lequel je suis (touches utilisées différentes si je suis sur mon pc portable).
Je vous invite à lire ce fil sur Hacker News autour de sshrc, il y a des réflexions intéressantes. Je me demande notamment dans quelle mesure on peut charger des fichiers de configuration (rendus disponibles par un serveur web) avec wget/curl. A noter le reddit dotfiles, the unofficial guide to doing dotfiles on GitHub, awesome-shell et tant qu’à faire awesome.