Configuration multisite avec Docker

:warning: While multisite is supported in the Discourse application, this is an advanced sysadmin setup. If you don’t know what you’re doing, do not set up multisite. The Discourse team is unable to provide multisite configuration support.

If you wish to host multiple domains on a singled Docker setup, you’ll need a multisite configuration. Here are the basic building blocks for one.

Understand hooks

Multisite is a fairly advanced topic. Before attempting a multisite build, spend some time to learn about them.

Discourse templates use pups; its rules are simple and powerful.

Each rule you run may define a hook:

run:
  exec:
    cd: some/path
    hook: my_hook
    cmd:
      - echo 1

Later on in your container you can insert rules before or after a hook:

hooks:
  before_my_hook:
    - exec: echo "I ran before"
  after_my_hook:
     - exec: echo "I ran after"

So in the example above you will see output like the following:

I ran before
1
I ran after

You can read through the templates in /var/discourse/templates to see what hooks you have available.

Amend your standalone container to provision the second site tenant

Replace the entire hooks section with:

hooks:
  after_postgres:
     - exec: sudo -u postgres createdb b_discourse || exit 0
     - exec:
          stdin: |
            grant all privileges on database b_discourse to discourse;
          cmd: sudo -u postgres psql b_discourse
          raise_on_fail: false

     - exec: /bin/bash -c 'sudo -u postgres psql b_discourse <<< "alter schema public owner to discourse;"'
     - exec: /bin/bash -c 'sudo -u postgres psql b_discourse <<< "create extension if not exists hstore;"'
     - exec: /bin/bash -c 'sudo -u postgres psql b_discourse <<< "create extension if not exists pg_trgm;"'

  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - mkdir -p plugins
          - git clone https://github.com/discourse/docker_manager.git
  before_bundle_exec:
    - file:
        path: $home/config/multisite.yml
        contents: |
         secondsite:
           adapter: postgresql
           database: b_discourse
           pool: 25
           timeout: 5000
           db_id: 2
           host_names:
             - b.discourse.example.com

  after_bundle_exec:
    - exec: cd /var/www/discourse && sudo -E -u discourse bundle exec rake multisite:migrate

There are 3 hooks in play:

  1. after_postgres ensures that after postgres is installed an additional db called b_discourse is created with the appropriate permissions.

  2. before_bundle_exec, ensures docker_manager is in place and that the multisite.yml file is in place (which defines where to find the databases)

  3. after_bundle_exec, runs the custom db migration task rake multisite:migrate this ensures all the dbs are up to date.

Note on configuration

The above sample can be split into data container / app container if needed. Just run the after_postgres hook in the data container and the rest in web container.

The above sample can be extended to provision even more DBs. To do so, provision more DBs by duplicating the create db etc calls, and make sure you add additional sites in multisite.yml.

Make sure you amend the host_names node in multisite.yml to match the actual host name you wish to host.

Also, if you plan to run HTTPS, you will need a proxy in front of the site to handle it as the built in letsencrypt functionality will not work in a multisite scenario.

Last edited by @JammyDodger 2024-05-26T20:56:50Z

Check documentPerform check on document:
68 « J'aime »

Je me demandais à quoi servait la valeur db_id: 2 dans la configuration suggérée ci-dessus ?

De plus, quelle est la procédure pour ajouter un nouveau site à la configuration multisite existante ? Est-ce simplement :

  • Mettre à jour le yaml
  • ./launcher bootstrap multisite [^1]
  • ./launcher start multisite

Je me demandais s’il existait un moyen d’éviter d’impacter tous les autres sites existants en effectuant un bootstrap ou une reconstruction complète et en ajoutant d’une manière ou d’une autre uniquement la base de données supplémentaire nécessaire ?

[^1] : J’ai d’abord essayé ./launcher rebuild multisite, mais cela semble échouer.

Je pense que l’identifiant de la base de données n’est plus nécessaire.

Vous pouvez simplement modifier le fichier multisite avec le nouveau site et effectuer un

sv restart unicorn

Puis migrer la base de données.

1 « J'aime »

Tu me sauves la vie !

Il me manquait cette commande pour redémarrer (j’avais aussi essayé sv reload unicorn mais d’une manière ou d’une autre, cela n’a pas suffi).

Pour ce qui est de la création de la base de données, existe-t-il déjà un moyen de le faire automatiquement ? Ce serait bien d’avoir rake db:create[mynewdbname]. Sinon, je peux écrire un petit script shell.

Pour le moment, je crée manuellement (création de la db et définition des permissions), puis j’exécute RAILS_DB=newdb rake db:migrate pour la peupler.

Et juste pour vérifier si je fais quelque chose de stupide :

  • Pour le moment, j’édite le fichier multisite dans docker (/var/www/discourse/config/multisite.yml)
  • Je crée la base de données manuellement
  • J’exécute rake db:migrate
  • Je redémarre unicorn avec sv restart
  • Je dois également éditer le fichier yaml en dehors de docker afin que la configuration multisite soit synchronisée en cas de future reconstruction ou de mises à niveau.

Suis-je idiot d’éditer la configuration multisite à 2 endroits différents alors qu’il existe déjà un moyen de l’éditer à un seul endroit et de pousser les changements ?

Serait-il possible de nettoyer un peu cette documentation et d’y ajouter quelques indications supplémentaires ? Je suis complètement novice en Docker, et bien que j’aie de l’expérience avec les serveurs Linux, je ne suis pas un expert. Je suis un ancien adepte des cron jobs et des scripts shell, et vous savez, des choses étranges comme ça avec Apache multi-site, etc. Mais ceci est un peu plus complexe et utilise un langage de programmation différent de celui auquel je suis habitué… Peut-être même une vidéo de démonstration ? Ce serait bien si Discourse était simplement prêt pour le multi-site, et qu’ainsi tout ce que vous auriez à faire serait de modifier quelques fichiers, etc.

Collez simplement cette strophe de texte et modifiez-la selon vos besoins.

Vous aurez ensuite besoin d’un proxy inverse ou de suivre Configurer Let’s Encrypt avec plusieurs domaines / redirections pour obtenir des certificats pour tous les domaines.

Voir aussi Configuration multisite avec Let’s Encrypt et sans proxy inverse. Mais cela doit être mis à jour pour inclure une autre ligne requise que vous pouvez obtenir du lien précédent. J’avais l’intention de le mettre à jour mais je n’ai pas réussi.

1 « J'aime »

Si je fais du multisite, vers où dois-je pointer mon domaine ? La même adresse IP que le serveur (qui héberge un autre forum) ?

Oui, faites pointer tous les domaines vers la même adresse IP de serveur.
Configurez un proxy inverse avec Nginx ou Caddy server.
Caddy est le meilleur car il offre des certificats SSL automatiques gratuits à tous vos domaines.

1 « J'aime »