Ecco la documentazione dei miei errori e del mio successo finale nel migrare un’istanza di discourse da scaleway a un raspberry pi 4, con cloudflare davanti.
Ho creato un backup dall’istanza discourse di scaleway, e ./launcher stop app, e ho spento la macchina.
Ho installato Ubuntu Server 23.10 su un SSD SATA collegato tramite USB che alimenta il Raspberry Pi 4
Ho installato LXD, ho creato un pool di archiviazione loopback btrfs da 100GiB.
Ho aggiornato il profilo default a:
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: Profilo LXD predefinito
devices:
eth0:
name: eth0
network: lxdbr0
type: nic
root:
path: /
pool: default
type: disk
name: default
Ho aggiunto un profilo discourse con:
config:
limits.memory: 1GiB
limits.memory.enforce: soft
security.nesting: 'true'
description: Configurazione per le istanze Discourse
devices: {}
name: discourse
Ho creato un’immagine Ubuntu 23.10 Minimal Server con quei profili. Ci ho acceduto tramite quanto segue nel mio ~/.ssh/config:
Host LXD_DISCOURCE_INSTANCE
ProxyJump LXD_HOST
User REDACTED
IdentityFile ~/.ssh/REDACTED.pub
Ho seguito le istruzioni di installazione cloud di discourse e ho ripristinato la mia configurazione di discourse dall’istanza 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" # non necessario con cloudflare
expose:
- "80:80"
- "443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
env:
LANG: en_US.UTF-8
## Configurazione HTTPS per: templates/web.letsencrypt.ssl.template.yml
LETSENCRYPT_ACCOUNT_EMAIL: "redacted" # https
## Il nome del dominio a cui risponderà questa istanza Discourse
DISCOURSE_HOSTNAME: "redacted"
## Elenco di email separate da virgola che diventeranno amministratori e sviluppatori
## alla prima registrazione, ad esempio 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: "redacted"
## Il server di posta che questa istanza Discourse utilizzerà
DISCOURSE_SMTP_ADDRESS: "redacted"
DISCOURSE_SMTP_PORT: redacted
DISCOURSE_SMTP_USER_NAME: "redacted"
DISCOURSE_SMTP_PASSWORD: "redacted"
#DISCOURSE_SMTP_DOMAIN: discourse.example.com # (richiesto da alcuni provider)
#DISCOURSE_NOTIFICATION_EMAIL: nobody@discourse.example.com # (indirizzo da cui inviare le notifiche)
#DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456
## Qualsiasi comando personalizzato da eseguire dopo la compilazione
run:
- exec: rails r "SiteSetting.contact_email='redacted'"
- exec: rails r "SiteSetting.notification_email='redacted'"
## Il container Docker è stateless; tutti i dati sono memorizzati in /shared
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## Plugin
## 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
Prima di poter ripristinare il backup, tuttavia, ho dovuto ricostruirlo. Sfortunatamente, il pool di archiviazione btrfs si bloccava durante la fase di installazione di yarn per ore, e alla fine andava in timeout, con un carico quasi nullo sulla macchina.
Dopo aver letto un po’, ho deciso di provare a utilizzare un pool di archiviazione zfs invece, questo sarebbe andato più avanti, ma si sarebbe comunque bloccato indefinitamente dopo Background saving terminated with sucess, con un carico quasi nullo sulla macchina.
(Ho screenshot, tuttavia caricarli qui fallisce.)
Ho quindi deciso di abbandonare LXD e provarlo direttamente sull’istanza Ubuntu Server sul Raspberry Pi 4.
Per la prima volta ho avuto una ricostruzione riuscita, tuttavia tutti i tentativi di accedervi reindirizzavano a se stessa, in un loop di reindirizzamento.
Il loop di reindirizzamento aveva due cause…
Se avessi quanto segue nella mia configurazione di discourse:
expose:
- "8080:80"
- "8081:443" # https
Si reindirizzava all’infinito, volendo sempre reindirizzare a https://hostname.
Risolvere questo è stato tornare a:
expose:
- "80:80"
- "443:443" # https
In secondo luogo, qualsiasi cosa accessibile tramite il tunnel cloudflare reindirizzava all’infinito a se stessa. La causa si è rivelata essere avere un tunnel sia per HTTP che per HTTPS. Cambiare il tunnel solo a HTTPS lo ha risolto.
Altre cose che ho fatto ma a questo punto non sono sicuro se abbiano avuto importanza:
- Ho rimosso letsencrypt poiché ho utilizzato invece un certificato di origine Cloudflare.
- Ho configurato il
Origin Server Namenel tunnel HTTPS sull’hostname desiderato.
Cose che potrebbero essere migliorate:
- L’HTTPS dall’origine a Cloudflare potrebbe essere evitato se bloccassi la macchina per consentire solo connessioni da Cloudflare e impostassi un tunnel SSH. Tuttavia, non sono sicuro se Discourse funzioni meglio avendo HTTPS su se stesso (ad esempio, http2, ecc.).
- Se letsencrypt funzioni con il tunnel cloudflare (non sono riuscito a testarlo poiché quando usavo letsencrypt ottenevo loop di reindirizzamento).
Come ho eseguito il debug dei loop di reindirizzamento:
- Per eseguire il debug del loop di reindirizzamento di discourse: ho impostato
/etc/hostsper puntare il mio hostname discourse direttamente all’indirizzo IP, quindi ho usatocurl -k --head 'https://hostname:8081ecc. per testarlo. - Per eseguire il debug del loop di reindirizzamento del tunnel cloudflare: ho rimosso quello da
/etc/hostsin modo che l’hostname venga risolto tramite DNS, quindi ho usatocurl -k --head 'https://hostnameecc. per testarlo.
Ci sono un sacco di altre cose utili e apprendimenti lungo il percorso, tuttavia questo può aspettare.
Feedback per discourse:
- La ricostruzione deve essere più chiara su ciò che sta facendo. Troppo spesso ci sono lunghi ritardi senza azioni ovvie in corso.
- Scoprire perché l’esposizione di porte diverse causerebbe un loop di reindirizzamento.
- Poiché letsencrypt è diventato una cosa, la documentazione su come specificare il proprio certificato SSL è noiosa da scoprire. Inoltre, sembra che possa essere utilizzato solo un certificato poiché è fissato a
/var/discourse/shared/standalone/ssl/ssl.keyinvece di, ad esempio,/var/discourse/shared/standalone/ssl/CONTAINER_ID.key, ad esempio/var/discourse/shared/standalone/ssl/app.key- cloudflare fornisce certificati di origine, quindi questa è una buona opzione per gli utenti cloudflare. - La pubblicazione di una guida completa passo dopo passo per cloudflare + raspberry pi 4 avrebbe aiutato enormemente, attualmente tali guide delegano troppe informazioni a terze parti che non hanno consapevolezza reciproca, e tutta la complessità e il debug risiedono nel modo in cui le diverse parti funzionano insieme, non in come funzionano da sole.
Altri todo per un giorno:
- Scoprire perché si bloccava in LXD.
- Vedere se funziona in LXD su un Raspberry Pi 5, o su Multipass su macOS, o LXD con il pool di archiviazione che è una partizione/disco invece di un file di loopback: poiché allora non devo sprecare un’intera macchina per questo.
- Vedere se posso far sì che docker e launcher non richiedano sudo.