Administration systèmes

Bases de données : MySQL

Bases de données : MySQL

Défragmenter les tables

Si vous avez accès au terminal

mysqlcheck --optimize --all-databases

Si vous n’avez pas accès au terminal

Pour trouver les tables à défragmenter :

USE information_schema;

SELECT TABLE_SCHEMA,TABLE_NAME FROM TABLES
  WHERE TABLE_SCHEMA NOT IN ("information_schema","mysql") AND Data_free > 0;

Pour défragmenter les tables :

OPTIMIZE TABLE nom_de_la_table;
Bases de données : MySQL

Optimiser MySQL avec Mysqltuner

mysqltuner.pl est un script Perl qui va analyser vos bases, la configuration de MySQL et ses statistiques pour vous fournir des indications de modifications de configuration, des actions à prendre, des conseils pour vos requêtes SQL…

C’est très simple à installer et utiliser, même si ça ne fait pas de miracles, MySQL étant ce qu’il est (quoi, ça se voit que j’aime pas MySQL ? 😛)

Ça se passe là pour l’installation : https://github.com/major/MySQLTuner-perl#downloadinstallation

Et pour l’utilisation : https://github.com/major/MySQLTuner-perl#specific-usage

Bases de données : PostgreSQL

Bases de données : PostgreSQL

Migration d’une version majeure de PostgreSQL à une autre

NB : instructions pour le passage de PostgreSQL 9.6 à PostgreSQL 11 (Debian Buster). Voir ici pour de 9.1 à 9.4 (Debian Jessie) et ici pour de 9.4 à 9.6 (Debian Stretch).

NB : mettez vous dans un tmux avant de commencer la procédure. Prudence est mère de sûreté.

NB : si vous utilisez l’extension PostGis, optez pour la méthode moins rapide, ça vous évitera bien des soucis.

Attention !

Quand on fait la mise à jour vers Debian Buster, il est nécessaire de réindexer les bases. On a d’ailleurs ce message à l’installation de PostgreSQL 11 :

  Existing PostgreSQL databases need to be reindexed

  When upgrading from stretch to buster, the glibc locale data is upgraded.
  Specifically, this changes how PostgreSQL sorts data in text indexes. To
  avoid corruption, such indexes need to be REINDEXed immediately after
  upgrading the locales or locales-all packages, before putting back the
  database into production.

  Suggested command: sudo -u postgres reindexdb --all

  Alternatively, upgrade the databases to PostgreSQL 11 using
  pg_upgradecluster. (This uses pg_dump by default which will rebuild all
  indexes. Using -m upgrade or pg_upgrade is not safe because it preserves
  the now-wrong index ordering.)

  Refer to the PostgreSQL Wiki for more information:
    https://wiki.postgresql.org/wiki/Locale_data_changes

Donc, dès la fin du apt dist-upgrade on réindexe les bases :

sudo -u postgres reindexdb --all

Méthode rapide

On stoppe les clusters PostgreSQL

service postgresql stop

On vire le cluster de la nouvelle version (normalement vide si on vient juste de l'installer : faire gaffe à ne pas laisser passer de temps entre l'installation de la nouvelle version et la migration des données, pour que personne n'utilise le nouveau cluster)

pg_dropcluster --stop 11 main

On migre les données

pg_upgradecluster -m upgrade 9.6 main

ATTENTION

Si vous avez mis des shared_preload_libraries dans la configuration de votre ancien cluster, il y a des chances que pg_upgradecluster -m upgrade 9.6 main se foire (mais pas si on utilise la méthode dump décrite plus bas.

La solution est simple : créez le répertoire /etc/postgresql/11/main/conf.d et mettez-y un fichier dont le nom se termine par .conf (genre shared_preload_libraries.conf).

Dans ce fichier, mettez la configuration de vos shared_preload_libraries et ça devrait être bon 🙂


Il faut savoir que cette commande copie les données de l’ancien cluster vers le nouveau. Il vous faut donc avoir au moins une fois la place de /var/lib/postgresql/9.6 de disponible. Un contournement est d’utiliser l’option --link qui utilisera des hard links plutôt qu’une copie. Par contre, si quelque chose foire, vous foirez votre ancien cluster avec, c’est donc dangereux.

On redémarre le cluster (le 11 pour le coup) :

systemctl start postgresql

On a normalement déjà réindexé la base en 9.6, donc la copie en 11 devrait avoir un index correct.
Dans le doute (je préfère perdre du temps qu’un cluster PostgreSQL) :

sudo -u postgres reindexdb --all

Allez dans /var/log/postgresql, vous aurez un dossier qui commence par pg_upgrade et qui contiendra deux scripts. Un pour réanalyser votre nouveau cluster, un autre pour supprimer l’ancien. On supprime l’ancien avec apt-get plus loin, vous n’avez donc qu’à lancer le script de réanalyse :

sudo -u postgres /var/log/postgresql/pg_upgradecluster-9.6-11-main.6bmx/analyze_new_cluster.sh

Méthode moins rapide

Cette méthode fait un pg_dump et un pg_restore. C’est infiniment plus long quand on a de grosses bases de données, mais ça donne un cluster bien propre. Tellement propre que des fois ça foire pour cause de clés dupliquées 😑

Vous aurez compris, je n’aime pas tellement cette méthode. Elle a cependant l’avantage d’éviter les problème d’index, vu que ça reconstruit les indexes (ce qui participe à la lenteur de la méthode).

service postgresql start
pg_upgradecluster -m dump 9.6 main

Fin de migration, partie commune aux deux méthodes

On teste les applis qui utilisent PostgreSQL.

Si ça fonctionne, on vire les anciennes données

pg_dropcluster 9.6 main --stop

On vire l'ancienne version de PostgreSQL

apt-get autoremove --purge postgresql-9.6 

Source

Bases de données : PostgreSQL

Utiliser Barman pour sauvegarder la base PostgreSQL d’un Gitlab Omnibus

Barman est un super logiciel de sauvegarde d’un cluster PostgreSQL au fil de l’eau.

Attention : ça ne sauvegarde pas les bases de données une à une, ça sauvegarde tout le cluster PostgreSQL. C’est un peu embêtant de devoir remonter un cluster entier pour récupérer une base ou juste quelques données mais comme c’est un outil surpuissant qui permet de récupérer ses données à la milliseconde près, il est facile de passer outre cet inconvénient.

Pour le côté « au fil de l’eau », ça veut dire que les modifications sont répliquées du cluster PostgreSQL à Barman en temps quasi réél par le biais des WAL.

Il est fort simple de mettre en place la sauvegarde d’un cluster PostgreSQL par Barman. Je vous laisse lire la documentation officielle.

Ce tutoriel vise le cas particulier de la sauvegarde du cluster PostgreSQL d’un serveur Gitlab installé via les paquets Omnibus. Avec cette méthode d’installation, c’est Gitlab qui installe sa version de PostgreSQL, à l’endroit qu’il a choisi, et qui le configure. Toute modification directe des fichiers de configuration de PostgreSQL serait supprimée à la mise à jour suivante. Ma méthode configure proprement PostgreSQL de façon à conserver les modifications par-delà les mises à jour.

Création des utilisateurs

Pas d’utilisateur postgres pour Gitlab, mais gitlab-psql, et les chemins habituels des outils ont changé.

On se logue :

su gitlab-psql -s /bin/bash

Et on crée les utilisateurs :

/opt/gitlab/embedded/bin/createuser -h /var/opt/gitlab/postgresql/ -s -P barman
/opt/gitlab/embedded/bin/createuser -h /var/opt/gitlab/postgresql/ -P --replication streaming_barman

Modification de la configuration

Il faut modifier le fichier /etc/gitlab/gitlab.rb pour que Gitlab configure PostgreSQL pour nous :

De façon un peu bête, dès qu’on fait écouter PostgreSQL sur une interface réseau, Gitlab n’essaye plus de se connecter en socket unix mais par le réseau… donc on va le forcer à utiliser la socket :

gitlab_rails['db_host'] = "/var/opt/gitlab/postgresql/"

Ensuite, c’est l’équivalent de la documentation officielle de Barman :

postgresql['listen_address'] = '0.0.0.0'
postgresql['wal_level'] = "replica"
postgresql['max_wal_senders'] = 3
postgresql['max_replication_slots'] = 3

À l’exception de la façon de créer des entrées dans

postgresql['custom_pg_hba_entries'] = {
  'barman': [{
    type: 'hostssl',
    database: 'all',
    user: 'barman',
    cidr: '203.0.113.42/32',
    method: 'md5'
  }],
  'streaming_barman': [{
    type: 'hostssl',
    database: 'replication',
    user: 'streaming_barman',
    cidr: '203.0.113.42/32',
    method: 'md5'
  }]
}

Puis il suffit de lancer la commande suivante pour que Gitlab reconfigure PostgreSQL (et tout le reste de Gitlab, mais ce n’est pas ce qui nous intéresse) :

gitlab-ctl reconfigure

Logiciels

Logiciels

Bitwarden_rs

Comment compiler et installer proprement le clone de Bitwarden en Rust. Les bases de données disponibles à ce jour sont MySQL et SQLite.

Compilation

On va avoir besoin des backports Debian pour installer npm (pour compiler l’interface web) :

echo "deb http://ftp.debian.org/debian stretch-backports main" | sudo tee /etc/apt/sources.list.d/backports.list
sudo apt update

Installation des dépendances :

sudo apt install pkg-config libssl-dev build-essential
sudo apt install npm

Si vous voulez utiliser MySQL comme base de données :

sudo apt install libmysqlclient-dev

Installation de Rust

Installation de rustup, qui nous fournira le compilateur Rust :

curl https://sh.rustup.rs -sSf > rustup.sh

On n’exécute pas direct un script tiré du web ! On regarde d’abord s’il ne va pas faire de saloperies :

vi rustup.sh

On le rend exécutable :

chmod +x rustup.sh

On installe le compilateur Rust (il sera dans notre $HOME) :

./rustup.sh --default-host x86_64-unknown-linux-gnu --default-toolchain nightly

On source un fichier qui nous permet de l’appeler

source $HOME/.cargo/env

Mise à jour de Rust (si vous l’avez déjà installé via rustup)

rustup update

Compilations

Gagnons du temps en clonant le projet bitwarden_rs et l’interface web (qu’il faut compiler aussi) en même temps .

git clone https://github.com/dani-garcia/bitwarden_rs
git clone https://github.com/bitwarden/web.git web-vault

Compilation de Bitwarden_rs :

cd bitwarden_rs
cargo build --release --features sqlite # ou mysql, selon la bdd que vous souhaitez utiliser

Le résultat de la compilation est dans bitwarden_rs/target/release/.

Compilation de l’interface web :

cd ../web-vault
# On se positionne sur le dernier tag en date
git checkout -b "$(git tag --sort=v:refname | tail -n1)" "$(git tag --sort=v:refname | tail -n1)"
# Un petit patch pour que ça fonctionne avec notre installation
# Attention, regardez https://github.com/dani-garcia/bw_web_builds/tree/master/patches
# et ce que donne `git tag --sort=v:refname | tail -n1` pour choisir la version de patch la plus proche de votre version de web-vault
wget https://raw.githubusercontent.com/dani-garcia/bw_web_builds/master/patches/v2.12.0.patch
# On vérifie le patch
cat v2.12.0.patch
git apply v2.12.0.patch
npm run sub:init
npm install
npm run dist

ATTENTION : on m’a dit que la compilation de l’interface web prenait 1,5Gio de RAM, assurez-vous que vous en avez assez de libre.

Et on copie l’interface web dans le dossier où attend le résultat de la compilation de bitwarden_rs :

cp -a build/ ../bitwarden_rs/target/release/web-vault/

Installation

On va installer Bitwarden_rs dans /opt/bitwarden et on le fera tourner avec l’utilisateur www-data :

cd ..
sudo rsync -a --info=progress2 bitwarden_rs/target/release/ /opt/bitwarden/
sudo chown -R www-data: /opt/bitwarden

Puis on va créer un service systemd, /etc/systemd/system/bitwarden.service :

[Unit]
Description=Bitwarden Server (Rust Edition)
Documentation=https://github.com/dani-garcia/bitwarden_rs
After=network.target

[Service]
# The user/group bitwarden_rs is run under. the working directory (see below) should allow write and read access to this user/group
User=www-data
Group=www-data
# The location of the .env file for configuration
EnvironmentFile=/etc/bitwarden_rs.env
# The location of the compiled binary
ExecStart=/opt/bitwarden/bitwarden_rs
# Set reasonable connection and process limits
LimitNOFILE=1048576
LimitNPROC=64
# Isolate bitwarden_rs from the rest of the system
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
ProtectSystem=strict
# Only allow writes to the following directory and set it to the working directory (user and password data are stored here)
WorkingDirectory=/opt/bitwarden/
ReadWriteDirectories=/opt/bitwarden/

[Install]
WantedBy=multi-user.target

Pour l’interface d’administration, on va créer un token avec :

openssl rand -base64 48

La configuration se fait via des variables d’environnement qu’on va mettre dans /etc/bitwarden_rs.env :

SIGNUPS_ALLOWED=false
WEBSOCKET_ENABLED=true
ADMIN_TOKEN=Un token généré avec `openssl rand -base64 48`
ROCKET_ADDRESS=127.0.0.1
WEBSOCKET_ADDRESS=127.0.0.1
SMTP_HOST=127.0.0.1
SMTP_FROM=bitwarden@example.org
SMTP_PORT=25
SMTP_SSL=false

Vous remarquerez que je dis à Bitwarden d’envoyer les mails via le serveur SMTP local. À vous de faire en sorte qu'il fonctionne. Allez voir le wiki du projet ou le modèle de fichier d’environnement pour voir quelles variables vous pourriez ajouter, enlever, modifier…

Puis :

sudo systemctl daemon-reload
sudo systemctl enable bitwarden
sudo systemctl start bitwarden
sudo systemctl status bitwarden

Nginx

On installe Nginx s’il n’est pas déjà installé :

sudo apt install nginx

Configuration du virtualhost :

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name bitwarden.example.org;

    access_log /var/log/nginx/bitwarden.access.log;
    error_log /var/log/nginx/bitwarden.error.log;

    ssl_certificate      /etc/letsencrypt/live/bitwarden.example.org/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/bitwarden.example.org/privkey.pem;

    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:5m;

    ssl_prefer_server_ciphers On;
    ssl_protocols TLSv1.2;
    ssl_ciphers 'EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA';

    ssl_dhparam /etc/ssl/private/dhparam4096.pem;
    add_header Strict-Transport-Security max-age=15768000; # six months
    gzip off;

    if ($https != 'on') {
        rewrite ^/(.*)$ https://bitwarden.example.org/$1 permanent;
    }

    root /var/www/html;

    # Allow large attachments
    client_max_body_size 128M;

    location ^~ '/.well-known/acme-challenge' {
        default_type "text/plain";
        root /var/www/certbot;
    }

    location / {
        include /etc/nginx/proxy_params;
        ## /etc/nginx/proxy_params contient normalement ceci :
        #proxy_set_header Host $http_host;
        #proxy_set_header X-Real-IP $remote_addr;
        #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        #proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:8000;
    }

    location /notifications/hub {
        include /etc/nginx/proxy_params;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://127.0.0.1:3012;
    }

    location /notifications/hub/negotiate {
        include /etc/nginx/proxy_params;
        proxy_pass http://127.0.0.1:8000;
    }
}

Pour créer /etc/ssl/private/dhparam4096.pem :

sudo openssl dhparam -out /etc/ssl/private/dhparam4096.pem 4096

Pour le certificat Let’s Encrypt, on commente le brol relatif à ssl puis :

sudo nginx -t && sudo nginx -s reload
sudo apt install certbot
sudo mkdir /var/www/certbot/
certbot certonly --rsa-key-size 4096 --webroot -w /var/www/certbot/ --agree-tos --text --renew-hook "/usr/sbin/nginx -s reload" -d bitwarden.example.org

Une fois qu’on a le certificat, on décommente le brol ssl puis :

sudo nginx -t && sudo nginx -s reload

Sauvegarde

Créer le script de sauvegarde /opt/backup_bitwarden.sh :

#!/bin/bash
function bwbackup {
    DATE=$(date '+%a%H')

    # Database
    if [[ ! -d /opt/backup_bitwarden/sqlite-backup/ ]]
    then
        mkdir -p /opt/backup_bitwarden/sqlite-backup/
    fi
    echo ".backup /opt/backup_bitwarden/sqlite-backup/db.${DATE}.sqlite3" | sqlite3 /opt/bitwarden/data/db.sqlite3 2>> /opt/backup_bitwarden/backup.log
    if [[ "$?" -ne "0" ]]
    then
        echo "Something went wrong with bitwarden database backup, please see /opt/backup_bitwarden/backup.log on verity" | mail -s "Bitwarden database backup" youraddress@mail.example.org
        bwbackup
    fi

    # Files
    if [[ ! -d /opt/backup_bitwarden/files-backup/ ]]
    then
        mkdir -p /opt/backup_bitwarden/files-backup/
    fi
    rsync -a --delete --exclude db.sqlite3 /opt/bitwarden/data/ /opt/backup_bitwarden/files-backup/$DATE/ 2>> /opt/backup_bitwarden/backup.log
    if [[ "$?" -ne "0" ]]
    then
        echo "Something went wrong with bitwarden files backup, please see /opt/backup_bitwarden/backup.log on verity" | mail -s "Bitwarden files backup" youraddress@mail.example.org
        bwbackup
    fi
}
bwbackup

Puis :

sudo chmod +x /opt/backup_bitwarden.sh
sudo mkdir /opt/backup_bitwarden
sudo chown www-data: /opt/backup_bitwarden
sudo apt install sqlite3

Puis, dans le cron de l’utilisateur www-data :

42 4 * * * /opt/backup_bitwarden.sh

Logs

J’aime bien avoir mes logs dans un dossier dédié pour ce genre de service.

Dans /etc/rsyslog.d/bitwarden.conf :

if $programname == 'bitwarden_rs' then /var/log/bitwarden/bitwarden.log
if $programname == 'bitwarden_rs' then ~

Dans /etc/logrotate.d/bitwarden :

/var/log/bitwarden/bitwarden.log
{
        rotate 52
        dateext
        weekly
        missingok
        notifempty
        compress
        sharedscripts
        postrotate
                invoke-rc.d rsyslog rotate > /dev/null
        endscript
}

Puis :

sudo mkdir /var/log/bitwarden
sudo chown root:adm /var/log/bitwarden
sudo service rsyslog restart

Fail2ban

Un fail2ban qui surveille les logs, ça permet de bloquer les petits malins qui font du bruteforce

sudo apt install fail2ban

Dans /etc/fail2ban/filter.d/bitwarden.conf :

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>\. Username:.*$
ignoreregex =

Dans /etc/fail2ban/jail.d/bitwarden.local :

[bitwarden]
enabled = true
port = 80,443
filter = bitwarden
action = iptables-allports[name=bitwarden]
logpath = /var/log/bitwarden/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400

Pour la page d’admin, dans /etc/fail2ban/filter.d/bitwarden-admin.conf :

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*Unauthorized Error: Invalid admin token\. IP: <HOST>.*$
ignoreregex =

Dans /etc/fail2ban/jail.d/bitwarden-admin.local :

[bitwarden-admin]
enabled = true
port = 80,443
filter = bitwarden-admin
action = iptables-allports[name=bitwarden]
logpath = /var/log/bitwarden/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400

Finalement :

sudo service fail2ban restart

Conclusion

Voilà, vous devriez avoir un serveur Bitwarden_rs fonctionnel. Plus qu’à aller sur l’interface web que vous venez de mettre en place ou télécharger les clients et à les utiliser !

Pour importer vos mots de passe de Firefox, il faut passer par une application pour les exporter, puis aller dans les outils de votre client (ou de l’interface web).

Logiciels

Créer une boutique en ligne avec Wordpress

On commence par installer un Wordpress. Je ne vais pas détailler, c’est un sujet fort bien traité sur les Internetz.

Les extensions

Pour transformer Wordpress en boutique en ligne, il faut installer quelques modules. Mais avant ça, voici ceux que j'ai installé pour la sécurité, les performances... :

Ensuite, des extensions pour améliorer la boutique, mais pas obligatoires :

Voici les extensions pour la boutique elle-même :

Le thème

Il va de soit qu'un thème pour un blog a peu de chance d'aller pour faire une boutique. J'ai choisi le thème Shop Isle, que je trouve simple et bien foutu. J'en ai néanmoins fait un thème enfant pour dégager ces cochonneries de google fonts.

Les frais d'envoi

L'extension « WooCommerce Weight Based Shipping » me permet de définir des frais d'envoi selon le poids de la commande ainsi que sa destination (vous imaginez bien qu'envoyer deux cartes postales en France ne coûte pas le même prix qu'en envoyer 15 dans un autre pays).

Cette extension est parfaite, à l'exception de l'interface pour choisir les pays de destination quand on crée les règles : ça va bien quand on ajoute une ou deux destinations, mais pas quand on doit en sélectionner 12 (france métropolitaine + DOM/TOM) ou plus (les pays de l'UE).

Personnellement, j'ai choisi de faire des frais d'envoi à prix plus ou moins coûtant : le tarif des timbres, arrondi un peu au-dessus pour faire le prix de l'enveloppe. Je ne dis pas que je ne fais pas un peu de bénéfice dessus, mais ça se compte à coup de centimes.

Le paiement

WooCommerce embarque déjà plusieurs moyens de paiements, je dois dire que c'est très bien foutu !

J'ai activé le virement SEPA, parce que ça ne coûte rien, ni à l'envoyeur, ni au destinataire. Par contre, comme ça prend du temps (le virement prend généralement 24h pour apparaître sur les comptes, sans compter que certaines banques mettent plusieurs jours pour accepter un nouvel IBAN et permettre des virements vers celui-ci), j'ai ajouté la possibilité d'utiliser Paypal : ça propose d'utiliser son compte Paypal (et c'est assez répandu pour que ça soit pratique pour un paquet de gens) pour payer ou la carte bancaire. Par contre, ça m'a fait deux blagounettes :

Conditions générales de vente

Pour les rédiger, j'ai d'abord cherché sur le web, et je suis tombé sur https://www.donneespersonnelles.fr/cgv, qui propose carrément une extension Wordpress. Après l'avoir installée, je me suis contenté de repomper les CGV qu'elle proposait : ça m'a permis, tout d'abord, de les lire, et ensuite de corriger des typos.

Après quoi, j'ai désinstallé l'extension 😁

Conclusion

Je ne pense pas qu'il soit nécessaire pour moi de trop détailler le réglage des différentes extensions : les infos se trouvent assez facilement sur le web, et même si les réglages sont touffus, c'est assez intuitif. La plus grosse partie du temps fut perdue dans la recherche des extensions et du thème kivonbien.

Après quelques tâtonnements, la mise en place de ma boutique fut assez simple. J'espère que cet article servira à d'autres pour leur éviter de chercher autant que moi.

Logiciels

RequestTracker

RequestTracker (RT) est un outil de tickets extrêmement puissant et flexible. Tellement flexible qu'on en vient à se prendre la tête pour faire des trucs de oufs.

Petit tour des trucs que j'ai mis en place sur un RT 4.4.0.

Utiliser le plus addressing

De façon simple, pour que RT traite les tickets qui arrivent sur l'adresse email dédiée, on la met dans le /etc/aliases de sa machine. Ça fait un truc comme ça :

rt:         "|/opt/rt4/bin/rt-mailgate --queue general --action correspond --url https://rt.example.org/"
rt-comment: "|/opt/rt4/bin/rt-mailgate --queue general --action comment --url https://rt.example.org/"

Vous noterez que cela met les mails à destination de cette adresse dans la queue (ou file) general. Or on utilise généralement plus d'une queue dans un système de ticket : cela permet de diriger automatiquement vers les personnes les plus à même d'y répondre.

Le problème avec ce système, c'est qu'il faudrait ajouter une adresse dédiée à chaque fois que l'on crée une nouvelle file. Ça peut vite devenir usant.

On va donc utiliser le plus addressing. Cette technique, toute bête, consiste à ajouter un discriminant à une adresse mail, précédé généralement d'un + (mais on peut configurer son serveur de mail pour utiliser n'importe quel caractère). rt@example.org aura alors pour alias (par exemple) rt+file_bidule@example.org.

Pour que RT puisse utiliser cette technique, il faut ajouter --extension=queue dans la commande du /etc/aliases :

rt:         "|/opt/rt4/bin/rt-mailgate --extension=queue --queue general --action correspond --url https://rt.example.org/"
rt-comment: "|/opt/rt4/bin/rt-mailgate --extension=queue --queue general --action comment --url https://rt.example.org/"

Voilà ! Il ne vous reste plus qu'à créer vos files via l'interface web. Attention, créez-les avec un nom qui passera dans une adresse mail. Pas d'espace par exemple.

RT récupérera le nom de la file kivabien dans la partie entre le + et le @ et placera automatiquement le ticket dans cette file, tout en gardant la file general par défaut.

Les articles

Quoi de plus casse-pieds que de se répéter encore et encore en donnant toujours la même réponse ? Heureusement il y a les articles qui peuvent vous servir de réponses pré-enregistrées :-)

Création des classes et des articles

Allez dans le menu Administration > Articles > Classes > Ajouter, créez vos classes (j'en ai créé une par file, n'ayant pas réussi à assigner automatiquement des articles aux files), cochez Tous les articles de cette classe doivent être disponibles sous forme de liste sur la page de réponse d'un ticket, décochez Inclure le résumé de l'article et Inclure le nom de l'article et cochez Include le champs personnalisé 'Content' > Value (oh la belle typo de traduction) qui apparaîtra après avoir enregistré la classe (pour ces trois derniers, vous faites comme vous le sentez hein).

Liez la classe à une file via le menu S'applique à.

Voilà, vous n'avez plus qu'à créer vos articles dans la classe que vous venez de créer via le menu Articles > Ajouter.

Et là, magie, lorsque vous répondez via l'interface web, vous pourrez choisir une réponse pré-enregistrée.

Placement des articles dans la réponse

Je suis un grand fan du bottom-posting, mais RT place l'article au-dessus de la citation du message précédent. Remédions à cela.

cd /opt/rt4
mkdir -p local/html/Elements/
cp share/html/Elements/MessageBox local/html/Elements/
vi local/html/Elements/MessageBox

Cherchez la ligne contenant

% $m->comp('/Articles/Elements/IncludeArticle', %ARGS) if $IncludeArticle;

et remplacez-la par

% if ($IncludeArticle) {
%    my $article = $m->scomp('/Articles/Elements/IncludeArticle', %ARGS);
%    $article    =~ s{\n}{<br />}g;
%    $article    = RT::Interface::Email::ConvertHTMLToText($article);
%    $Default   .= $article unless ($Default =~ s/(.*)(-- .*)/$1$article$2/m);
% }

Hop ! votre article se trouve maintenant entre la citation et votre signature :-)

(un redémarrage de RT est peut-être nécessaire pour que cela soit pris en compte)

Ajout des articles pertinents dans le mail de notification d'un nouveau message

Une des forces de RT est de permettre aux intervenants de répondre aux tickets par mail. Le problème est que cela empêche de piocher dans les réponses pré-enregistrées.

Qu'à cela ne tienne, ajoutons-les au mail de notification envoyé aux membres du support.

Allez dans Administration > Global > Modèles > Choisir. Il faut modifier le modèle Notification de modification HTML (oui, j'ai traduit le nom de mes modèles, mais il est simple à repérer, il est utilisé par les scrips 8 et 11).

Ajoutez ceci en bas du modèle :

{ my $hotlist = RT::Articles->new( RT->SystemUser );
  $hotlist->LimitHotlistClasses;
  $hotlist->LimitAppliedClasses( Queue => $Ticket->QueueObj );
  my $content   = "-- \n<p><b>Réponses pré-enregistrées pour cette catégorie de tickets:</b></p>";

  if ($hotlist->Count) {
    while (my $article = $hotlist->Next) {
      $content .= '<p><b>'.$article->Name.'</b><br/>';
      my $class   = $article->ClassObj;
      my $cfs     = $class->ArticleCustomFields;
      my %include = (Name => 1, Summary => 1);
      $include{"CF-Title-".$_->Id} = $include{"CF-Value-".$_->Id} = 1 while $_ = $cfs->Next;
      $include{$_} = not $class->FirstAttribute("Skip-$_") for keys %include;

      while (my $cf = $cfs->Next) {
        next unless $include{"CF-Title-".$cf->Id} or $include{"CF-Value-".$cf->Id};
        my $values = $article->CustomFieldValues($cf->Id);
        if ($values->Count == 1) {
          my $value = $values->First;
          if ($value && $include{"CF-Value-".$cf->Id}) {
            $content .= '<br/>';
            my $c     = $value->Content || $value->LargeContent;
            $c =~ s/\r?\n/<br\/>/g;
            $content .= $c;
          }
        } else {
          my $val = $values->Next;
          if ($val && $include{"CF-Value-".$cf->Id}) {
            $content .= '<br/>';
            my $c     = $value->Content || $value->LargeContent;
            $c =~ s/\r?\n/<br\/>/g;
            $content .= $c;
          }
          while ($val = $values->Next) {
            if ($include{"CF-Value-".$cf->Id}) {
              $content .= '<br/>';
              my $c     = $value->Content || $value->LargeContent;
              $c =~ s/\r?\n/<br\/>/g;
              $content .= $c;
            }
          }
        }
      }
      $content .= "<br/>-----------</p>\n";
    }
  }
  $content;
}
{$content}

C'est moche et long, je sais. Dites-vous que j'ai passé plus d'une après-midi pour trouver ça, la documentation est inexistante pour faire ça.

Les intervenants n'auront plus qu'à copier-coller l'article qui se trouve au bas de leur mail de notification dans leur réponse :-)

Commandes par mail

C'est beau de répondre par mail, mais il faut encore se connecter à l'interface web pour effectuer certaines actions. Comme je suis fier d'être fainéant, j'ai créé un scrip pour autoriser certaines actions par mail.

Mais avant ça, précisions :

Créons donc un scrip. Menu Administration > Scrips > Ajouter.

Dans le Programme de préparation d'action personnalisé: :

if ($self->TransactionObj->Attachments->First->Content =~ m/#(JePrends|Fermeture|Spam|Move:.*)/i) {
    return 1;
} else {
    return 0;
}

Oui, j'aurais pu faire un one-liner, mais il faut que ça reste lisible facilement, et quand on passe des heures à faire des bidouilles comme ça, on apprécie les codes lisibles en un coup d'œil.

Dans le Code d'action personnalisée (commit): :

if ($self->TransactionObj->Attachments->First->Content =~ m/#JePrends/i) {
    if ( $self->TicketObj->OwnerAsString eq '' ) {
        my $id = $self->TransactionObj->Creator;
        $RT::Logger->info("Setting owner to ".$id);
        $self->TicketObj->SetOwner($id, 'SET');
    }
} elsif ($self->TransactionObj->Attachments->First->Content =~ m/#Fermeture/i) {
    $RT::Logger->info("Closing ticket");
    $self->TicketObj->SetStatus('resolved');
} elsif ($self->TransactionObj->Attachments->First->Content =~ m/#Spam/i) {
    my $ticket = $self->TicketObj;
    my ($status, $msg) = $ticket->SetStatus('rejected');
    $RT::Logger->error("Couldn't delete ticket: $msg") unless $status;

    my $requestors = $ticket->Requestor->UserMembersObj;
    while (my $requestor = $requestors->Next) {
        $requestor->SetDisabled(1);
        $RT::Logger->info("Disabling user ".$requestor->Format." because he's likely a spammer");
    }
} elsif ($self->TransactionObj->Attachments->First->Content =~ m/#Move:(.*)/i) {
    my $new_queue = $1;
    my $ticket    = $self->TicketObj;

    my ($result, $msg) = $ticket->SetQueue($new_queue);
    if ($result) {
        $RT::Logger->info("Moving ticket to queue ".$new_queue);
    } else {
        $RT::Logger->error("Error while moving ticket to queue ".$new_queue.": ".$msg);
    }
} elsif ($self->TransactionObj->Attachments->First->Content =~ m/#Merge:(.*)/i) {
    my $target = $1;
    my $ticket = $self->TicketObj;

    $ticket->MergeInto($target);
    $RT::Logger->info("Merging ticket into ticket ".$target);
}

return 1;

Voilà, enregistrez et c'est bon.

Lorsqu'un commentaire contiendra une commande, elle sera exécutée :

Et le spam alors ?

Pour le spam, préparez d'abord un spamassassin pour votre serveur de mails. Ce n'est pas l'objet de cet article, il n'y a qu'à fouiller un peu le web pour trouver des tutos.

On va recréer un scrip, mais avant cela on va créer une nouvelle file nommée spam (menu Administration > Files > Ajouter).

Pour notre nouveau scrip :

Dans le Programme de préparation d'action personnalisé: :

if ( $self->TicketObj->Subject !~ /\[ .* \]/i ) {
  my $inMessage = $self->TransactionObj->Attachments->First;

  # if no message attachment - assume web UI
  return 0 if (!$inMessage);

  # exit if not email message
  return 0 if (!$inMessage->GetHeader('Received'));

  return ($inMessage->GetHeader('X-Spam-Level') =~ m/\*+/) ? 1 : 0;
} else {
  return 1;
}

Dans le Code d'action personnalisée (commit): :

my $spamlevel = $self->TransactionObj->Attachments->First->GetHeader('X-Spam-Level');
if ($spamlevel =~ m/\*\*\*+/) {
  if ($spamlevel =~ m/\*\*\*\*\*/) {
    $RT::Logger->info("This mail seems to be a spam => deleting");
    $self->TicketObj->Delete();
  } else {
    $RT::Logger->info("This mail seems to be a spam => queue spam");
    $self->TicketObj->SetQueue('spam');
  }
}
return 1;

Avec cela, les mails ayant un score de 5 ou plus au spamLevel seront supprimés, et ceux qui ont entre 3 et 5 vont au purgatoire, dans la file spam.

Prenez soin de déplacer ce scrip tout en haut de la liste pour qu'il soit le premier exécuté.

Plugins

En vrac, les plugins que j'utilise :

Les deux premiers sont maintenant intégrés à RT, il n'y a pas besoin de les installer, juste de les configurer. Ils servent respectivement à assurer l'authentification LDAP à l'interface web, et à importer en masse les comptes du LDAP pour permettre à l'administrateur de mettre les collaborateurs dans les bons groupes sans attendre qu'ils se soient logués une première fois.

Le dernier plugin ajoute un S dans le menu des tickets, permettant de les déclarer comme spam d'un simple clic.

Conclusion

On peut faire de merveilleuses choses avec RT, pour peu que l'on ait le temps de fouiller dans la documentation officielle… et dans le code !

Une fois bien configuré, il devrait permettre d'alléger la charge de travail du groupe de support et je peux vous dire que pour en faire depuis plus de deux ans pour Framasoft et bien plus pour mon ancien boulot, ce n'est pas quelque chose à négliger 🙂

NB : bien évidemment, ce superbe logiciel est en Perl :D

Logiciels

Une web radio avec MPD

Rien de plus simple que de faire une web radio pour diffuser sa musique.

MPD

On installe MPD :

apt install mdp

On modifie sa configuration dans /etc/mpd.conf (je ne mets que les paramètres intéressants à modifier) :

# chemin vers le dossier contenant la musique
music_directory "/var/lib/mpd/music"
# Là c’est vous qui voyez. Moi je mets à off pour pas que ça surveille le dossier en permanence
# Je déclenche la mise à jour de la bibliothèque via le client MPD
auto_update "no"
# Zeroconf/avahi, c’est intéressant dans un réseau local, beaucoup moins sur un serveur
zeroconf_enabled "no"
# On commente l’`audio_output` de type `alsa`
# et on décommente celui de type `httpd`
audio_output {
       type            "httpd"
       name            "Ma radio perso"
 #      encoder         "vorbis"                # optional, vorbis or lame
       port            "8000"
       bind_to_address "127.0.0.1"               # optional, IPv4 or IPv6
 #      quality         "5.0"                   # do not define if bitrate is defined
       bitrate         "128"                   # do not define if quality is defined
 #      format          "44100:16:1"
 #      max_clients     "0"                     # optional 0=no limit
}

On redémarre MPD :

systemctl restart mpd

Un client

J’ai tendance à préférer les outils en CLI :

apt install ncmpcpp

Lancez-le.

Pour le reste, lisez l’aide.

Proxifier via Nginx

Pas grand chose de particulier, c’est de la proxification classique :

    location / {
        proxy_set_header Host $host;
        proxy_connect_timeout 300s;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
        proxy_pass http://127.0.0.1:8000/;
    }

(je mets pas toute la configuration Nginx, c’est pas le sujet ici)

Logiciels

TinyTinyRSS : rétablir la consultation web des articles publiés (+ bonus)

On peut, dans TTRSS, publier des articles de ses flux RSS. Cela permet de partager aisément des articles. Les articles sont publiés dans un flux RSS que d’autres personnes pourront à leur tour mettre dans un lecteur de flux RSS.

Je couple cette fonctionnalité avec Feed2toot, qui me permet d’envoyer un pouet sur Mastodon pour chaque nouvel article que je publie.

Le flux RSS généré a longtemps eu un document XSLT associé afin de rendre le flux lisible dans un navigateur web. Ce document XSLT a été supprimé le 28 mars 2020 par le projet TTRSS, mais il est fort simple de le remettre en place.

Ajouter la référence au document XSLT

On va commencer par copier le fichier modèle du flux dans le dossier templates.local : cela permettra de conserver les modifications de ce fichier malgré les mises à jour de TTRSS.

cp templates/generated_feed.txt templates.local/generated_feed.txt

On ajoute alors cette ligne à la ligne 2 du fichier copié :

<?xml-stylesheet type="text/xsl" href="templates.local/atom-to-html.xsl"?>

Vous noterez que je place le document XSLT dans le dossier templates.local : il me semble logique de mettre mes modifications dans un dossier *.local.

Créer le document XSLT

Je suis parti du fichier précédemment fourni par TTRSS, mais je l’ai un peu modifié pour :

Voici mon fichier templates.local/atom-to-html.xsl :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="html"/>

<xsl:template match="/atom:feed">
<html>
  <head>
    <title><xsl:value-of select="atom:title"/></title>
    <link rel="stylesheet" type="text/css" href="themes/light.css"/>
    <link rel="stylesheet" type="text/css" href="themes.local/dark-mode.css"/>
    <script language="javascript" src="lib/xsl_mop-up.js"></script>
  </head>

  <body onload="go_decoding()" class="ttrss_utility">

    <div id="cometestme" style="display:none;">
      <xsl:text disable-output-escaping="yes">&amp;amp;</xsl:text>
    </div>

    <div class="rss">

    <h1><xsl:value-of select="atom:title"/></h1>

    <p class="description">This feed has been exported from
      <a target="_new" class="extlink" href="http://tt-rss.org">Tiny Tiny RSS</a>.
      It contains the following items:</p>

    <xsl:for-each select="atom:entry">
      <h2 id="{atom:id}"><a target="_new" href="{atom:link/@href}"><xsl:value-of select="atom:title"/></a></h2>

      <div name="decodeme" class="content">
        <xsl:value-of select="atom:content" disable-output-escaping="yes"/>
      </div>

      <xsl:if test="enclosure">
        <p><a href="{enclosure/@url}">Extra...</a></p>
      </xsl:if>


    </xsl:for-each>

    </div>

  </body>
 </html>
</xsl:template>

</xsl:stylesheet>

Et voici la feuille de style pour le thème sombre automatique, que je place dans themes.local/dark-mode.css :

@media (prefers-color-scheme: dark) {
    * {
        scrollbar-color: #2a2c2e #1c1e1f;
    }
    html, body, input, textarea, select, button {
        background-color: #181a1b;
    }
    html, body, input, textarea, select, button {
        border-color: #575757;
        color: #e8e6e3;
    }
    body.ttrss_utility {
        background-image: initial;
        background-color: rgb(27, 29, 30);
        color: rgb(232, 230, 227);
    }
    body.ttrss_utility .content {
        background-image: initial;
        background-color: rgb(24, 26, 27);
        border-top-color: rgb(58, 58, 58);
        border-right-color: rgb(58, 58, 58);
        border-bottom-color: rgb(58, 58, 58);
        border-left-color: rgb(58, 58, 58);
        box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 1px -1px;
    }
}

Configuration Feed2toot

Pour l’installation de Feed2toot, je vous laisse regarder la documentation officielle, ce n’est pas l’objet de cet article.

Voici ma configuration Feed2toot, qui poste le lien vers mon flux, le titre de l’article, l’adresse d’origine de l’article et le résumé de l’article :

[mastodon]
instance_url=https://framapiaf.org
user_credentials=/etc/feed2toot/feed2toot_usercred.txt
client_credentials=/etc/feed2toot/feed2toot_clientcred.txt

[cache]
cachefile=/opt/feed2toot.db

[rss]
uri=https://ttrss.fiat-tux.fr/public.php?op=rss&id=-2&key=60c63a21c2928546b4485017876fe850c6ebcebd
toot=[veille] https://lstu.fr/veille-luc#{id} « {title} » {link} {summary}

Notez le #{id} après https://lstu.fr/veille-luc (qui est une URL raccourcie vers mon flux RSS) : cela permet de renvoyer pile à l’article plutôt que de laisser les gens descendre et rechercher l’article 🙂

Mail

Mail

Rspamd

Rspamd est plus qu’un simple antispam : il s’occupera aussi d’ajouter les signatures DKIM et ARC à vos mails sortants et pourra faire la liaison avec un antivirus. C’est un tout-en-un vraiment sympa 🙂

Installation

Je vous laisse aller voir ça sur le site de rspamd.

Création et utilisation de clés DKIM et ARC

Création

NB : par défaut, Rspamd va chercher les clés dans le dossier /var/lib/rspamd/dkim/. Cependant, je préfère les mettre dans le dossier /etc/dkim : on pense plus souvent à sauvegarder /etc que /var/lib/rspamd/.

rspamadm dkim_keygen -k /etc/dkim/example.com.dkim.key -b 2048 -s 'dkim' -d example.com > /etc/dkim/example.com.dkim.txt

À noter, la redirection de la sortie de la commande vers /etc/dkim/example.com.dkim.txt : ce fichier contient l’enregistrement DNS que vous devrez créer pour votre domaine pour déclarer la clé DKIM utilisée.

Cela ressemble à :

dkim._domainkey IN TXT ( "v=DKIM1; k=rsa; "
        "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzgAF2ozDnleUGRbtwmbTEg1zmmoSLhOjsT96q0P+JOrTPnGX/oIWwx2MkTRW46gSU7Ya1ByG9EKfEQo3V+Zfr5xeY+O0ksl8nrHUk56haW7kqVAEhyo4NPqhhTRUheAIMgLbyYlFNOqpQDCdmfyn6fvObK6caqtNXAWy3vWTeMacBgx1JGfrYE1NFyNqKcfHcbtXXfSGNo6phVz9K"
        "1Tll3wvZhdW3hBwgq49cZ5yp0IsrlLOfqMOnHcS83YHlNMRVVGvPko8+ucMhKktbAoDdEMMWupxyWGs1M1xKW0RQxFyYi5oZhSTW53VpyzldrlWXInerDRW2hn1amA2dlWwewIDAQAB"
) ;

Le sélecteur est une clé qui servira, on le voit, dans le nom de l’enregistrement DNS. Il sera indiqué dans l’en-tête de signature DKIM des mails, et donc utilisé par les antispams pour aller chercher le bon enregistrement DNS qui déclare la clé utilisée. Par défaut, pour DKIM, rspamd utilise le sélecteur dkim et je ne vois pas de raison d’en changer (en plus ça ferait des modifications de configuration supplémentaires).

Le sélecteur est aussi utilisé par défaut par rspamd pour choisir la clé à utiliser pour signer les mails.

Pour les clés ARC, c’est tout pareil, mais on change le sélecteur pour arc. Vous pouvez utiliser le même dossier /etc/dkim, c’est ce que je fais.

Utilisation par Rspamd

Si vous avez utilisé /var/lib/rspamd/dkim/ (et /var/lib/rspamd/arc pour ARC) comme chemins à la place de /etc/dkim, vous n’avez rien à faire : rspamd cherche les clés des domaines avec le chemin /var/lib/rspamd/dkim/$domain.$selector.key (et /var/lib/rspamd/arc/$domain.$selector.key pour ARC).

Si comme moi vous utilisez /etc/dkim pour ranger vos clés, il va falloir surcharger la configuration de rspamd.

Créez les fichiers /etc/rspamd/local.d/dkim_signing.conf et /etc/rspamd/local.d/arc.conf et mettez-y ceci :

path = "/etc/dkim/$domain.$selector.key"

Relancez rspamd, et c’est normalement tout bon 🙂

Ajouter les en-têtes donnant le spam score dans les mails

Certains spams passent, des mails légitimes ne passent pas… pour comprendre ça, on peut aller dans les logs pour y retrouver les infos qui vont bien, ou alors on ajoute directement ces informations dans les en-têtes des mails 🙂

Dans le fichier /etc/rspamd/local.d/milter_headers.conf, mettez :

extended_spam_headers = true;

Relancez rspamd, et c’est normalement tout bon 🙂

Comprendre les symboles Rspamd

Dans les en-têtes ajoutés dans les mails via la configuration juste au-dessus, il y a les symboles rspamd. Ce sont différentes catégories de vérification antispam, avec un score. C’est la somme de ces scores qui donne le spam score qui va déclencher l’acceptation du mail, son classement en spam ou carrément son refus.

Cependant ces symboles n’ont pas forcément une signification évidente. Voici une liste de symboles expliqués (cette liste n’est pas exhaustive) :

Mettre des domaines en liste blanche pour les vérifications des SURBL

Contexte : vous avez un domaine qui se retrouve dans une SURBL (une liste noire de domaines de phishing/spam/etc). Problème : si quelqu’un souhaite vous envoyer un mail d’abuse à propos de ce domaine sans le protéger (genre en écrivant [https]://lstu [.] fr, ça arrive dans vos spams et vous ne voyez pas les abuses.

Pour éviter ce problème, vous pouvez mettre des exceptions pour les vérifications des SURBL.

Mettez simplement vos domaines dans /etc/rspamd/local.d/maps.d/surbl-whitelist.inc.local (un domaine par ligne) et rechargez rspamd.

Exemple de fichier /etc/rspamd/local.d/maps.d/surbl-whitelist.inc.local :

lstu.fr

Système

Système

Borg

https://borgbackup.readthedocs.io/

Quelques mots sur Borg

Pour se simplifier la vie, on peut utiliser Borgmatic qui est un wrapper de Borg.

Installation

apt-get install borgbackup

On peut aussi utiliser pip, c’est vous qui voyez.

Initialisation

On doit d'abord initialiser le répertoire qui accueillera les sauvegardes :

mkdir /opt/backup
borg init /opt/backup/

Au cas où l'on souhaiterait utiliser un serveur distant pour acceuillir les sauvegardes, il faut que celui-ci soit joignable par SSH et dispose lui-aussi de Borg.

borg init <username>@<server>:/remotepath

Dans le cas où il n'est pas possible d'y installer Borg (un espace de stockage fourni par un hébergeur par exemple), il est possible de le monter en sshfs :

apt-get install sshfs
sshfs <username>@<server>:/remotepath /opt/backup/

Sshfs possède de multiples options améliorant les performances et la stabilité du point de montage, je vous laisse chercher car je ne les ai pas sous la main.

Par défaut, l'initialisation vous demandera un mot de passe qui servira à chiffrer les sauvegardes. Il est possible de désactiver le chiffrement via les options de borg init.

borg help init

Le chiffrement nécessite deux choses pour fonctionner : le mot de passe et une clé de chiffrement. Dans le cas d'une initialisation par défaut (sans options), la clé de chiffrement sera dans le fichier /opt/backup/config.

Il est impératif de sauvegarder cette clé sans laquelle vos sauvegardes seraient inutiles ! On peut l'exporter via borg key export /opt/backup et l'importer via borg key import /opt/backup keyfile.

Le mot de passe vous sera demandé pour toute opération sur les sauvegardes (création, restauration, etc). Pour éviter de le taper toutes les cinq minutes, vous pouvez exporter la variable d'environnement BORG_PASSPHRASE :

export BORG_PASSPHRASE="mot_de_passe"

N’oubliez pas que cet export se retrouvera dans votre historique bash (ou zsh, ou ce que vous utilisez) ! Je vous conseille de le supprimer de votre historique après usage.

Création d'une sauvegarde

Rien de plus simple :

borg create /opt/backup::nom_de_la_sauvegarde /chemin/a/sauvegarder

L'option --stats est très appréciable car elle fournit des informations sur la sauvegarde créée (comme sa taille par exemple).

Le nom de la sauvegarde doit être unique et ne doit pas se terminer par .checkpoint. On peut utiliser des placeholders comme {hostname} dans le nom de la sauvegarde. Voir borg help placeholders pour plus de détails.

Manipulation des sauvegardes

Lister les sauvegardes

borg list /opt/backup

Supprimer une sauvegarde

borg delete /opt/backup::nom_de_la_sauvegarde

Renommer une sauvegarde

borg rename /opt/backup::nom_de_la_sauvegarde nouveau_nom

Extraire le contenu d'une sauvegarde

Attention ! Le contenu sera extrait dans le répertoire où vous vous trouvez !

borg extract /opt/backup::nom_de_la_sauvegarde

Il est possible de n'extraire que certains fichiers :

borg extract /opt/backup::nom_de_la_sauvegarde home/etudiant/travail.pl
borg extract /opt/backup::nom_de_la_sauvegarde home/etudiant/ --exclude '*.rb'

Monter une sauvegarde

borg mount /opt/backup::nom_de_la_sauvegarde /mnt

Vous pourrez alors parcourir et utiliser (cp, cat…) la sauvegarde en parcourant le dossier /mnt.

Pour démonter la sauvegarde :

borg umount /mnt

Voir les informations détaillées d'une sauvegarde

borg info /opt/backup::nom_de_la_sauvegarde

Supprimer les vieilles sauvegardes

Même si l'espace disque ne coûte aujourd'hui pas très cher, on ne va quand même pas garder 30 ans de sauvegardes

borg prune -w 4 --prefix='{hostname}-' /opt/backup

Cette commande ne gardera que 4 sauvegardes hebdomadaires. L'option --prefix='{hostname}-' permet de discriminer les sauvegardes à éliminer d'après un préfixe (ici le nom de la machine), ceci afin d'éviter de supprimer les sauvegardes d'une autre machine si jamais le répertoire de sauvegarde servait pour plusieurs machines.

Je vous laisse regarder les autres options de borg prune dans le manuel.

Vérifier une sauvegarde (ou toutes)

borg check /opt/backup::nom_de_la_sauvegarde
borg check /opt/backup

Attention ! Cela vérifie que la sauvegarde n'est pas corrompue, pas que vous avez ciblé les bons répertoires à sauvegarder ! :P

Vérification des sauvegardes

« Une sauvegarde est à la fois valide et corrompue tant qu'on n'a pas essayé de la restaurer »

La sauvegarde de Schrödinger

Et oui, tant qu'on n'a pas essayé de restaurer des fichiers depuis la sauvegarde, comment savoir si celle-ci a fonctionné ? Les déboires de la société Gitlab qui a perdu 6 heures d'enregistrements en base de données pour cause de dysfonctionnement des 5(!) méthodes de sauvegardes nous en donnent la preuve.

Il existe cependant un outil qui permet de vérifier que vos sauvegardes respectent un certain nombre de critères : Backup Checker

Avec cet outil, on pourra s'assurer que la sauvegarde comporte bien tel ou tel fichier, soit d'une certaine taille, etc.

À défaut d'avoir le temps de mettre en place un tel outil, on pourra ponctuellement essayer de restaurer localement un fichier. Même si cela ne vérifie pas grand chose, c'est toujours mieux que pas de vérification du tout !

Un peu de lecture

http://sebsauvage.net/wiki/doku.php?id=borgbackup

Plutôt que d’écrire un script qui utilise borg…

Il y a un soft qui fait une surcouche à Borg, le rendant plus simple à utiliser : Borgmatic.

Système

Borgmatic

Borgmatic est un wrapper autour de Borg qui en simplifie infiniment l’utilisation.

Installation

Il nous faut d’abord Borg (utilisez la version des backports Debian si vous êtes encore en stretch) :

apt install borgbackup

D’habitude, je préfère utiliser les paquets Debian, mais la version pip de Borgmatic apporte une option en plus que j’apprécie particulièrement.

apt install python3-pip
pip3 install borgmatic

Configuration

C’est là que Borgmatic est pratique : il permet une configuration très simple de Borg.

Générez un fichier de configuration :

generate-borgmatic-config

Cela créera le fichier /etc/borgmatic/config.yaml. Si vous souhaitez que la configuration soit dans un autre fichier :

generate-borgmatic-config -d /etc/borgmatic/autre_config.yaml

La configuration générée (exemple) est très simple à comprendre et auto-documentée, je ne vais l’expliquer, je vais me contenter d’en mettre certains points en valeur

Le dépôt

On le verra plus bas, j’utilise un serveur distant pour faire les sauvegardes. Donc :

location:
    repositories:
        - borg@server:/var/lib/borg/depot/

La passphrase

Choisissez quelque chose de costaud et sauvegardez-là quelque part !

storage:
    encryption_passphrase: "foo-bar-baz"

Utilisation d’une clé SSH particulière

Je crée plus bas une clé SSH dédiée pour Borg pour faire les sauvegardes sur le serveur distant. Il faut donc que j’indique à Borgmatic que je souhaite utiliser cette clé.

storage:
    ssh_command: ssh -i /root/.ssh/id_borgmatic

Les hooks

Situés à la fin du fichier de configuration, il s’agit d’actions qui seront effectuées avant et après la sauvegarde, ou en cas de problème lors de l’exécution.

Personnellement, j’aime bien avoir la liste de mes sauvegardes après qu’une sauvegarde soit effectuée. Je vais donc écrire :

hooks:
    after_backup:
        - /usr/local/bin/borgmatic list

Comme il est conseillé d’exporter la clé du dépôt borg, je mets aussi ceci dans les hooks :

    before_backup:
        - borg key export borg@server:/var/lib/borg/depot/ /etc/ssl/private/borg.key

Rétention et vérification du dépôt et des archives

Je fais ça sur le serveur, j’y reviendrai plus loin.

Cron

On crée un petit cron (avec l’utilisateur root) pour sauvegarder régulièrement l’ordinateur :

35 0 * * * borgmatic create -c /etc/borgmatic/mon_pc.yaml --stats 2>&1

Si ce n’est pas un serveur allumé 24h/24, il est préférable de mettre ça dans /etc/anacrontab :

@daily  15      backup  borgmatic -c /etc/borgmatic/mon_pc.yaml --stats 2>&1

Cela lancera le backup tous les jours, 15 minutes après le démarrage du pc. Ou plus tard.

Attention, sur Debian, les tâches anacron ne sont lancées que si vous êtes sur secteur ! Pour changer ça, reportez-vous au fichier /usr/share/doc/anacron/README.Debian.

Préparation du serveur du dépôt distant

Je préfère faire mes sauvegardes sur un disque distant : si mon disque lâche, j’aurai toujours mes sauvegardes.

Pour ce faire, je crée une clé dédiée sur l’ordinateur à sauvegarder, sans mot de passe vu que borgmatic va tourner automatiquement :

ssh-keygen -o -a 100 -t ed25519 -f /root/.ssh/id_borgmatic -N ''

Sur le serveur de sauvegarde, j’installe Borg et Borgmatic comme précédemment puis je crée un utilisateur borg :

adduser --system --home /var/lib/borg --shell /bin/bash --disabled-password borg
mkdir /var/lib/borg/.ssh
chmod 700 /var/lib/borg/.ssh
touch /var/lib/borg/.ssh/authorized_keys
chmod 600 /var/lib/borg/.ssh/authorized_keys
chown -R borg: /var/lib/borg/.ssh

Et je mets la clé publique créée précédemment dans /var/lib/borg/.ssh/authorized_keys, avec quelques restrictions :

command="/usr/bin/borg --umask=077 --info serve --append-only --restrict-to-repository /var/lib/borg/becky2/",restrict ssh-ed25519 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX root@mon_pc

On génère une configuration :

generate-borgmatic-config -d /etc/borgmatic/mon_pc.yaml

Et c’est dans cette configuration qu’on va configurer les durées de rétention et les vérifications du dépôt et des archives.

Rétention

C’est très simple. Pour garder un backup par mois sur les 6 derniers mois, un par semaine sur les 8 dernières semaines et un par jour sur les 14 derniers jours, il suffit de :

retention:
    keep_daily: 14
    keep_weekly: 8
    keep_monthly: 6

Comme Borg déduplique comme un monstre, cela ne prendra pas énormément de place (sauf si vous sauvegardez des trucs qui changent tout le temps)

Vérification du dépôt et des archives

Cela permet de s’assurer que votre dépôt et vos archives sont utilisables et non corrompus. Je me contente de décommenter la configuration proposée :

consistency:
   checks:
       - repository
       - archives
   check_last: 3

J’ai laissé check_last à 3 car vérifier toutes les archives peut être fort long. Donc une vérification des 3 dernières devrait faire l’affaire, surtout si on vérifie quotidiennement.

Dépôt

Attention, comme on est là sur le serveur distant, il faut lui donner un dossier local !

location:
    repositories:
        - /var/lib/borg/depot/

Script de suppression d’anciennes sauvegardes / vérification des archives

Il y a des éléments dans ce script qui prendront tout leur sens plus tard.

NOTA BENE : ce script est tout à fait adaptable à un usage à Borg sans Borgmatic.

On prépare le terrain :

apt install libcpanel-json-xs-perl
mkdir -P /opt/borgmatic-stats/tmp/ /opt/borgmatic-stats/json/
cd /opt/borgmatic-stats/
wget https://framagit.org/snippets/3716/raw -O verify-archives.pl
chmod 700 -R /opt/borgmatic-stats/
chown borg: -R /opt/borgmatic-stats/

Puis on met ceci dans /opt/borgmatic_prune_and_check.sh :

#!/bin/bash
cat <<EOF
==============================================
== mon_pc
==============================================
EOF

/usr/local/bin/borgmatic list -c /etc/borgmatic/mon_pc.yaml --json > /opt/borgmatic-stats/tmp/mon_pc.json.tmp
CONTINUE=0
if [[ -e /opt/borgmatic-stats/json/mon_pc.json ]]
then
    echo "Checking repository consistency."
    CONTINUE=$(/opt/borgmatic-stats/verify-archives.pl --old /opt/borgmatic-stats/json/mon_pc.json --new /opt/borgmatic-stats/tmp/mon_pc.json.tmp)
    echo "Repository consistency checked."
else
    CONTINUE=1
fi

if [[ $CONTINUE == '1' ]]
then
    ## Check
    /usr/local/bin/borgmatic check -c /etc/borgmatic/mon_pc.yaml 2>&1 && \
    echo "Repository checked." && \
    ## Allow pruning
    borg config /var/lib/borg/depot/ append_only 0 && \
    ## Prune
    /usr/local/bin/borgmatic prune -c /etc/borgmatic/mon_pc.yaml --stats 2>&1 && \
    echo "Repository pruned."
    ## List
    echo "Borg archives of mon_pc:"
    /usr/local/bin/borgmatic list -c /etc/borgmatic/mon_pc.yaml 2>&1

    /usr/local/bin/borgmatic list -c /etc/borgmatic/mon_pc.yaml --json > /opt/borgmatic-stats/json/mon_pc.json

    ## Disallow pruning
    borg config /var/lib/borg/depot/ append_only 1

    echo ''
else
    cat <<EOF

******************************************
* ALERT ON mon_pc! *
******************************************
All of the old archives can’t be retrieved from the repository (/var/lib/borg/depot/)!

Someone may have deleted an archive from mon_pc.

Pruning has been aborted. Please manually review the repository.

$CONTINUE
EOF
fi

On n’oublie pas de le rendre exécutable :

chmod +x /opt/borgmatic_prune_and_check.sh

Cron

Attention ! Il faut éditer la crontab de l’utilisateur borg :

crontab -e -u borg

Et son contenu :

15 3 * * * /opt/borgmatic_prune_and_check.sh

Initialisation du dépôt de sauvegarde

Sur l’ordinateur à sauvegarder :

borgmatic init -c /etc/borgmatic/mon_pc.yaml --append-only -e repokey

Le dépôt est initialisé en append-only (mais de toute façon, on le force dans le .ssh/authorized_keys du serveur distant) et avec un chiffrement par mot de passe mais avec la clé dans le dossier du dépôt distant.

Lancement d’une sauvegarde

Sur l’ordinateur à sauvegarder :

borgmatic create -c /etc/borgmatic/mon_pc.yaml --stats

Le --stats est l’option que j’affectionne et dont je parlais au début : cela affiche des statistiques sur la sauvegarde qui a été faite : sa taille, sa taille compressée, sa taille dédupliquée, le temps que ça a pris…

Afficher la liste des sauvegardes

borgmatic list -c /etc/borgmatic/mon_pc.yaml 

Restauration de sauvegardes

Voir la section kivabien de l’article sur Borg.

Explication de l’option --append-only

Contrairement à ce qu’on pourrait croire, --append-only n’empêche pas de supprimer des sauvegardes (Ce ticket Github m’en a fait prendre conscience). Ainsi, un attaquant ayant pris le contrôle de l’ordinateur à sauvegarder pourra supprimer des sauvegardes. Sauf qu’elle ne seront pas vraiment supprimées : l’attaquant aura créé des transactions qui indiquent la suppression des sauvegardes mais ces transactions ne seront rééllement appliquées que lors d’une action comme prune depuis un ordinateur qui aura le droit de faire sauter le append-only. C’est comme un BEGIN TRANSACTION; sans COMMIT; en SQL 🙂

C’est le cas du script /opt/borgmatic_prune_and_check.sh qui fait effectivement sauter (et le remet après) le verrou avec :

borg config /var/lib/borg/depot/ append_only 0

Comme on automatise la suppression des anciennes sauvegardes avec cron, il nous faut un moyen de repérer de tels changements. C’est tout le but de /opt/borgmatic-stats/verify-archives.pl qui compare la liste des archives du dépôt avec la liste créée la dernière fois que /opt/borgmatic_prune_and_check.sh a supprimé les anciennes archives. Comme le serveur distant est le seul à normalement pouvoir supprimer des archives, il est logique de retrouver toutes les anciennes archives au lancement suivant.

Ainsi, en cas d’incohérence, la suppression des anciennes archives ne s’effectue pas.

NOTA BENE : ceci n’empêchera pas un attaquant de changer la configuration de borgmatic pour lui faire sauvegarder des trucs inutiles plutôt que ce qui vous intéresse. Ou de couper les sauvegardes. C’est un inconvénient des sauvegardes en push plutôt qu’en pull. Je n’ai pas encore trouvé de solution à ça. Peut-être un script qui analyserait la sortie de borgmatic create --stats --jon qui me permettrait de repérer des changements importants dans la taille de la sauvegarde, le temps de sauvegarde ou le ratio de déduplication ?

En cas d’incohérence : restaurer des sauvegardes supprimées par un attaquant

Sur le serveur distant :

su - borg
cd /var/lib/borg/depot/

Regarder le log des transactions pour trouver les n° des transactions suspectes : cat transactions

Ce qui nous donne un truc du genre :

transaction 23, UTC time 2019-08-01T13:40:34.435019
transaction 25, UTC time 2019-08-01T13:42:05.662188
transaction 27, UTC time 2019-08-01T13:43:18.403771
transaction 29, UTC time 2019-08-01T13:43:53.306636
transaction 31, UTC time 2019-08-01T13:44:51.831937
transaction 33, UTC time 2019-08-01T13:45:17.786886
transaction 35, UTC time 2019-08-01T22:17:12.044179
transaction 37, UTC time 2019-08-02T08:02:55.005430
transaction 43, UTC time 2019-08-02T22:17:10.068843
transaction 45, UTC time 2019-08-03T22:17:09.625745
transaction 47, UTC time 2019-08-04T22:17:09.673447
transaction 49, UTC time 2019-08-05T22:17:13.709208
transaction 51, UTC time 2019-08-06T10:11:26.301496
transaction 53, UTC time 2019-08-06T10:20:46.178014
transaction 55, UTC time 2019-08-06T10:26:47.940003

Là, il faut savoir quand a eu lieu le problème. Ici, c'était le 6 août à partir de 10h. Donc les transactions 51 à 55. Mais attention ! Il s'agit en fait des transactions 50 à 55 : le numéro indiqué dans le fichier est celui du dernier fichier modifié par la transaction. Il faut donc partir du n+1 de la dernière transaction correcte.

Après, c'est facile :

rm hints.* index.* integrity.*
rm data/**/{50..55}

On finit par rafraîchir le cache du dépôt :

borg delete --cache-only /var/lib/borg/depot/

Sur l’ordinateur sauvegardé, par contre, je n’arrivais pas à supprimer le cache, j’avais ce message :

Cache, or information obtained from the security directory is newer than repository - this is either an attack or unsafe (multiple repos with same ID)

Ceci m'a réglé le problème :

rm -rf ~/.cache/borg/le_dossier_avec_un_nom_monstrueux
rm -rf ~/.config/borg/security/un_autre_dossier_avec_un_nom_monstrueux
Système

LVM

LVM permet, à partir de plusieurs disque physiques, de créer des partitions qui utiliseront plusieurs disques de manière invisible.

L'autre avantage est de pouvoir rajouter du disque sans arrêter la machine ou démonter la partition.

Bases

Le LVM est composé de plusieurs morceaux :

On n'est pas obligé d'utiliser toute la place disponible dans un groupe de volume lorsqu'on crée un volume logique, on a tout à fait le droit de se garder de la place.

On peut augmenter la taille d'un volume physique à chaud, sans démonter la partition, mais on doit la démonter si on veut réduire la taille ! C'est pourquoi il vaut mieux mettre juste ce qu'il faut comme taille (avec une marge de sécurité, bien sûr), quitte à augmenter plus tard la taille de la partition, plutôt que de tout mettre et ne plus avoir de marge pour une autre partition.

Créer une nouvelle partition

lvcreate -L 30G -n nom-partition xenvg
mkfs.ext4 /dev/mapper/xenvg-nom-partition

Augmentation de la taille d'une partition

Ajout d'un nouveau disque au groupe de volumes xenvg :

pvcreate /dev/sdc1
vgextend xenvg /dev/sdc1

Augmentation de la taille de la partition data, appartenant au groupe xenvg :

lvextend -L +6.5G /dev/xenvg/data
resize2fs /dev/mapper/xenvg-data

Pour prendre toute la place disponible :

lvextend -l +100%FREE /dev/mapper/xenvg-data
resize2fs /dev/mapper/xenvg-data

Si c'est une partition de ''swap'' qui a été étendue :

swapoff -a
mkswap /dev/mapper/beta--vg-swap_1
swapon -a
Système

Réinstaller les modules Perl installés avec la version précédente de Perl

Un truc con quand on installe des modules Perl avec cpan ou cpanm, c’est qu’ils sont installés dans un répertoire dont le nom est la version de Perl utilisée.

Donc quand on installe un module sur une Debian Stretch et qu’on met à jour la machine vers Debian Buster, les modules installés via cpan ou cpanm ne sont plus disponibles vu qu’on change de version de Perl.

Heureusement que les modules installés sont listés dans un coin 🙂

Pour trouver les modules qu’on avait installé en Stretch :

cat /usr/local/lib/x86_64-linux-gnu/perl/5.24*/perllocal.pod | grep "C<Module>" | sed -e 's/.*C<Module> L<\(.*\)|.*>/\1/' | tr '\n' ' '

Pour tous les réinstaller en un tour de main :

cpanm $(cat /usr/local/lib/x86_64-linux-gnu/perl/5.24*/perllocal.pod | grep "C<Module>" | sed -e 's/.*C<Module> L<\(.*\)|.*>/\1/' | tr '\n' ' ')

Bien évidemment, ça marche avec les précédentes versions de Debian, et ça devrait aussi fonctionner avec les suivantes, il n’y a qu’à changer le numéro de version 🙂

NB : ça ne concerne pas les modules Perl installés via les paquets Debian.

Système

Sed

C’est l’outil absolu pour modifier du texte en le passant par un pipe ! Ou pour effectuer des changements en masses sur un fichier sans l’ouvrir. Bref, comme le dit l’adage : « Sed, c’est bien » 😁

Il est possible de faire des trucs de tarés avec (hey, c’est pas juste un truc pour faire des substitutions à coup d’expressions rationnelles, c’est un vrai éditeur de texte, on peut se balader dans le texte, faire des copier/coller, etc).

Usage classique

On va prendre comme exemple la substitution qui transforme foo en bar.

Pour modifier la sortie d’une commande :

echo 'foo' | sed -e 's/foo/bar/'

Pour afficher un fichier en modifiant son contenu (seul l’affichage est modifié, le fichier ne change pas) :

sed -e 's/foo/bar/' fichier.txt

Pour modifier un fichier (là ça change le fichier) :

sed -e 's/foo/bar/' -i fichier.txt

Pour supprimer les retours à la ligne (là je les remplace par des espaces) :

echo -e "foo\nbar" | sed -z 's/\n/ /g'
echo -e "foo\nbar" | sed ':a;N;$!ba;s/\n/ /g'

NB : on peut aussi utiliser tr.

echo -e "foo\nbar" | tr '\n' ' '
Système

Trucs et astuces

Il est un certain nombre de logiciels qu’un administrateur systèmes renacontrera au cours du temps. Ceux-ci lui permettront d’acquérir des automatismes et de gagner un temps considérable dans l’accomplissement de ses tâches.

Page aussi disponible sur https://luc.frama.io/cours-asrall/tips/.

Éditer un fichier

Que votre éditeur favori soit vim, nano, emacs ou autre, il faut vous assurer :

Il est nécessaire de connaître son éditeur pour être efficace.

Pour vim, vous pouvez lancer vimtutor qui vous fera passer par des exercices pour vous familiariser avec vim. Le site VimCasts regorge de tutoriaux et d’astuces.

Attention : quand bien même vous ne choisiriez pas vim, il vous faut en connaître les commandes de base. En effet, emacs n’est que rarement installé sur un serveur, et nano est parfois (souvent ?) trop limité pour travailler vite et bien.

Les processus

htop

htop permet de lister les processus, rechercher un processus, tuer des processus, trier les processus selon différents critères…

Il affiche également des informations sur le système : occupation mémoire, utilisation des processeurs, charge du système, etc.

Pour n’afficher que les processus de l’utilisateur foo :

htop -u foo

Voir https://peteris.rocks/blog/htop/ pour comprendre les informations fournies par htop.
Carl Chenet a traduit ces articles en français dans une série d’article disponible sur https://carlchenet.com/category/htop-explique/.

kill

La commande kill permet d’envoyer un signal à un processus. On peut indifféremment utiliser le n° ou le nom d’un signal pour l’utiliser. Ainsi kill -9 <PID> est normalement équivalent à kill -KILL <PID>.

Pour être bien certain du signal envoyé, il est préférable d’utiliser son nom : tous les signaux n’ont pas un n° attribué de façon certaine.

Voir https://en.wikipedia.org/wiki/Unix_signal#POSIX_signals pour la liste des signaux POSIX.

killall

killall est le petit frère de kill. Il permet d’envoyer des signaux aux processus sans connaître leur PID, juste avec leur nom.

Comme killall peut ratisser large, il vaut mieux lui préférer le couple pgrep / pkill.

pgrep / pkill

pgrep permet de rechercher parmi les processus, pkill permet d’envoyer un signal aux processus avec la même syntaxe de recherche que pgrep.

Rechercher un processus par son nom :

pgrep nom

Rechercher un processus par l’intégralité de sa ligne de commande :

pgrep -f nom

Rechercher un processus par son nom, appartenant à l’utilisateur foo :

pgrep -u foo nom

Afficher le nom du processus en plus de son PID :

pgrep -l nom

Afficher la ligne de commande complète en plus de son PID :

pgrep -a nom

Envoyer le signal SIGTERM aux processus correspondants à la recherche :

pkill SIGTERM nom

lsof

lsof permet de connaître le ou les processus utilisant une ressource.

Qui utilise /home/foo ?

lsof /home/foo

Qui utilise /dev/sda ?

lsof /dev/sda

Qui utilise le port 80 ?

lsof -i :80

Les logs

multitail

multitail permet de surveiller en temps réel les modifications d’un ou plusieurs fichiers à la manière d’un tail -f mais est bien plus souple d’usage.

Lire plusieurs fichiers :

multitail mail.log kern.log

Filtrer les lignes affichées d’un fichier selon une regex :

multitail -e regex mail.log kern.log

Filtrer les lignes affichées de tous les fichiers selon une regex :

multitail -E regex mail.log kern.log

Une fois multitail lancé, un grand nombre de raccourcis claviers permet de le manipuler :

goaccess

goaccess va analyser en temps réel les logs d’un serveur pour fournir des statistiques.

On pourra alors voir rapidement quelle est l’adresse IP qui se connecte le plus, quelle est la page la plus visitée, etc.

Veille technologique

Non, passer du temps sur LinuxFR ou sur le Journal du hacker n’est pas du temps perdu, quoi qu’on en dise. Il est en effet important d’effectuer une veille technologique régulière afin de découvrir de nouvelles technologies, de nouvelles astuces ou d’être averti de nouvelles failles de sécurité.

Votre meilleur ami pour cette veille sera un lecteur de flux RSS. En effet, un lecteur de flux a cet immense avantage sur les réseaux sociaux d’être asynchrone : partez en vacances deux semaines, revenez, et lisez tout ce que vous avez loupé (essayez un peu de faire cela avec Twitter : impossible). Vous pouvez aussi généralement le configurer pour qu’il vous envoie un résumé par mail de vos flux RSS… parfait quand on le couple à la liste de discussion des autres administrateurs systèmes !

Attention : les réseaux sociaux comme Twitter peuvent aussi être utiles, de par leur propension à propager (très) rapidement l’information. Le revers de la médaille est qu’il faudra bien vérifier la véracité de la-dite information.

SSH

Concierge

SSH fonctionne bien de base, mais avoir un fichier de configuration SSH améliore grandement les choses.

Exemple : votre identifiant sur votre machine locale est rim, mais rimd sur la machine mavrick.chatons.org. Pour vous connecter, vous lancez la commande ssh rimd@mavrick.chatons.org

Avec un fichier de configuration ssh (~/.ssh/config) contenant

Host mavrick
    HostName mavrick.chatons.org
    User rimd

vous pourrez vous connecter avec un simple ssh mavrick,

Avec quelques serveurs, la gestion de ce fichier ne pose pas de problème, mais on s’aperçoit, au fur et à mesure que l’on a plus de serveurs à gérer que cela devient une plaie. C’est là qu’intervient concierge.

concierge permet de gérer son fichier de configuration avec un langage de template.

On pourra donc écrire

{% for i in ('dorone', 'khais') %}
Host {{i}}
    HostName {{i}}.chatons.org
    User rimd
    IdentitiesOnly yes
    IdentityFile /home/%u/.ssh/id_chatons
{% endfor %}

{% for i in ('gohan', 'diren') %}
Host {{i}}
    HostName {{i}}.perso.org
    User rim
    IdentitiesOnly yes
    IdentityFile /home/%u/.ssh/id_perso
{% endfor %}

Ce qui créera des entrées dans le fichier de configuration SSH pour les serveurs dorone, khais, gohan et diren.

Voir https://github.com/9seconds/concierge pour l’installation de concierge.

Mssh

mssh, disponible habituellement dans les dépôts de votre distribution préférée, vous permettra de lancer plusieurs connexions SSH en même temps. La fenêtre contiendra autant de terminaux que de connexions SSH. Les commandes tapées seront envoyées à tous les terminaux en même temps (il est possible de n’envoyer la commande que sur un seul serveur ou de “désactiver” certains serveurs pour que les commandes ne leur soient pas envoyées).

mssh est très utile pour effectuer des tâches simultanément.

On lance mssh ainsi : mssh gohan diren

Confort visuel

redshift

redshift, lui aussi généralement dans les dépôts, ajuste la température de votre écran en fonction de l’heure. L’idée est de rougir graduellement l’écran afin d’éviter la fatigue visuelle due à la lumière bleue de votre écran.

Confort dans le terminal

bash-completion

Activer l’utilisation d’une complétion avancée des commandes se fait dans Debian en décommentant les lignes suivantes du fichier /etc/bash.bashrc :

if ! shopt -oq posix; then
    if \[ -f /usr/share/bash-completion/bash\_completion \]; then
        . /usr/share/bash-completion/bash\_completion
    elif \[ -f /etc/bash\_completion \]; then
        . /etc/bash\_completion
    fi
fi

Cela permettra, par exemple, de compléter les options d’un logiciel, le nom d’un paquet à installer, etc. Sans cela, vous n’aurez que la complétion du logiciel que vous voulez utiliser et des chemins de votre système de fichiers.

tree

tree affichera l’ensemble d’une arborescence… sous forme arborescente. Ce qui permet de parcourir un dossier très vite.

% tree foo
foo
└── bar
    └── baz.txt

1 directory, 1 file

Sécurité

mkpasswd.pl

Fourni par le paquet libstring-mkpasswd-perl dans Debian, mkpassword.pl permet de générer des mots de passe aléatoires, éventuellement en forçant quelques paramètres.

% mkpasswd.pl -l 20 -s 4
kta*wvN:g7bxM/se8a-b

Divers

ncdu

ncdu va regarder la taille du répertoire ciblé (celui où on se trouve par défaut) et afficher les fichiers/dossiers contenus, triés par taille. Très utile pour trouver ce qui bouffe de l’espace disque.

watch

watch permet de lancer une commande à intervalle régulier. Après une modification DNS, watch dig chatons.org pourra par exemple vous permettre de surveiller la prise en compte de cette modification sur votre résolveur.

truncate

truncate permet de réduire ou étendre la taille d’un fichier à la taille indiquée.

truncate -s 1M fichier_trop_gros

split

split permet de découper un fichier en plusieurs parties.

wall

wall permet d’envoyer un message à tous les utilisateurs connectés à la machine.