Jacques Foucry bio photo

Jacques Foucry

IT, râleur et faiseur de pain

Email

J’ai une instance mastodon. Nous sommes peu nombreux dessus (je suis 1 et il y a des comptes de secours ou dormant).

J’ai récemment installé PostgreSQL dans une jail FreeBSD.

Je vais utiliser cette jail pour mettre la base de données PostgreSQL de mon instance Mastodon. L’étape suivante sera de mettre mastodon dans une nouvelle jail et d’en faire la mise à jour1.



Travaux préliminaires

Avant de faire les manipulations qui nous interessent, il est préférable de prévenir les utilisateurs de l’instance, par un mail par exemple.

Sur la jail Postgres il est nécessaire de créer l’utilisateur mastodon :

1
2
# pw useradd -n mastodon -c "Mastodon user" -s /bin/csh -m -w random
Password for 'mastodon' is: <random generated password>

:information_source: pensez à noter dans votre gestionnaire de mot de passe celui que le système a généré pour vous. Pour plus d’information sur la commande pw, reférez vous à la page man de la commande pw(8)

:information_source: si la commande pw vous semble trop complexe, vous pouvez utiliser la commande interactive adduser.

Création du rôle mastodon

PostgreSQL a besoin d’un rôle spécifique pour la base de données mastodon. Pour cela nous allons suivre la documentation de mastodon.

1
2
# sudo -u postgres psql
postgres=# create user mastodon createdb;

Avant de quitter PostgreSQL, on peut vérifier que la création de l’utilisateur est correcte :

postgres=#\du
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 mastodon  | Create DB                                                  | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 root      |

 postgres=#\q

Création de la base de données

Toujours sur notre jail Postgresql, nous allons créer la base de données de production qui va accueillir nos données.

:information_source: normalement cette étape se fait à l’installation de mastodon, mais comme nous allons importer les données d’une base déjà existante, il nous faut faire cette manipulation à la main.

# su - mastodon
mastodon@postgres:~ % createdb mastodon_production
mastodon@postgres:~ % psql mastodon_production
psql (9.6.8)
Type "help" for help.

mastodon_production=> \l
                                  List of databases
        Name         |  Owner   | Encoding | Collate | Ctype |   Access privileges
---------------------+----------+----------+---------+-------+-----------------------
 mastodon_production | mastodon | UTF8     | C       | C     |
 postgres            | postgres | UTF8     | C       | C     |
 template0           | postgres | UTF8     | C       | C     | =c/postgres          +
                     |          |          |         |       | postgres=CTc/postgres
 template1           | postgres | UTF8     | C       | C     | =c/postgres          +
                     |          |          |         |       | postgres=CTc/postgres
 test_db             | postgres | UTF8     | C       | C     |
(5 rows)
mastodon_production=> \q
mastodon@postgres:~ % exit
logout

Sauvegarde et transfert de la base de données

:warning: Pour éviter de perdre des messages, il faut faire la migration rapidement. Je vous conseille de finir de lire cet article, puis de faire les manipulations.

Arrêt des services Mastodon

Avant de faire la sauvegarde de la base de données, nous devoir arrêter les processus qui forme la plateforme Mastodon.

1
2
3
4
5
# service mastodon_web stop
# service mastodon_worker stop
# service mastodon_stream stop

Sauvegarde de la base de données

La base de données de mastodon est orchestrée par l’utilisateur et le rôle éponyme. Nous allons exécuter une commande qui nous permet de tout faire d’un coup, passer mastodon, faire la sauvegarde et redevenir root :

# sudo -u mastodon pg_dump -Fc mastodon_production > /tmp/mastodon_production_2018-06-09.db

Transfert de la sauvegarde depuis l’hôte vers la jail PostgreSQL

Avec la commande scp nous allons copier le fichier de sauvegarde depuis l’hôte vers la jail :

# scp /tmp/mastodon_production_2018-06-09.db 192.168.12.3:/tmp/.

Restauration de la sauvegarde dans la jail PostgreSQL

Maintenant que nous avons sur la jail PostgreSQL les éléments nécessaires à savoir 

  • l’utilisateur mastodon ;
  • le rôle postgres mastodon ;
  • la base de données mastodon_production ;
  • le fichier de sauvegarde de notre base de production.

    Nous pouvons injecter les données sauvegardées dans la base de données :
1
2
# su - mastodon
# pg_restore /tmp/mastodon_production-2018-06-09.db



:information_source: la restauration de la base est longue, vous avez le temps de prendre un café.

Connexion réseau

Il est maintenant essentiel que la connexion réseau (à la base mastodon_production) fonctionne (pour l’instant depuis l’hôte).

Souvenez-vous que dans l’épisode précécent de nos aventures, nous avons mofifié la ligne listen_addresses du fichier /var/db/postgresql/data96/postgres.conf de la jail PostgreSQL.

Sur cette même machine nous allons autoriser les connexions à la base PostgreSQL en provenance du réseau, avec un utilisateur et son mot de passe en indiquant sous quelle forme le mot de passe sera transféré sur le réseau. C’est le fichier /var/db/postgresql/data96/pg_hba.conf que nous allons modifer.

host    mastodon_production     mastodon        192.168.12.0/24 md5

:information_source: j’ai mis le mot clef password dans l’article sur PostgreSQL, c’est une erreur que j’ai pu rectifier grâce à des conseils venus de mastodon.

:information_source: il faut bien sûr recharger posgresql pour que les modifictions soient prises en compte.

Par précaution nous autorisons tout le réseau des jals, plus tard nous pourrons afiner en n’autorisant que la jail de mastodon.
Sur la jail PostgreSQL, il faut s’assurer que le rôle mastodon a bien un mot de passe :

1
2
3
# su - postgres
$ psql
postgres=# ALTER ROLE mastodon WITH PASSWORD 'my_password';

De retour sur la jail Mastodon, nous allons tester la connexion avec la base de données :

[mastodon@mastodon ~]$ psql -h 192.168.12.3 -d mastodon_production -U mastodon
Password for user mastodon: 
psql (9.5.12, server 9.6.8)
WARNING: psql major version 9.5, server major version 9.6.
         Some psql features might not work.
Type "help" for help.

mastodon_production=> \q
[mastodon@mastodon ~]$ 

Nous savons maintenant que la connexion avec la base de données mastodon_production qui se trouve dans la jail postgresql fonctionne.

Modification de la configuration de Mastodon

Notre mastodon utilise actuellement la base hébergée sur l’hôte et nous voudrions qu’il utilise celle de la jail.

Il faut modifier le fichier /usr/local/www/mastodon/config/.env.production2

1
2
3
4
5
6
# You may set DATABASE_URL instead for more advanced options
DB_HOST=/tmp
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=
DB_PORT=5432

Nous allons indiquer la machine qui fait tourner PostgreSQL et le mot de passe de l’utitlisateur mastodon.
La variable DB_HOST=/tmp/ devient DB_HOST=192.168.12.3.

La mise à jour de mastodon

Pour faire la mise à jour de mastodon nous allons en réalité, faire une installation toute neuve sur notre jail. C’est bien plus facile à gérer, sachant que le paquet d’origine n’existe plus le mainteneur ayant jeté l’éponge devant tant de travail.

Un guide existe

Mon camarade Gerad Niel a écrit un tutoriel que j’ai moi-même suivit pour ma propre installation. Vous le trouveez à cette adresse.

Vous pouvez suivre ce guide en n’oubliant pas que vous faites une migration.

En effet votre base de données est celle d’une install 2.3.x de mastodon et celle que vous réalisez est plus récente, il y a donc eu des modifications dans la base de données.

Vous devrez alors suivre le guide de migration.

Copiez les scripts de démarrage des trois services mastodon.

Le problème de ngnix

Tout comme pour peertube, nous allons utiliser le service ngnix de l’hôte comme proxy_pass vers notre jail qui devra gérer elle-même son service nginx.

Sur l’hôte

Comme pour peertube j’ai fais un fichier de configuration minimal que j’ai appellé mastodon-jail.conf et qui se trouve dans le répertoire /usr/local/etc/nginx/sites-available.

En voici le contenu :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    listen 443 ssl http2;
    # listen [::]:443 ssl http2;
    server_name mastodon.tamanoir.foucry.net;

    access_log /var/log/nginx/mastodon-access.log main;
    error_log /var/log/nginx/mastodon-error.log;

    ssl_protocols TLSv1.2;
    ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_certificate /usr/local/etc/letsencrypt/live/mastodon.tamanoir.foucry.net/fullchain.pem;
    ssl_certificate_key /usr/local/etc/letsencrypt/live/mastodon.tamanoir.foucry.net/privkey.pem;
    ssl_dhparam /usr/local/etc/ssl/dhparam.pem;

    location /.well-known/acme-challenge {
        root /usr/local/www/bidon;
    }

    location / {
#        try_files $uri @proxy;
        proxy_set_header Host $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 https;
        proxy_set_header Proxy "";
        proxy_pass_header Server;

        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        tcp_nodelay on;
        proxy_pass http://192.168.12.4/;
    }
}

C’est l’hôte qui gére la partie sécurité (https) avec les lignes ssl_* et qui, après avoir positionné les entêtes (proxy_header_*) de proxy, passe la main à la jail avec la commande proxy_pass http://192.168.12.4.



On fait le lien symbolique depuis sites-available vers sites-enabled :

# ln -s /usr/local/etc/nginx/sites-available/mastodon_jail.conf /usr/local/etc/nginx/sites-enabled

Et on vérifie que la syntaxe est bonne avant de rédmarrer nginx :

# nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
# service nginx restart
service nginx restart
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Stopping nginx.
Waiting for PIDS: 26069.
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Starting nginx.

Sur la jail mastodon

La configuration de nginx sur la jail mastodon est simple. il suffit de faire un lien symbolique du fichier fourni /usr/local/www/mastodon/nginx-include.conf dans /usr/local/nginx/sites-enabled :

# ln -s /usr/local/www/mastodon/nginx-include.conf /usr/local/etc/nginx/sites-enabled

Certaines modifications doivent être faite dans ce fichier aussi. Le voici dans son intégralité :

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name mastodon.tamanoir.foucry.net;

    access_log /var/log/nginx/mastodon-access.log main;
    error_log /var/log/nginx/mastodon-error.log;

    keepalive_timeout    70;
    sendfile             on;
    client_max_body_size 0;

    root /usr/local/www/mastodon/live/public;

    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    add_header Strict-Transport-Security "max-age=31536000";

    location / {
        try_files $uri @proxy;
    }

    location /sw.js {
        add_header Cache-Control no-cache;
        add_header Pragma "no-cache";
    }

    location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
        add_header Cache-Control "public, max-age=31536000, immutable";
        try_files $uri @proxy;
    }

    location @proxy {
        proxy_set_header Host $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 https;
        proxy_set_header Proxy "";
        proxy_pass_header Server;

        proxy_pass http://localhost:3000;
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        tcp_nodelay on;
    }

    location /api/v1/streaming {
        proxy_set_header Host $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 https;
        proxy_set_header Proxy "";

        proxy_pass http://localhost:4000;
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        tcp_nodelay on;
    }

    error_page 500 501 502 503 504 /500.html;
}

Comme toujours après une modification de fichier de configuration de nginx, on en vérifie la syntax et si tout va bien, on redémarre le service :

# nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
# service nginx restart
service nginx restart
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Stopping nginx.
Waiting for PIDS: 26069.
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Starting nginx.

Le moment de vérité

Normalement, si tout ce qui précéde a fonctionné, vous devriez pouvoir redémarrer les trois services qui constituent mastodon :

1
2
3
# service mastodon_web start
# service mastodon_worker start
# service mastodon_stream sart

Une fois les services démarrés (utilisez la commande service <nom_du_service> status pour vérifier, vous pouvez aller sur votre instance avec votre navigateur et pouetter que vous avez fini votre migration de base de données.

Conclusion

La migration n’est pas très longue à faire. Elle demande juste de la rigueur. C’est l’import de la base de données qui prend le plus de temps en réalité.
Vous pouvez au passage mettre en place une sauvegarde régulière de votre base de données autour de la ligne de commande que nous avons utilisé pour le dump.
Si par hasard votre migration n’avait pas réussi, il suffirait de prendre la sauvegarde du fichier /usr/local/www/mastodon/config/.env.production pour revenir à la situaiton précédente.
La prochaine étape consistera à migrer la base PostgreSQLQ de peertube, sur la jail PostgreSQL.

  1. le paquet FreeBSD de Mastodon n’est plus maintenu, le mainteneur a jetté l’éponge devant l’ampleur du travail. 

  2. pensez à faire une sauvegarde de votre fichier avant de le modifier pour pouvoir revenir en arrière en cas de problème. 


Laisser un commentaire

Les commentaires sont soumis à modération.