# Playbooks Ansible de l’AFPy On découpe nos *playbooks* Ansible par rôles : - `pycon.yml`: Pour les pycon.fr - `backup.yml`: Configure rsnapshot pour sauvegarder nos serveurs. - ... En partant de là, on peut utiliser les commandes suivantes : Après avoir cloné ce repo, installé Ansible (dans un venv), installez les roles nécessaires via : - ansible-galaxy install julienpalard.nginx Récupérez le secret dans [afpy/pass](https://github.com/AFPy/pass/): git clone https://github.com/AFPy/pass/ PASSWORD_STORE_DIR=pass/infra pass Ansible-Vault > ~/.ansible-afpy-vault Puis pour jouer les *playbooks* : - Pour tout relancer : `ansible-parallel *.yml` - Pour configurer les PyCons : `ansible-playbook pycons.yml` ## Faire, ne pas faire Faire : Configurer les machines : - `apt install`, - fichiers de configuration, - créer les utilisateurs, - éventuellement un premier `git clone` pour que ça marche si c’est un site statique. Ne pas faire : - Deployer. En dehors de l’éventuel premier git clone, c’est le rôle de la CI (Github Actions, ...), pas de nos playbooks. # Servers La distinction services/serveurs : - Un serveur contient un nombre dans son nom : - deb2.afpy.org, - bbb2.afpy.org, - … - Un service ne contient pas de chiffre dans son nom : - discuss.afpy.org, - bbb.afpy.org, - www.afpy.org, - … ## deb2.afpy.org ♥ Machine sponsorisée par Gandi ♥ C’est un VPS `V-R4 2 CPUs · 4 GB RAM`. Elle héberge surtout des sites statiques, mais pas que : - https://www.afpy.org ([source](https://github.com/AFPy/site)). - [https://\*.pycon.fr/\*](https://pycon.fr/) (que des sites statiuques). - Alain le bot IRC du canal #afpy ([source](https://github.com/AFPy/alain)). - La gate [IRC](https://afpy.org/irc)—[Discord](https://afpy.org/discord) (un [discord-irc-sync](https://github.com/Hackndo/discord-irc-sync)). - https://dl.afpy.org: un *directory listing* nginx des vidéos de nos conférences. - https://logs.afpy.org: Les logs du salon IRC #afpy ([source](https://github.com/AFPy/AfpyLogs/)). - https://munin.afpy.org ## bbb2.afpy.org ♥ Machine sponsorisée par Gandi ♥ C’est un VPS `V-R8 4 CPUs · 8 GB RAM`. C’est une Ubuntu 18.04 (c’est imposé par BBB). Elle n’est **pas** gérée par Ansible, c’est un peu particulier BBB, mais le serveur `turn` l'est, et le playbook `turn.yml` configure quand même un fichier sur BBB. D'ailleurs pour tester la configurtion turn/stun: https://docs.bigbluebutton.org/administration/turn-server#test-your-turn-server J’y ai appliqué un poil de ssh-hardening : AuthenticationMethods publickey LogLevel VERBOSE Ensuite j’ai [rsync les enregistrements depuis le bbb précédent](https://docs.bigbluebutton.org/2.2/customize.html#transfer-published-recordings-from-another-server). Puis j’ai sauvegardé/restauré la DB de greenlight : # Sur l’ancienne machine : docker exec greenlight_db_1 /usr/bin/pg_dumpall -U postgres -f /var/lib/postgresql/data/dump.sql # Sur la nouvelle machine : # Copier la sauvegarde sur le nouveau serveur : cd ~root/greenlight rsync bbb.afpy.org:/root/greenlight/db/production/dump.sql ./ docker-compose down rm -fr db # Configurer le même mot de passe dans .env et docker-compose.yml que l’ancienne machine # En profiter pour vérifier le SAFE_HOSTS dans le .env. docker-compose up -d # Attendre un peu avec un top sous les yeux que ça se termine vraiment docker exec greenlight_db_1 /usr/local/bin/psql -U postgres -c "DROP DATABASE greenlight_production;" mv dump.sql db/production/ docker exec greenlight_db_1 /usr/local/bin/psql -U postgres -f /var/lib/postgresql/data/dump.sql rm db/production/dump.sql docker-compose down docker-compose up -d # Il va s’occuper de la migration docker-compose logs -f # pour voir si tout va bien `rsync` des certificats TLS aussi : rsync -vah bbb.afpy.org:/etc/letsencrypt/ /etc/letsencrypt/ Ça a pris un petit : sed s/sd-106563.dedibox.fr/bbb.afpy.org/ /etc/nginx/sites-available/bigbluebutton Il faut attendre un moment avec un `top` qui tourne, ruby a tout plein de truc a faire avant de démarrer. ### BBB password reset Pour accepter le password reset, BBB doit avoir : ALLOW_MAIL_NOTIFICATIONS=true dans /root/greenlight/.env (Pour relire le `.env`: `cd /root/greenlight; docker-compose down && docker-compose up -d`) Pour vérifier la conf : docker run --rm --env-file .env bigbluebutton/greenlight:v2 bundle exec rake conf:check Il y a des chances que ça ne passe pas, il faut laisser les mails sortir de leur conteneur Docker (par défaut il utilise sendmail DANS le conteneur). Il faut configurer le `.env` tel que: SMTP_SERVER=172.17.0.1 SMTP_PORT=25 SMTP_DOMAIN=greenlight.afpy.org SMTP_SENDER=bbb@afpy.org Puis vérifier qu’exim et le firewall (attention c’est peut-être `ufw`) les acceptent. ## backup1.afpy.org ♥ Machine sponsorisée par Gandi ♥ C’est un « Gandi Cloud V5 » à Bissen au Luxembourg avec 512MB de RAM et 512GB de disque, il sauvegarde (via rsnapshot) les autres machines (voir `backup.yml`). Dernière vérification de `backup1.afpy.org` le 7 mai 2023 via : ssh root@backup1.afpy.org sh check-afpy.sh Dernière vérification de `silence` (chez Julien) le 7 mai 2023 via : ssh root@silence sh /srv/backups/check-afpy.sh
Le script `check-afpy.sh`. ```bash #!/bin/sh BASE=/srv/backups/rsnapshot_afpy for machine in bbb deb git discuss do echo "# $machine.afpy.org" echo rsnapshot-diff -H "$BASE/weekly.0/$machine.afpy.org" "$BASE/daily.0/$machine.afpy.org" echo echo done echo '# discuss.afpy.org' echo ls -lahtr $BASE/daily.0/discuss.afpy.org/var/discourse/shared/standalone/backups/default/ | sed 's/^/ /' echo echo echo '# logs.afpy.org' echo ls -lahtr $BASE/daily.0/deb.afpy.org/var/www/logs.afpy.org/ | tail | sed 's/^/ /' echo echo echo '# git.afpy.org' echo ls -lahtr $BASE/daily.0/git.afpy.org/var/backups/gitea/ | sed 's/^/ /' ```
## gitea1.afpy.org ♥ Machine sponsorisée par Gandi ♥ C’est un « Gandi VPS V-R1 » 1 CPU, 1 GB RAM, 25 GB disk. C’est la machine derrière `git.afpy.org`, déployée via `gitea.yml`. ### Mise à jour Pour faire une mise à jour, se connecter en root à la machine puis exécuter : systemctl start gitea-backup.service backupopts="-c /etc/gitea/app.ini --file /var/backups/gitea/before-upgrade.zip" gitea-upgrade.sh (Oui, je sais, ça fait deux sauvegardes, une par nous (avec un `pg_dump`), une par le script de gitea dont le SQL n’est pas aussi propre que celui généré par `pg_dump`). Une fois la mise à jour terminée, il est de bon goût de mettre à jour `gitea_version` dans `gitea.yml`. ### Sauvegardes Les données sont sauvegardées automatiquement via rsync sur `backup1.afpy.org` (voir `backup.yml`). Côté VPS Gandi on a aussi un snapshot du volume tous les jours. ### Restaurer une sauvegarde Procédure testée le 2022-11-29 par [mdk](https://git.afpy.org/mdk). Voici la procédure pour restaurer une sauvegarde sur une nouvelle machine « from scratch ». #### Commander une nouvelle machine Typiquement chez Gandi une `V-R1: 1 CPU · 1 GB RAM`, avec une Debian 11, n’oubliez pas d’y mettre une clé SSH. #### Nommer la machine Typiquement `gitea2.afpy.org`, configurer les DNS, en profiter pour réduire le TTL de git.afpy.org puisqu’il faudra le changer à la fin. #### Autoriser à se ssh en root ssh debian@giteatest.afpy.org sudo cp /home/debian/.ssh/authorized_keys /root/.ssh/ #### Ajouter la machine dans l’inventaire Ansible Ça devra donc ressembler à : ```ini [gitea] gitea2.afpy.org ``` On peut probablement supprimer l’autre qui ne marche plus... #### Lancer Ansible `ansible-playbook gitea.yml` #### rsync la sauvegarde J’utilise du `ssh agent forwarding`, si vous n’en utilisez-pas vous aurez peut-être à rsync sur votre machine d’abord. Adapté de : https://docs.gitea.io/en-us/backup-and-restore/#restore-command-restore Donc, depuis gitea2: cd /var/lib/gitea/ rsync -vah backup1.afpy.org:/srv/backups/rsnapshot_afpy/daily.0/git.afpy.org/var/backups/gitea/ ./ systemctl stop gitea rm -fr data custom unzip gitea.zip rm gitea.zip mv app.ini /etc/gitea/app.ini mv repos data/gitea-repositories chown -R git:git . sudo --user git psql -d gitea < gitea.sql rm gitea.sql Puis passer le playbook `gitea.yml` pour remettre les bons droits partout (le playbook démarrera aussi `gitea`). #### Tester et mettre à jour git.afpy.org Un rapide test peut être effectué via : curl --resolve git.afpy.org:IP_DE_LA_NOUVELLE_MACHINE https://git.afpy.org Puis il faut mettre à jour le CNAME de git.afpy.org pour le faire pointer vers la nouvelle machine. ## woodpecker1.afpy.org ♥ Machine sponsorisée par Gandi ♥ C’est un « Gandi VPS V-R1 » 1 CPU, 1 GB RAM, 25 GB disk. C’est [Woodpecker CI](https://woodpecker.afpy.org) lié à notre [forge](https://git.afpy.org). Il ne fait tourner aucune tâche, ce sont les agents qui font tourner les tâches. Si vous avez une machine de libre, vous êtes invités à proposer un agent. Il suffit de : - Installer une Debian. - Y ajouter nos [authorized_keys](https://git.afpy.org/AFPy/infra/src/branch/main/group_vars/all/authorized_keys). - Nous donner son IP. Un agent n’a pas besoin d’IPv4, donc une vieille machine recyclée planquée chez vous sans NAT mais avec de l’IPv6 ça suffit. Pas de Raspberry PI par contre, nous n’avons pour le moment pas de tâches à faire tourner sur arm64. ### boole.mdk.woodpecker-agents.afpy.org ♥ Machine sponsorisée par Julien Palard ♥ C’est un vieux laptop à moi, 4 cœurs, 8GB de RAM, planqué sous mon bureau. Il sert uniquement d’agent au Woodpecker, et c’est pour le moment le seul. ## discourse1.afpy.org ♥ Machine sponsorisée par Gandi ♥ C’est un VPS `V-R4 2 CPUs · 4 GB RAM`. Elle héberge https://discuss.afpy.org une instance Discourse. ### Déplacement du Discourse vers une nouvelle machine Le 31 janvier 2023 Julien a déplacé le Discourse de deb2 à discourse1.
Voici la procédure - Ajouter les enregistrements A et AAAA de la machine. - Baisser le TTL du CNAME `discuss.afpy.org`. - Mettre à jour le SPF pendant qu’on y est. - Configurer le reverse DNS de la nouvelle machine. - Côté Ansible, ajouter la machine au groupe `[discourse]` dans le fichier `inventory`. - Copier sa clé ssh sur la machine dans `/root/.ssh/authorized_keys`. - Lancer `ansible-playbook discuss.yml`. - Lancer à la main dans `/var/discourse/`: `./launcher rebuild app` (ça prend ~10mn). - Sur l’ancienne machine, faire une sauvegarde, soit via https://discuss.afpy.org/admin/backups, soit : ``` ./launcher enter app discourse backup exit ``` - Copier une sauvegarde dans `/var/discourse/shared/standalone/backups/default/`. - Restaurer la sauvegarde : ``` cd /var/discourse ./launcher enter app discourse enable_restore discourse restore afpy-2023-01-31-215204-v20230130053144.tar.gz exit ``` Bien tester l’envoi d’emails.
# Rôles utilisés On utilies ces rôles Ansible : ## roles/nginx Ce rôle configure un nginx avec Letsencrypt en DNS-01 via l’API Gandi (nos domaines étant chez Gandi). L’avantage du DNS-01 c’est qu’on peut configurer un nouveau serveur **avant** que le DNS ne pointe sur lui. ## julienpalard.nginx Ce rôle configure un nginx avec Letsencrypt en HTTP-01, on l’utilise assez peu maintenant, on l’utilise là où on ne peut pas faire de DNS-01 (pour `fr.pycon.org` par exemple). Voir la [doc](https://github.com/JulienPalard/ansible-role-nginx). ## common *common* est un rôle "de base" permettant d’avoir une conf "normale" sur toutes nos machines (emacs et vim installés, nos authorized-keys, pas de mlocate, hostname propre, firewall, ce genre de broutilles). ## exim Le playbook exim configure une clé DKIM et signe les mails avec. Mais un humain doit la propager sur les DNS. Le nom d’hote est le nom du serveur, donc pour `deb2`, `d=deb2.afpy.org`, et le selecteur vaut le nom de domaine avec des `-`, soit `s=deb2-afpy-org`. TL;DR la configuration qu’il faut faire ressemble à : deb2-afpy-org._domainkey.deb2.afpy.org. IN TXT "v=DKIM1; k=rsa; p=MIG...QAB" La clé publique se situe dans `/etc/exim4/dkim/*.pem` et est donc récupérable via : ssh root@deb2.afpy.org cat /etc/exim4/dkim/deb2-afpy-org.pem | grep -v ^- | tr -d '\n'