Un pour les unir tous
Avant c’était pas si mieux
Combien de fois en voulant installer un logiciel quelconque sur une machine debian, je suis tomber sur une
instruction du genre: curl https://www.closeyoureye.org/random_script.sh | bash
La seule attitude décente face à une telle ligne de commande est de:
- lever les yeux au ciel;
- télécharger le script random dont l’url est fournie;
- ouvrir le script téléchargé avec son éditeur préféré;
- extraire les instructions qui concernent notre distribution;
- les exécuter manuellement, ou depuis un nouveau script.
La découverte
Et puis un jour, en voulant installer une alternative à Firefox, je tombe sur autre chose. Cette fois-ci les instructions sont:
sudo apt update && sudo apt install extrepo -y sudo extrepo enable librewolf sudo apt update && sudo apt install librewolf -y
Comme son nom l’indique, extrepo est un paquet debian qui permet d’ajouter facilement des dépôts extérieurs. Les dépôts pris en charge par cet outil sont gérés dans un répertoire git dédié. On peut y voir la liste des logiciels rendus ainsi disponibles. En voici un petit extrait appétissant:
- Crowdsec
- Docker
- Fai
- HAProxy
- Kubernetes
- Nodejs
- Postgresql
- Signal
- Wine HQ
Avant de commencer il vous faudra peut-être jouer avec la configuration du logiciel dans
/etc/extrepo/config.yaml
pour viser la bonne version de debian et éventuellement ajouter les dépôts
contrib
ou non-free
. Vous pourrez aussi installer extrepo-offline-data
pour
éviter des requêtes web à chaque utilisation de l’outil.
Les deux commandes principales à connaître sont extrepo search
et extrepo enable
.
En guise de conclusion j’espère juste que le répertoire git contenant la liste des dépôts et leurs clefs publiques est surveillé comme du petit lait sur le feu par les équipes debian. La sécurité de bien des serveurs en ligne est dépend.
Récupération d’information rapide
Nouveaux serveurs à gérer
Je viens de récupérer plusieurs machines à gérer. Je n’ai qu’un accès ssh à chaque machine, et une description sommaire de son rôle. Hors j’aimerais savoir rapidement de quoi est capable chaque serveur:
- combien a-t-il de RAM?
- les partitions,
- l’espace disponible sur les disques,
- le nombre de processeurs,
- etc.
L’outil
Après quelques recherches je suis tombé sur l’outil magique qui fait tout ça: inxi. Écris en perl, inxi va récupérer toutes les informations dans l’arborescence
/proc/
et /dev/
pour nous présenter une synthèse lisible par nous, pauvres humains.
Pour mes serveurs, je l’utilise avec les options -C -D -j -m -p -S -n -o -R
inxi -C -D -j -m -p -S -n -o -R
Mais il existe d’autres options pour afficher à peu près tout: les besoins ne sont pas les même pour un desktop et pour un serveur.
L’avantage qu’il soit écrit en perl, c’est qu’on peut simplement copier l’exécutable sur un serveur et le lancer ensuite directement, sans avoir à installer tout le paquet.
Un tunnel low cost
Besoin de tunnel
La dernière mode chez les développeurs, c’est d’exposer publiquement son environnement local, généralement une application web en cours d’écriture. De mon côté, il m’a été demandé de travailler sur un système de paiement dont la configuration nécessitait que ma machine de développement soit accessible au service de paiement.
Il m’a été proposé d’utiliser les tunnels Cloudflare, ou bien d’installer ngrok. Mais ces deux solutions, ainsi que leurs multiples alternatives, me semblaient «/overkill/» pour mon simple besoin. J’ai donc préféré m’amuser à implémenter une solution plus modeste et sur mesure, que je vais présenter ci-après.
Solution maison
Je contrôle déjà un serveur web qui est accessible publiquement sur internet. C’est le serveur web qui héberge le
blog sur lequel vous êtes certainement en train de lire cet article. Mon objectif va être d’utiliser ce serveur comme
proxy web sur un nom de domaine dédié, qui transmettra toutes les requêtes vers mon serveur de développement, qui lui
tournera sur mon portable dans des containers configurés avec docker-compose
.
Configuration DNS
La première étape consiste donc à faire pointer le nom de domaine sous lequel on veut rendre accessible notre environnement de développement vers ce serveur.
Par convention je vais utiliser les noms suivants:
-
my-web-server.net
: le nom de domaine de mon serveur web public; -
dev1.devs.my-web-server.net
: le nom de domaine sous lequel l’environnement de développement sera accessible.
L’enregistrement DNS à créer ressemblera à quelque chose comme: *.devs.my-web-server.net CNAME
my-web-server.net
Configuration Caddy
Mon serveur web utilise Caddy. Ici je vais utiliser deux fonctionnalités de cet outil particulièrement pratiques:
- en déclarant un nom de domaine ouvert sur le port
443
, Caddy récupère automatiquement le certificat Letsencrypt! - Un reverse proxy se configure en une seule ligne.
La section de ma configuration Caddy dédiée au tunnel ressemble à ceci:
dev1.devs.my-web-server.net:80, dev1.devs.my-web-server.net:443 { log { output file /var/log/caddy/dev1-devs.log } reverse_proxy { to 127.0.0.1:8888 } }
Configuration Docker avec le certificat
Lorsque mon application web sera accessible depuis l’extérieur, Caddy va utiliser le certificat généré par Letsencrypt pour sécuriser la connexion. Mais lorsque j’accède à cette même application en local depuis mon portable, c’est au serveur web qui tourne dans Docker de s’en occuper. Pour cela ce serveur a aussi besoin des fichiers du certificat.
Ces fichiers (la clé publique et la clé privée) se trouvent dans le sous répertoire
dev1.devs.my-web-server.net
du répertoire
/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/
Il faut les copier
en local, puis les insérer dans le container qui fera tourner le serveur web.
Dans le Dockerfile
du serveur web on trouvera donc quelque chose qui ressemble à:
COPY certs/dev1.devs.my-web-server.net.crt /usr/local/apache2/conf/dev1.devs.my-web-server.net.crt COPY certs/dev1.devs.my-web-server.net.key /usr/local/apache2/conf/dev1.devs.my-web-server.net.key
Dans mon cas particulier l’application en local est servie par un serveur apache. La configuration de ce serveur ressemble à ceci:
<VirtualHost _default_:443> DocumentRoot "/var/www/my-app/" ServerName dev1.devs.my-web-server.net SSLEngine on <Directory "/var/www/my-app/"> AllowOverride All Require all granted </Directory> SSLCertificateFile "/usr/local/apache2/conf/dev1.devs.my-web-server.net.crt" SSLCertificateKeyFile "/usr/local/apache2/conf/dev1.devs.my-web-server.net.key" Protocols h2 http/1.1 </VirtualHost>
Modification du fichier /etc/hosts
Pour pouvoir travailler localement, sans passer par le proxy, il faut associer l’adresse IP du container apache au
nom de domaine dev1.devs.my-web-server.net
. On récupère cette adresse avec la commande suivante:
docker inspect \ --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \ $(docker compose ps -q apache)
Connexion ssh
La dernière étape consiste à créer le tunnel, avec SSH, entre notre machine locale et le serveur web:
ssh -R 8888:127.0.0.1:8351 my-web-server.net
Ici on a:
-
8351
le port ouvert de notre serveur web dans votre docker-compose; -
8888
le port qui est dans la configuration reverse proxy de Caddy.
Et voilà!
Aller plus loin
Il ne semble pas trop difficile de bricoler une solution qui automatise un peu toutes ces étapes. D’ailleurs c’est
pour cela que j’ai déclaré le domaine *.devs.my-web-server.net
dans ma configuration dns, au lieu de
dev1.my-web-server.net
. Ainsi je peux ajouter plus facilement d’autres domaines sans modifier mon serveur
DNS. Je n’aurais ensuite que les modifications de la configuration Caddy et de docker à programmer. Pour le moment, avec
un seul environnement à rendre accessible, je n‘ai pas besoin d’automatiser plus.
Post Scriptum
Après avoir écrit cet article, je découvre un projet qui met en œuvre exactement le même procédé que moi, avec un début d’automatisation.
Nouvel outil de traduction hors ligne
Le besoin
Vivant et travaillant en Allemagne, utilisant les langues anglaise et allemande de manière professionnelle, le français et l’allemand dans la sphère privée, je suis un utilisateur pas très modéré des outils de traduction en ligne.
Aussi l’annonce d’un outil de traduction hors ligne basé sur des travaux universitaires par Mozilla m’a enchanté. La description technique de la conception de l’outil est intéressante à lire.
Malheureusement l’outil n’est distribué que sous la forme d’une extension Firefox, et le dépôt git et les explications pour obtenir une application indépendante est indigeste. «Hillariously difficult to use» pour rependre le titre d’un rapport un bogue, dont une réponse pointe vers Kotki, un projet dérivé qui promet de simplifier l’utilisation de l’outil.
L’outil
L’installation de Kotki se déroule en deux partie. Au niveau système, en tant que root:
apt install -y cmake ccache build-essential git pkg-config \ rapidjson-dev pybind11-dev libyaml-cpp-dev python3-dev \ python3-virtualenv libopenblas-dev libpcre2-dev \ libprotobuf-dev protobuf-compiler libsqlite3-dev pip3 install kotki -v
En tant qu’utilisateur, il faut ensuite télécharger les «modèles» permettant de traduire d’une langue à l’autre:
mkdir -p ~/.config/kotki/models/ cd /tmp/ # Voir https://github.com/kroketio/kotki/releases wget https://github.com/kroketio/kotki/releases/download/0.6.0/kotki_models_0.3.3-tiny.zip unzip kotki_models_0.3.3-tiny.zip -d ~/.config/kotki/models
Personnellement je télécharge la version tiny
du fichier, parce que le
fichier contient les modèles de traduction dont j’ai besoin. Si vous êtes
intéressé par le russe ou l’ukrainien, la version complète sera nécessaire:
wget https://github.com/kroketio/kotki/releases/download/0.6.0/kotki_models_0.3.3-tiny.zip unzip kotki_models_0.3.3.zip -d ~/.config/kotki/models
Utilisation
Ça marche plutôt pas mal:
kotki-cli -i "Longtemps je me suis couché de bonne heure." # For a long time I went to bed early. kotki-cli -m enfr -i "For a long time I went to bed early." # Pendant longtemps, je suis allé me coucher tôt. kotki-cli -i \ "Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte, \ fand er sich in seinem Bett zu einem ungeheueren Ungeziefer \ verwandelt." # One morning, when Gregor Samsa awoke from troubled dreams, # he found himself in his bed turning into a monstrous vermin. kotki-cli -m ende -i \ "One morning, when Gregor Samsa awoke from troubled dreams,\ he found himself in his bed turning into a monstrous vermin." # Eines Morgens, als Gregor Samsa aus unruhigen Träumen erwachte, # fand er sich in seinem Bett wieder, das sich in ein # ungesäuertes Ungeziefer verwandelte.
Mais l’allemand, n’est pas encore très au point.
Une autre critique: l’anglais est pivot. Il n’existe pas (encore?) de modèle permettant de traduire de l’allemand vers le français ou du français vers l’allemand.
Utiliser l’historique Bash
Apperçu rapide
Bash propose des raccourcis bien utiles pour relancer des commandes, ou des bouts de commandes, précédemment exécutées. Cette page va recenser ceux que j’ai trouvés les plus utiles jusqu’à présent.
Voici quelques exemples d’usage:
# Relance la dernière commande en la faisant précéder par sudo sudo !! # Opération inverse: relancer la dernière commande sudo sans sudo !* # Pour modifier le dernier fichier visualisé avec less !less:s/less/vi/
Tableau récapitulatif
Et voici un tableau à garder sous la main en cas de besoin
!! | dernière commande |
!rm | dernière commande qui commence par rm
|
!?force? | dernière commande qui contient force
|
!$ | dernier argument de la dernière commande executée |
!^ | premier argument de la dernière commande executée |
!* | tous les arguments de la dernière commande executée (synonymes: !!:1* !!:1-$ !!:* ) |
!scp$ | dernier argument de la dernière commande qui commence par scp
|
!scp^ | premier argument de la dernière commence qui commence par scp
|
:p | affichage au lieu d’exécuter |
:h | dirname (head) |
:t | filename (tail) |
:r | enlève l’extension (peut être utilisé deux fois pour des fichiers tar.gz ) |
:e | retourne l’extension seulement |
^search^replace | remplace search par replace dans la dernière commande |
!rm:s/search/replace/ | remplace search par replace dans la dernière commande commençant par rm
|
!rm:sg/search/replace/ | remplace partout … |
sudo !! | relance la commande précédente avec sudo
|
chmod +x !$ | un exemple parmi mille de l’utilisation du racourci !$
|
!scp^:h | le chemin du fichier copié par scp (si le fichier était le premier argument à scp ie il n’y avait pas d’options) |
!grunt:2-$:p | affichage tous les arguments sauf le premier de la dernière commande commençant par grunt
|