Auto-hébergement
Runtime Docker portable pour exécuter Yayaw sans Vercel ni stockage Supabase.
Périmètre
La première cible auto-hébergée supportée est un déploiement Docker unique:
- serveur Next.js standalone
- Postgres
- MinIO ou autre stockage objet compatible S3
- worker base de données Page AI
- Caddy ou autre proxy inverse qui préserve les en-têtes d'hôte d'origine
Ce chemin prouve la portabilité. Il ne remplace pas Stripe, OpenAI, Resend, l'accès au code GitHub, ni toutes les fonctions propres aux plateformes de déploiement. L'analytics peut utiliser Umami auto-hébergé ou un fournisseur externe comme PostHog.
Fichiers
Dockerfiledocker-compose.self-host.yml.env.self-host.exampledeploy/self-host/Caddyfile
next.config.ts utilise output: "standalone" afin que l'image de production
puisse lancer le serveur Next.js tracé avec node server.js.
Démarrage Rapide
cp .env.self-host.example .env.self-host
perl -0777 -i -pe "s/^BETTER_AUTH_SECRET=$/BETTER_AUTH_SECRET=$(openssl rand -hex 32)/m" .env.self-host
docker compose --env-file .env.self-host -f docker-compose.self-host.yml --profile setup run --rm migrate
docker compose --env-file .env.self-host -f docker-compose.self-host.yml up --buildDéfinissez BETTER_AUTH_SECRET avant le premier build. Le Dockerfile refuse de
construire avec un secret vide parce que les routes Better Auth sont évaluées
pendant next build.
Le profil setup lance drizzle-kit push pour synchroniser le schéma Drizzle
courant dans la base auto-hébergée, puis exécute le seed idempotent pour les
rôles, indicateurs de fonctionnalité, catalogue de facturation, thèmes et
contenu CMS de départ.
Ouvrez http://localhost:8080. MinIO est exposé sur http://localhost:9000 pour l'API S3, et sa console sur http://localhost:9001. Les URL publiques de ressources sont servies via Caddy sur l'origine de l'app par défaut.
Environnement Runtime
Valeurs auto-hébergées importantes:
NEXT_PUBLIC_BASE_URL=http://localhost:8080
BETTER_AUTH_SECRET=<generate-a-long-random-secret>
DATABASE_URL=postgresql://yayaw:yayaw@postgres:5432/yayaw
STORAGE_PROVIDER=s3
STORAGE_MEDIA_BUCKET=media
STORAGE_PUBLIC_BASE_URL=http://localhost:8080
S3_ENDPOINT=http://minio:9000
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=yayaw
S3_SECRET_ACCESS_KEY=yayaw-minio-password
S3_FORCE_PATH_STYLE=true
PUBLIC_DOMAIN_PROVIDER=manual-dns
PAGE_AI_QUEUE_DRIVER=db-worker
DEPLOYMENT_PROVIDER=static
DEPLOYMENT_URL=http://localhost:8080
NEXT_PUBLIC_ANALYTICS_PROVIDER=none
NEXT_PUBLIC_ANALYTICS_CAPTURE_MODE=hybrid
NEXT_PUBLIC_UMAMI_HOST_URL=
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
UMAMI_API_URL=
UMAMI_WEBSITE_ID=
UMAMI_API_TOKEN=
UMAMI_API_KEY=
UMAMI_USERNAME=
UMAMI_PASSWORD=
RESEND_API_KEY=
EMAIL_SENDER=team@yayaw.app
EMAIL_SUPPORT=support@yayaw.app
EMAIL_USERNAME=Yayaw TeamLes valeurs EMAIL_* permettent aux e-mails transactionnels de fonctionner
avant la connexion d'un admin. Après setup, Admin > Site Settings > Email peut
les surcharger au runtime.
Les valeurs NEXT_PUBLIC_* sont intégrées au bundle navigateur au moment du
build. Les commandes Compose ci-dessus passent .env.self-host comme fichier
d'environnement de build pour que ces valeurs atteignent les arguments Docker.
Reconstruisez une image lorsqu'elles changent. BETTER_AUTH_SECRET est aussi
fourni au build Docker afin que Next.js puisse évaluer les routes Better Auth
pendant next build; gardez-le aussi présent au runtime.
Les autres valeurs uniquement serveur peuvent changer dans le magasin de secrets
de l'orchestrateur ou .env.self-host, puis par redémarrage des conteneurs
concernés.
Les builds Docker fixent NEXT_BUILD_WORKERS à 1 par défaut pour garder la
génération statique Next.js stable sur de petites machines. Augmentez cette
valeur comme variable ou argument de build uniquement après vérification de la
marge CPU et mémoire.
Les pages de documentation sont rendues dynamiquement dans les builds auto-hébergés au lieu d'être prégénérées pendant la construction d'image. Cela évite aux petits hôtes Coolify ou Docker de consacrer l'essentiel du budget de déploiement aux pages docs, tout en les servant normalement au runtime.
YAYAW_APP_IMAGE et YAYAW_WORKER_IMAGE contrôlent les tags d'image Compose
utilisés par l'app et les cibles worker Bun. Le service migrate utilise
volontairement le même tag d'image worker que le worker long-lived, afin que
Docker et Coolify réutilisent cette cible de build entre services.
docker-compose.coolify.yml est optimisé pour le chemin Coolify managé par
Yayaw et attend des images app et worker déjà présentes sur le serveur Coolify.
GitHub Actions construit ces images pour linux/arm64, les charge sur la VM Mac
mini, définit YAYAW_APP_IMAGE et YAYAW_WORKER_IMAGE via l'API Coolify, puis
déclenche le déploiement Compose. Utilisez docker-compose.self-host.yml pour
les installations locales ou clients portables qui doivent construire les images
directement depuis le code source.
Dans Coolify, ces variables de tags d'image doivent être disponibles au build
time comme au runtime, car Compose résout l'interpolation image: avant de
démarrer les services.
Proxy Inverse
Le proxy doit préserver:
HostX-Forwarded-HostX-Forwarded-Proto- en-têtes de transmission de l'IP client
Les pages publiques d'organisation routent par hostname; perdre le Host
d'origine casse la résolution des domaines personnalisés. Gardez un buffering
compatible avec les réponses streaming et l'optimisation d'images Next.js.
Lorsque STORAGE_PUBLIC_BASE_URL pointe vers l'origine app ou CDN, routez tous
les préfixes de buckets publics vers MinIO avant le repli vers l'app. Le fichier
Caddy fourni gère les buckets publics intégrés:
handle /media/* {
reverse_proxy minio:9000
}
handle /organization-logos/* {
reverse_proxy minio:9000
}Si STORAGE_PUBLIC_BASE_URL pointe directement vers une origine dédiée de
stockage objet ou CDN, configurez cette origine pour servir les mêmes chemins
/<bucket>/<key>.
Stockage
La pile Compose démarre MinIO et crée les buckets publics media et
organization-logos. Les médias téléversés et les miniatures utilisent des
opérations compatibles S3; les pages publiées utilisent les URL publiques
stockées.
Les URL média Supabase existantes ne sont pas migrées par la pile auto-hébergée. Gardez l'ancien bucket joignable ou prévoyez une migration média séparée.
Domaines Publics
Les domaines auto-hébergés utilisent une vérification DNS manuelle:
- Ajoutez le hostname depuis les réglages d'organisation ou MCP.
- Publiez le challenge TXT affiché par le dashboard.
- Pointez le domaine vers l'ingress avec les enregistrements CNAME ou A configurés.
- Relancez le check ou la vérification du domaine.
- Configurez TLS au niveau du proxy.
Utilisez PUBLIC_DOMAIN_CNAME_TARGET et PUBLIC_DOMAIN_IPV4_TARGETS pour
afficher les indications de routage à l'opérateur. Utilisez APP_MANAGED_HOSTS
et RESERVED_PUBLIC_DOMAIN_SUFFIXES pour empêcher les clients de réclamer des
hôtes possédés par l'app ou réservés.
Worker
Lancez un ou plusieurs workers Page AI avec:
bun run worker:page-aiLe worker interroge Postgres pour les runs Page AI durables. Vercel Queues reste
disponible sur Vercel, mais le défaut de production auto-hébergé est
db-worker.
Exploitation
- Lancez le profil
setupavant le premier démarrage et après les changements de schéma afin de synchroniser la base et réparer les seeds. - Persistez les volumes Postgres, MinIO, Caddy et
.next/cache. - Sauvegardez Postgres et le stockage objet ensemble pour garder les lignes média et les objets synchronisés.
- Gardez
NEXT_SERVER_ACTIONS_ENCRYPTION_KEYet une stratégie de build ID stable comme suivi avant de passer à plusieurs instances app. - Choisissez un fournisseur d'analytics avec
NEXT_PUBLIC_ANALYTICS_PROVIDER. Valeurs supportées:posthog,umami,none; Umami requiertNEXT_PUBLIC_UMAMI_*pour le suivi et les variables APIUMAMI_*pour les données dashboard. - Choisissez un mode de capture analytics avec
NEXT_PUBLIC_ANALYTICS_CAPTURE_MODE. Utilisezserverpour éviter tout script analytics navigateur; utilisezhybridpour combiner analytics produit navigateur et conversions facturation côté serveur. - Gardez les risques fournisseurs Stripe, OpenAI, Resend et GitHub documentés tant que leurs contrats fournisseurs n'existent pas.
Vérifications Production
Après un déploiement production, vérifiez la configuration depuis le conteneur app en cours d'exécution plutôt que seulement depuis l'UI de l'orchestrateur. Signaux auto-hébergés importants:
STORAGE_PROVIDER=s3STORAGE_PUBLIC_BASE_URLpointe vers l'origine app, CDN ou stockage objet qui sert les chemins/<bucket>/<key>S3_ENDPOINTest joignable depuis les conteneurs app et workerNEXT_PUBLIC_ANALYTICS_PROVIDER=umamilorsque vous utilisez Umami auto-hébergéNEXT_PUBLIC_ANALYTICS_CAPTURE_MODE=serverlorsqu'aucun script analytics navigateur ne doit être rendu
Pour les médias, téléversez un petit objet avec les mêmes identifiants S3 que
l'app, puis récupérez son URL publique. L'URL publique doit utiliser
STORAGE_PUBLIC_BASE_URL, par exemple /media/<key> quand Caddy route le
préfixe de bucket vers MinIO. Si ce test stockage réussit mais que le
téléversement dashboard échoue, inspectez l'organisation active, les permissions
média, le quota de plan, le type de fichier et la taille avant de changer de
fournisseur de stockage.
Pour une configuration sans analytics navigateur, récupérez une page publique et
confirmez que le HTML ne contient pas l'URL du script Umami ni
data-website-id. Les analytics dashboard ont encore besoin d'identifiants API
Umami via UMAMI_API_TOKEN, UMAMI_API_KEY ou
UMAMI_USERNAME/UMAMI_PASSWORD; la capture événementielle côté serveur
utilise /api/send et ne requiert pas le script navigateur.
Validation
docker compose --env-file .env.self-host -f docker-compose.self-host.yml config
bun test src/config/storage.config.test.ts src/lib/storage.test.ts
bun test src/lib/server/services/organization-domains/organization-public-domains.test.ts
bun test src/lib/server/services/pages/page-ai-runner.test.ts