---
title: "Déployez Mastodon sur Pethost en un clic"
description: "Votre propre serveur dans le fédivers : messages, abonnements et réponses au-delà de Mastodon. Un template pour Pethost : en une minute ou deux l’application tourne sur votre machine, en HTTPS à sa propre adresse, avec des sauvegardes chaque nuit."
---

[← Tous les templates](https://pethost.dev/fr/templates/)

# Déployez Mastodon sur Pethost en un clic

Votre propre serveur dans le fédivers : messages, abonnements et réponses au-delà de Mastodon

[Déployer sur Pethost](https://console.pethost.dev/?template=mastodon)

## Ce qui se passe

1. Vous vous connectez à Pethost ou créez un compte, avec une clé d’accès, GitHub ou Google.
2. Pas encore de machine ? Vous choisissez une offre, et nous en préparons une pour vous. Le lien attend dans votre navigateur qu’elle soit prête.
3. Nouveau projet s’ouvre sur l’application. Vous remplissez ce qu’elle demande et cliquez sur Créer le projet : **Nom d’utilisateur**, **E-mail**, **Mot de passe administrateur**.
4. En une minute ou deux, l’application tourne à sa propre adresse en HTTPS. Ses secrets sont créés pour elle au hasard, et ses données sont dans la sauvegarde nocturne.
5. C’est un projet comme les autres : son compose.yaml, son .env, ses logs et un terminal sont dans le panel, et votre agent peut le modifier, revenir à une version précédente ou le restaurer.

## Premiers pas

Connectez-vous avec l’e-mail et le mot de passe indiqués : vous êtes le propriétaire du serveur, avec le nom d’utilisateur indiqué. L’e-mail doit pouvoir recevoir du courrier : Mastodon vérifie son domaine, et sinon le déploiement échoue. Mastodon réserve des noms comme admin ou root. Les inscriptions sont fermées ; ouvrez-les dans Préférences, Administration, Paramètres du serveur. Mastodon n’envoie aucun e-mail tant que SMTP_SERVER, SMTP_LOGIN, SMTP_PASSWORD et SMTP_FROM_ADDRESS ne sont pas dans le .env du projet et que le projet n’a pas redémarré. Chaque compte reste lié à cette adresse pour de bon : donnez au projet son adresse définitive avant de publier. Les médias envoyés sont conservés dans /opt/mastodon/public/system.

## Ce qui tourne

Le template, c’est ce compose.yaml et les variables qu’il écrit dans le .env du projet. Pethost exécute le fichier tel qu’il est écrit.

```
# Mastodon's docker-compose.yml with a small Caddy in front, which gives the streaming
# API its path on the project's address, as Mastodon's nginx does.
x-env: &env
  LOCAL_DOMAIN: ${HOST}
  DB_HOST: db
  DB_PORT: "5432"
  DB_USER: mastodon
  DB_NAME: mastodon
  DB_PASS: ${DB_PASSWORD}
  REDIS_HOST: redis
  REDIS_PORT: "6379"
  SECRET_KEY_BASE: ${SECRET_KEY_BASE}
  ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: ${AR_DETERMINISTIC_KEY}
  ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: ${AR_KEY_DERIVATION_SALT}
  ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: ${AR_PRIMARY_KEY}
  VAPID_SEED: ${VAPID_SEED}
  ES_ENABLED: "false"
  WEB_CONCURRENCY: "1"
  SMTP_SERVER: ${SMTP_SERVER:-}
  SMTP_PORT: ${SMTP_PORT:-587}
  SMTP_LOGIN: ${SMTP_LOGIN:-}
  SMTP_PASSWORD: ${SMTP_PASSWORD:-}
  SMTP_FROM_ADDRESS: ${SMTP_FROM_ADDRESS:-}

# Web push needs a VAPID key pair. Its private key is the 32 random bytes of VAPID_SEED,
# and the public key is derived from it, so web and sidekiq read the same pair and
# nothing is kept apart from .env.
x-vapid: &vapid |
  eval "$$(ruby -ropenssl -rbase64 -e '
    d = [ENV.fetch("VAPID_SEED")].pack("H*")
    point = OpenSSL::PKey::EC::Group.new("prime256v1").generator.mul(OpenSSL::BN.new(d, 2))
    puts "export VAPID_PRIVATE_KEY=#{Base64.urlsafe_encode64(d)}"
    puts "export VAPID_PUBLIC_KEY=#{Base64.urlsafe_encode64(point.to_octet_string(:uncompressed))}"
  ')"

services:
  proxy:
    image: caddy:2.10-alpine
    restart: unless-stopped
    configs:
      - source: caddy
        target: /etc/caddy/Caddyfile
    depends_on:
      - web
      - streaming

  web:
    image: ghcr.io/mastodon/mastodon:v4.7.3
    restart: unless-stopped
    environment:
      <<: *env
      ADMIN_USERNAME: ${ADMIN_USERNAME}
      ADMIN_EMAIL: ${ADMIN_EMAIL}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      VAPID: *vapid
    # Every start migrates the database and seeds what is missing; the first one also
    # makes the owner from the username, email and password given. Registrations stay
    # closed, Mastodon's default, so nobody else can sign up until the owner opens them.
    command:
      - sh
      - -c
      - |
        set -e
        eval "$$VAPID"
        bundle exec rails db:prepare db:seed
        bundle exec rails runner '
          owner = UserRole.find_by!(name: "Owner")
          unless User.exists?(role_id: owner.id)
            password = ENV.fetch("ADMIN_PASSWORD")
            user = User.create!(
              email: ENV.fetch("ADMIN_EMAIL"),
              password: password,
              password_confirmation: password,
              account: Account.new(username: ENV.fetch("ADMIN_USERNAME")),
              role: owner,
              confirmed_at: Time.now.utc,
              agreement: true,
              approved: true,
              bypass_registration_checks: true
            )
            # Closed registrations leave a new user waiting for approval.
            user.approve!
          end
        '
        exec bundle exec puma -C config/puma.rb
    volumes:
      - system:/opt/mastodon/public/system
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "curl -s --noproxy localhost localhost:3000/health | grep -q OK"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 300s

  streaming:
    image: ghcr.io/mastodon/mastodon-streaming:v4.7.3
    restart: unless-stopped
    environment: *env
    command: node ./streaming/index.js
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "curl -s --noproxy localhost localhost:4000/api/v1/streaming/health | grep -q OK"]
      interval: 10s
      timeout: 5s
      retries: 5

  sidekiq:
    image: ghcr.io/mastodon/mastodon:v4.7.3
    restart: unless-stopped
    environment:
      <<: *env
      VAPID: *vapid
    command:
      - sh
      - -c
      - |
        eval "$$VAPID"
        exec bundle exec sidekiq
    volumes:
      - system:/opt/mastodon/public/system
    depends_on:
      web:
        condition: service_healthy

  db:
    image: postgres:17
    restart: unless-stopped
    shm_size: 256mb
    environment:
      POSTGRES_USER: mastodon
      POSTGRES_DB: mastodon
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "mastodon"]
      interval: 5s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7.4
    restart: unless-stopped
    volumes:
      - redis:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 10

configs:
  # The machine's proxy is trusted for X-Forwarded-Proto, so Rails sees HTTPS.
  caddy:
    content: |
      {
        admin off
        auto_https off
        servers {
          trusted_proxies static private_ranges
        }
      }

      :8080 {
        reverse_proxy /api/v1/streaming* streaming:4000
        reverse_proxy web:3000
      }

volumes:
  system:
  db:
  redis:
```

[compose.yaml](https://pethost.dev/templates/mastodon/compose.yaml)[Le voir sur GitHub](https://github.com/pethost-dev/templates/tree/main/mastodon)

Pethost · Stephan Gomer · NIP 1133096755

[Templates](https://pethost.dev/fr/templates/) [À propos](https://pethost.dev/about/) [Blog](https://pethost.dev/blog/) [Conditions](https://pethost.dev/terms/) [Confidentialité](https://pethost.dev/privacy/) [Remboursements](https://pethost.dev/refunds/) [API](https://pethost.dev/docs/api/) [CLI](https://pethost.dev/docs/cli/) [Plugin](https://github.com/pethost-dev/plugin) [support@pethost.dev](mailto:support@pethost.dev)
