Skip to main content

suitenumerique/calendars

https://github.com/suitenumerique/calendars

Stack de développement auto-hébergé sur Debian, exposé en HTTPS via Nginx Proxy Manager.

Domaines à adapter :

  • cal.domain.tld → frontend (port 8930)
  • cal-api.domain.tld → backend API (port 8931)
  • cal-auth.domain.tld → Keycloak (port 8935)

Prérequis

Docker et plugins

docker --version          # v20+ minimum
docker compose version    # doit afficher v2.x
docker buildx version     # doit répondre

Si docker compose ou docker buildx ne répondent pas :

sudo apt install docker-compose-plugin docker-buildx-plugin

Activer BuildKit

Sans BuildKit, le build du backend échoue. Édite /etc/docker/daemon.json :

sudo nano /etc/docker/daemon.json

Contenu (adapte data-root si nécessaire) :

{
  "data-root": "/var/lib/docker",
  "features": {
    "buildkit": true
  }
}

Redémarre Docker :

sudo systemctl restart docker

Vérifie que BuildKit est actif :

docker buildx version

Git

sudo apt install git

Étape 1 : Cloner le repo

cd /chemin/vers/ton/dossier
git clone https://github.com/suitenumerique/calendars.git
cd calendars

Étape 2 : Créer les dossiers de données

mkdir -p data/media data/static

Étape 3 : Créer les fichiers .local

Ces fichiers doivent exister car le compose.yaml les référence.

for service in postgresql keycloak backend frontend caldav; do
  echo "# local overrides" > env.d/development/${service}.local
done

Étape 4 : Configurer les variables d'environnement

env.d/development/frontend.defaults

Remplace la ligne NEXT_PUBLIC_API_ORIGIN :

NEXT_PUBLIC_API_ORIGIN=https://cal-api.domain.tld

env.d/development/backend.defaults

Remplace toutes les occurrences de localhost par les bons domaines :

OIDC_OP_AUTHORIZATION_ENDPOINT=https://cal-auth.domain.tld/realms/calendars/protocol/openid-connect/auth
LOGIN_REDIRECT_URL=https://cal.domain.tld
LOGIN_REDIRECT_URL_FAILURE=https://cal.domain.tld
LOGOUT_REDIRECT_URL=https://cal.domain.tld
OIDC_REDIRECT_ALLOWED_HOSTS="https://cal.domain.tld,https://cal-api.domain.tld"
OIDC_OP_URL=https://cal-auth.domain.tld/realms/calendars

env.d/development/backend.local

# local overrides
DJANGO_SECURE_PROXY_SSL_HEADER=HTTP_X_FORWARDED_PROTO,https
USE_X_FORWARDED_HOST=True

src/backend/calendars/settings.py — fix CORS

La classe Base utilise values.BooleanValue qui empêche Development d'écraser correctement CORS_ALLOW_ALL_ORIGINS. Fixe-le avec sed :

sed -i 's/CORS_ALLOW_ALL_ORIGINS = values.BooleanValue(False)/CORS_ALLOW_ALL_ORIGINS = False/' src/backend/calendars/settings.py

Vérifie :

grep -n "CORS_ALLOW_ALL_ORIGINS" src/backend/calendars/settings.py
# doit afficher deux lignes : une à False (Base) et une à True (Development)

Si la classe Development n'a pas CORS_ALLOW_ALL_ORIGINS = True, ajoute-le manuellement :

nano src/backend/calendars/settings.py

Cherche class Development(Base): et ajoute :

ALLOWED_HOSTS = ["*"]
CORS_ALLOW_ALL_ORIGINS = True
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
CSRF_TRUSTED_ORIGINS = [
    "https://cal.domain.tld",
    "https://cal-api.domain.tld",
]

compose.yaml

Dans la section keycloak, change le --hostname :

      - --hostname=https://cal-auth.domain.tld

Étape 5 : Créer le réseau Docker externe

docker network create lasuite-network

Si le réseau existe déjà, l'erreur "already exists" est normale.


Étape 6 : Fixer les permissions

chown -R DOCKER_UID:DOCKER_GID src/frontend/

Remplace DOCKER_UID:DOCKER_GID par ton user/group Docker (ex: 998:100).


Étape 7 : Build des images

DOCKER_USER=UID:GID docker compose build

C'est long (10-20 min).


Étape 8 : Migrations Django

DOCKER_USER=UID:GID docker compose up -d postgresql
# Attends 5 secondes, puis :
DOCKER_USER=UID:GID docker compose run --rm backend-dev python manage.py migrate

Étape 9 : Init de la base CalDAV

DOCKER_USER=UID:GID docker compose run --rm caldav /usr/local/bin/init-database.sh

Étape 10 : Démarrage complet

DOCKER_USER=UID:GID docker compose up -d backend-dev worker-dev frontend-dev keycloak

Vérifie que tout tourne :

docker compose ps

Tu dois voir ces containers en état running : postgresql, redis, mailcatcher, caldav, keycloak, worker-dev, backend-dev, frontend-dev.


Étape 11 : Configurer Nginx Proxy Manager

Crée 3 proxy hosts :

Domaine Forward vers Port
cal.domain.tld 192.168.x.x 8930
cal-api.domain.tld 192.168.x.x 8931
cal-auth.domain.tld 192.168.x.x 8935

Active SSL (Let's Encrypt) sur les 3.

Sur cal-api.domain.tld uniquement, active Websockets Support et dans l'onglet Advanced ajoute :

proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;

Sur cal.domain.tld, active Websockets Support (requis pour le hot reload Next.js).


Étape 12 : Configurer Keycloak

Accède à https://cal-auth.domain.tld — login admin : admin / admin

Important : switche vers le realm calendars-realm via le menu déroulant en haut à gauche. Ne reste pas sur master.

Va dans Clients > calendars > onglet Settings, section Access settings :

Valid redirect URIs :

https://cal.domain.tld/*
https://cal-api.domain.tld/*
http://192.168.x.x:8932/*
http://192.168.x.x:8933/*

Valid post logout redirect URIs :

https://cal.domain.tld/*
https://cal-api.domain.tld/*

Web origins :

https://cal.domain.tld
https://cal-api.domain.tld
http://192.168.x.x:8932
http://192.168.x.x:8933

Clique Save.


Étape 13 : Créer le superuser Django

DOCKER_USER=UID:GID docker compose run --rm backend-dev python manage.py shell -c "
from core.models import User, Organization
org, _ = Organization.objects.get_or_create(name='Admin', defaults={'external_id': 'admin'})
user = User.objects.create_superuser(email='admin@example.com', password='admin', organization=org)
print('Superuser created')
"

Accès

Service URL
App https://cal.domain.tld
Backend API https://cal-api.domain.tld
Keycloak admin https://cal-auth.domain.tld
Django admin https://cal-api.domain.tld/admin
CalDAV http://192.168.x.x:8932
Mailcatcher http://192.168.x.x:8937

Login app par défaut : calendars / calendars Login Django admin : admin@example.com / admin


Commandes utiles

Arrêter :

docker compose stop

Redémarrer :

DOCKER_USER=UID:GID docker compose up -d backend-dev worker-dev frontend-dev keycloak

Logs :

docker compose logs -f
docker compose logs -f backend-dev
docker compose logs -f frontend-dev

Après un git pull :

DOCKER_USER=UID:GID docker compose build
DOCKER_USER=UID:GID docker compose run --rm backend-dev python manage.py migrate
DOCKER_USER=UID:GID docker compose up --force-recreate -d backend-dev worker-dev frontend-dev keycloak

Reset complet :

docker compose down
rm -rf data/postgresql.*