Opérations

Auto-hébergement

Faire tourner ta propre instance routess avec Docker Compose.

Ce guide pas à pas met une instance routess en route sur ta propre machine ou ton serveur en environ cinq minutes. Pour Kubernetes, voir Kubernetes.

Ce dont tu as besoin

  • Docker et Docker Compose v2 (un Docker Desktop moderne ou Docker Engine est livré avec les deux).
  • Un client Google OAuth pour la connexion Google (le fichier compose l'exige). Les utilisateurs peuvent aussi se connecter avec e-mail + mot de passe une fois la stack en place.
  • Un token d'accès Mapbox ; le tier gratuit suffit.
  • Un moteur de routage Valhalla (VALHALLA_URL). Le calcul d'itinéraire et l'analyse de surface passent par lui ; sans lui, les endpoints de routage renvoient 503.
  • Des chaînes aléatoires longues pour JWT_SECRET, ANALYTICS_SALT, PAT_PEPPER et DB_PASSWORD. Génère-les avec openssl rand -base64 32.

Optionnels, désactivés proprement quand non définis :

  • Resend pour les e-mails transactionnels (sans lui, les URL de vérification sont écrites sur stdout).
  • Sentry / GlitchTip pour le reporting d'erreurs du navigateur.
  • Umami pour l'analytics produit.
  • Rôle admin pour accéder au panneau d'administration intégré à l'application.

Configurer Google OAuth

  1. Ouvre la page des identifiants de la Google Cloud Console.
  2. Crée un OAuth 2.0 Client ID de type Web application.
  3. Sous Authorized JavaScript origins, ajoute l'URL que tes utilisateurs ouvriront (par ex. http://localhost:8080 ou https://routess.example.com).
  4. Sous Authorized redirect URIs, ajoute <your-web-url>/auth/callback.
  5. Copie le Client ID et le Client secret.

Obtenir un token Mapbox

  1. Inscris-toi sur account.mapbox.com.
  2. Crée un token d'accès public (pk.…) sous Access tokens.
  3. Restreins-le à ton domaine quand tu passes en production.

Le lancer

git clone https://github.com/robbeverhelst/routess.git
cd routess
cp docker/.env.selfhost.example .env
# edit .env and fill in the required values
docker compose -f docker/compose.selfhost.yaml --project-directory . up -d

Ouvre ensuite http://localhost:8080.

La stack démarre quatre conteneurs :

ServiceImagePort par défaut
Postgrespostgres:18(interne)
APIghcr.io/robbeverhelst/routess-api3000
Webghcr.io/robbeverhelst/routess-web8080
Docsghcr.io/robbeverhelst/routess-docs3002

Change les ports hôtes via WEB_PORT, API_PORT, DOCS_PORT dans .env.

Figer une version

Le tag par défaut est latest. Pour la production, fige une release précise :

ROUTESS_TAG=1.122.7 docker compose -f docker/compose.selfhost.yaml --project-directory . up -d

Ou définis ROUTESS_TAG dans .env. Voir la page des releases pour les tags disponibles.

Variables d'environnement

Le fichier .env dans docker/.env.selfhost.example fait foi. Les variables que tu manipuleras le plus souvent :

VariableRequiseDéfautObjectif
JWT_SECREToui-Signe les tokens de session et d'API. La rotation déconnecte tout le monde.
ANALYTICS_SALToui-Hache les ID utilisateurs dans les événements d'analytics. La rotation réinitialise les pseudonymes d'analytics.
PAT_PEPPERoui-Hache les personal access tokens au repos. La rotation invalide tous les PAT existants.
DB_PASSWORDoui-Mot de passe Postgres.
GOOGLE_CLIENT_ID/SECREToui-Identifiants Google OAuth.
VITE_MAPBOX_ACCESS_TOKENoui-Token d'accès Mapbox utilisé par l'application web.
PUBLIC_WEB_URLnonhttp://localhost:8080Où les utilisateurs ouvrent l'app. Utilisé comme base de redirection OAuth.
PUBLIC_API_URLnonhttp://localhost:3000Où l'application web atteint l'API.
ADMIN_EMAILSnonvideE-mails (séparés par des virgules) auxquels le rôle admin est accordé à la connexion. Vide désactive le panneau d'administration.
RESEND_API_KEYnonvideClé d'API Resend. Vide se rabat sur l'écriture des URL de vérification sur stdout.
EMAIL_FROMnonroutess <[email protected]>Adresse d'expéditeur utilisée par Resend.
VALHALLA_URLouivideURL de base d'une instance Valhalla auto-hébergée pour le routage et l'analyse de surface. Vide, les endpoints de routage renvoient 503.
VITE_UMAMI_URL / _WEBSITE_IDnonvideEndpoint et site ID Umami pour l'application web. Vide désactive l'analytics produit.
UMAMI_URL / _WEBSITE_IDnonvideMêmes endpoint et site ID Umami pour le site de documentation (Next les lit côté serveur).
VITE_SENTRY_DSNnonvideDSN Sentry / GlitchTip pour le reporting d'erreurs du navigateur.
VITE_SENTRY_ENVIRONMENTnonproductionTag d'environnement attaché aux rapports d'erreurs du navigateur.
PUBLIC_DOCS_URLnonhttp://localhost:3002Origine canonique du site de documentation, utilisée dans ses liens sitemap, robots.txt et llms.txt.

Variables avancées

L'API comprend plus de réglages que ce que le fichier compose transmet. Pour en utiliser un, ajoute-le sous le service api dans environment dans docker/compose.selfhost.yaml (ou ton propre fichier de surcharge) :

VariableDéfautObjectif
LOG_LEVELinfoNiveau de log Pino pour l'API (debug, info, warn, error).
SESSION_TTL_DAYS7Combien de temps une session de navigateur reste valide.
SESSION_COOKIE_NAMEroutess_sessionNom du cookie de session HTTP-only.
JWT_EXPIRES_IN7dDurée de vie du token JWT.
FRONTEND_URLSvideListe d'origines web autorisées, séparées par des virgules ou des retours à la ligne ; surcharge FRONTEND_URL quand elle est définie.
SWAGGER_ENABLEDfalse en prodSert la doc API interactive sur SWAGGER_PATH.
SWAGGER_PATH/apiChemin de l'UI Swagger quand elle est activée.
TELEMETRY_ENABLEDtrueInterrupteur principal pour OpenTelemetry (métriques + traces).
METRICS_ENABLEDtrueMétriques Prometheus sur /metrics sur le port de l'API. Renvoie 503 quand désactivé.
OTEL_EXPORTER_OTLP_ENDPOINTvideURL de base du collecteur OTLP pour les traces (/v1/traces est ajouté). Vide désactive l'export de traces.
OTEL_EXPORTER_OTLP_HEADERSvideEn-têtes OTLP supplémentaires sous forme d'objet JSON, par ex. {"authorization":"Bearer …"}.
GRAFANA_URLSvideObjet JSON de liens de dashboards affichés dans le panneau d'administration : {"apiOverview":"…","apiLatency":"…","runtime":"…"}.

Pour le conteneur web :

VariableDéfautObjectif
VITE_SENTRY_TRACES_SAMPLE_RATE0.1Fraction des sessions de navigateur tracées quand Sentry est activé.
VITE_SENTRY_DEBUGfalseLogging verbeux du SDK Sentry.

Le logging de la console du navigateur est par défaut à warn. Pour déboguer un seul navigateur, mets localStorage["routess:log-level"] à debug, info, warn, error ou none et recharge.

Paiement (produit hébergé uniquement)

Routess.com vend un pass Pro annuel (ADR 0039). Une instance auto-hébergée laisse le paiement désactivé, c'est le défaut : toutes les fonctionnalités restent débloquées, tout le monde a droit à GENERATION_QUOTA_PER_DAY routes générées par jour, et aucun prestataire de paiement n'est contacté. Laisse BILLING_ENABLED=false, ou ne le définis pas.

Pour référence, voici les variables que définit le produit hébergé. Avec BILLING_ENABLED=true, l'API refuse de démarrer tant que le moment du lancement et les trois valeurs Stripe ne sont pas définis.

VariableDéfautRôle
BILLING_ENABLEDfalseActive le pass Pro, le paywall et le quota de génération par niveau.
BILLING_PROVIDERstripePrestataire de paiement. Seul stripe est implémenté.
BILLING_LAUNCHED_ATvideHorodatage ISO du lancement. Les comptes créés avant reçoivent 3 mois de Pro à leur prochaine connexion.
STRIPE_SECRET_KEYvideClé secrète Stripe (sk_live_… ou une clé restreinte rk_live_…).
STRIPE_WEBHOOK_SECRETvideSecret de signature (whsec_…) du endpoint webhook <api>/api/v1/billing/webhook.
STRIPE_PRICE_PRO_YEAR_PASSvideIdentifiant de Price Stripe du pass Pro annuel (paiement unique).
GENERATION_QUOTA_PER_DAY_ANONYMOUS1Routes générées par jour pour les visiteurs non connectés (par IP) quand le paiement est actif. 0 supprime la limite.
GENERATION_QUOTA_PER_DAY_FREE3Pareil pour les utilisateurs connectés du plan gratuit.
GENERATION_QUOTA_PER_DAY_PRO50Pareil pour les utilisateurs Pro.

Le mettre derrière un reverse proxy

Le compose par défaut expose les ports directement. Pour le TLS et un vrai domaine, place les services web et api derrière un reverse proxy (Caddy, Traefik, ingress-nginx, Cloudflare Tunnel) et surcharge les URL publiques dans .env :

PUBLIC_WEB_URL=https://routess.example.com
PUBLIC_API_URL=https://api.routess.example.com

PUBLIC_WEB_URL est aussi utilisé comme base de redirection OAuth, il doit donc correspondre à ce que tu as configuré dans Google Cloud.

Mettre à jour

Fais d'abord une sauvegarde de la base de données (voir ci-dessous) ; les migrations sont uniquement en avant, donc un snapshot est ton chemin de rollback. Ensuite :

docker compose -f docker/compose.selfhost.yaml --project-directory . pull
docker compose -f docker/compose.selfhost.yaml --project-directory . up -d

L'API exécute les migrations automatiquement au démarrage. Il n'y a pas d'étape de migration manuelle. Pour revenir en arrière, restaure le dump d'avant mise à jour et fige ROUTESS_TAG sur la release précédente.

Sauvegarder

Les données Postgres vivent dans le volume nommé postgres_data. Un pg_dump standard fonctionne :

docker compose -f docker/compose.selfhost.yaml --project-directory . exec postgres \
  pg_dump -U routess routess > routess-$(date +%F).sql

Restaure dans un volume frais avec psql :

docker compose -f docker/compose.selfhost.yaml --project-directory . exec -T postgres \
  psql -U routess routess < routess-2026-06-04.sql

Dépannage

  • L'API est-elle en bonne santé ? curl http://localhost:3000/health/ready renvoie 200 quand l'API peut atteindre la base de données ; /health/live vérifie seulement que le processus est actif.
  • « address already in use » sur :8080 ou :3000 : change WEB_PORT / API_PORT dans .env.
  • La connexion Google renvoie redirect_uri_mismatch : l'URI de redirection autorisée du client OAuth doit correspondre exactement à <PUBLIC_WEB_URL>/auth/callback.
  • Les tuiles de carte ne se chargent pas : vérifie que VITE_MAPBOX_ACCESS_TOKEN est défini ; regarde les devtools du navigateur pour des 401 venant de api.mapbox.com.
  • Les e-mails de vérification n'arrivent pas : définis RESEND_API_KEY et EMAIL_FROM. Sans eux, l'API écrit l'URL de vérification sur stdout ; lance docker compose logs api | grep '\[email:console\]'.

On this page