Voici la documentation de mes déboires et de mon succès éventuel à migrer une instance discourse de scaleway vers un raspberry pi 4, avec cloudflare devant.
Créé une sauvegarde de l’instance discourse de scaleway, et ./launcher stop app, et arrêté la machine.
Installé Ubuntu Server 23.10 sur un SSD SATA connecté en USB alimentant le Raspberry Pi 4
Installé LXD, créé un pool de stockage loopback btrfs de 100 Gio.
Mis à jour le profil default pour :
config:
cloud-init.user-data: |
#cloud-config
ssh_pwauth: false
package_update: true
package_upgrade: true
packages:
- openssh-server
- vim
- git
- rsync
users:
- name: root
lock_passwd: true
ssh_import_id: gh:balupton
description: Profil LXD par défaut
devices:
eth0:
name: eth0
network: lxdbr0
type: nic
root:
path: /
pool: default
type: disk
name: default
Ajouté un profil discourse avec :
config:
limits.memory: 1GiB
limits.memory.enforce: soft
security.nesting: 'true'
description: Configuration pour les instances Discourse
devices: {}
name: discourse
Créé une image Ubuntu 23.10 Minimal Server avec ces profils. Accédé via la configuration suivante dans mon ~/.ssh/config :
Host LXD_DISCOURCE_INSTANCE
ProxyJump LXD_HOST
User REDACTED
IdentityFile ~/.ssh/REDACTED.pub
Suivi les instructions d’installation cloud de discourse et restauré ma configuration discourse depuis l’instance scaleway :
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/cloudflare.template.yml"
- "templates/web.ssl.template.yml" # https
- "templates/web.letsencrypt.ssl.template.yml" # https
# - "templates/web.ratelimited.template.yml" # pas nécessaire avec cloudflare
expose:
- "80:80"
- "443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
env:
LANG: en_US.UTF-8
## Configuration HTTPS pour : templates/web.letsencrypt.ssl.template.yml
LETSENCRYPT_ACCOUNT_EMAIL: "redacted" # https
## Le nom de domaine auquel cette instance Discourse répondra
DISCOURSE_HOSTNAME: "redacted"
## Liste des emails délimités par des virgules qui seront faits administrateurs et développeurs
## lors de la première inscription exemple 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: "redacted"
## Le serveur de messagerie que cette instance Discourse utilisera
DISCOURSE_SMTP_ADDRESS: "redacted"
DISCOURSE_SMTP_PORT: redacted
DISCOURSE_SMTP_USER_NAME: "redacted"
DISCOURSE_SMTP_PASSWORD: "redacted"
#DISCOURSE_SMTP_DOMAIN: discourse.example.com # (requis par certains fournisseurs)
#DISCOURSE_NOTIFICATION_EMAIL: nobody@discourse.example.com # (adresse pour envoyer les notifications depuis)
#DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456
## Toutes commandes personnalisées à exécuter après la construction
run:
- exec: rails r "SiteSetting.contact_email='redacted'"
- exec: rails r "SiteSetting.notification_email='redacted'"
## Le conteneur Docker est sans état ; toutes les données sont stockées dans /shared
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## Plugins
## https://meta.discourse.org/t/19157
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/discourse-adplugin.git
- git clone https://github.com/discourse/discourse-affiliate.git
- git clone https://github.com/discourse/discourse-assign.git
- git clone https://github.com/discourse/discourse-docs.git
- git clone https://github.com/discourse/discourse-topic-voting.git
- git clone https://github.com/discourse/discourse-github.git
- git clone https://github.com/discourse/discourse-saved-searches.git
- git clone https://github.com/discourse/discourse-shared-edits.git
- git clone https://github.com/discourse/discourse-solved.git
# - git clone https://github.com/discourse/discourse-encrypt.git
# - git clone https://github.com/discourse/discourse-reactions.git
# - git clone https://github.com/discourse/discourse-subscriptions.git
Avant de pouvoir restaurer la sauvegarde, j’ai dû la reconstruire. Malheureusement, le pool de stockage btrfs se bloquait à l’étape d’installation de yarn pendant des heures, puis finissait par expirer, avec une charge quasi nulle sur la machine.
Après quelques recherches, j’ai décidé d’essayer d’utiliser un pool de stockage zfs à la place, cela a permis d’aller plus loin, mais bloquait toujours indéfiniment après “Sauvegarde en arrière-plan terminée avec succès”, avec une charge quasi nulle sur la machine.
(J’ai des captures d’écran, mais leur téléchargement ici échoue.)
J’ai ensuite décidé d’abandonner LXD et d’essayer directement sur l’instance Ubuntu Server sur le Raspberry Pi 4.
Pour la première fois, j’ai eu une reconstruction réussie, cependant toutes les tentatives d’accès redirigeaient vers lui-même, dans une boucle de redirection.
La boucle de redirection avait deux causes…
Si j’avais ceci dans ma configuration discourse :
expose:
- "8080:80"
- "8081:443" # https
Cela redirigeait sans fin, voulant toujours rediriger vers https://hostname.
Pour résoudre cela, il fallait revenir à :
expose:
- "80:80"
- "443:443" # https
Deuxièmement, tout ce qui était accédé via le tunnel cloudflare redirigeait également sans fin vers lui-même. La cause s’est avérée être la présence d’un tunnel pour HTTP et d’un tunnel pour HTTPS. Changer le tunnel pour HTTPS uniquement a résolu le problème.
Autres choses que j’ai faites mais dont je ne suis pas sûr si elles ont eu un impact à ce stade :
- J’ai supprimé letsencrypt car j’utilisais un certificat d’origine Cloudflare à la place.
- J’ai configuré le
Nom du serveur d'originedans le tunnel HTTPS pour qu’il soit le nom d’hôte prévu.
Points à améliorer :
- Le HTTPS de l’origine vers Cloudflare pourrait être évité si je verrouille la machine pour n’autoriser que les connexions de Cloudflare, et que je configure un tunnel SSH. Cependant, je ne suis pas sûr si Discourse fonctionne mieux avec le HTTPS activé lui-même (par exemple, http2, etc.).
- Si letsencrypt fonctionne avec le tunnel cloudflare (je n’ai pas pu le tester car lorsque j’utilisais letsencrypt, j’avais les boucles de redirection).
Comment j’ai débogué les boucles de redirection :
- Pour déboguer la boucle de redirection discourse : j’ai défini
/etc/hostspour pointer mon nom d’hôte discourse directement vers l’adresse IP, puis j’ai utilisécurl -k --head 'https://hostname:8081etc pour le tester. - Pour déboguer la boucle de redirection du tunnel cloudflare : j’ai retiré cela de
/etc/hostsafin que le nom d’hôte soit résolu via DNS, puis j’ai utilisécurl -k --head 'https://hostnameetc pour le tester.
Il y a un tas d’autres choses astucieuses et d’apprentissages en cours de route, mais cela peut attendre.
Commentaires pour discourse :
- La reconstruction doit être plus claire sur ce qu’elle fait. Trop souvent, il y a de longs délais sans action évidente.
- Découvrir pourquoi l’exposition de différents ports causerait une boucle de redirection.
- Depuis que letsencrypt est devenu une chose, la documentation sur la façon de spécifier son propre certificat SSL est fastidieuse à trouver. De plus, il semble qu’un seul certificat puisse être utilisé car il est fixé à
/var/discourse/shared/standalone/ssl/ssl.keyau lieu de, par exemple,/var/discourse/shared/standalone/ssl/CONTAINER_ID.key, par exemple/var/discourse/shared/standalone/ssl/app.key— cloudflare fournit des certificats d’origine, c’est donc une bonne option pour les utilisateurs de cloudflare. - La publication d’un guide complet, étape par étape et tout compris pour cloudflare + raspberry pi 4 m’aurait énormément aidé, actuellement de tels guides délèguent trop d’informations à des tiers qui n’ont aucune conscience les uns des autres, et toute la complexité et le débogage résident dans la façon dont les différentes parties fonctionnent ensemble, pas dans la façon dont elles fonctionnent seules.
Autres tâches à faire un jour :
- Découvrir pourquoi cela se bloquait dans LXD.
- Voir si cela fonctionne dans LXD sur un Raspberry Pi 5, ou sur Multipass sur macOS, ou LXD avec le pool de stockage étant une partition/disque au lieu d’un fichier loopback : car alors je n’ai pas à gaspiller une machine entière pour cela.
- Voir si je peux faire en sorte que docker et launcher n’aient pas besoin de sudo.