Déployez Mastodon sur Pethost en un clic
Votre propre serveur dans le fédivers : messages, abonnements et réponses au-delà de Mastodon
Ce qui se passe
- Vous vous connectez à Pethost ou créez un compte, avec une clé d’accès, GitHub ou Google.
- 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.
- 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.
- 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.
- 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: