deploy.sh only synced the permission catalog; the system roles (admin, user) were never seeded, leaving the admin Roles page empty after a fresh deploy. Add app:seed-rbac (idempotent) to the deploy script, refresh the embedded script in deployment-docker.md, document the RBAC post-deploy step (with the manual fix for an already-deployed prod), and note it in CLAUDE.md.
10 KiB
Deploiement Docker — Lesstime
Pre-requis
Docker
# Ubuntu
sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker $USER
Se deconnecter/reconnecter pour que le groupe docker prenne effet.
Nginx
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
PostgreSQL
PostgreSQL tourne dans un conteneur Docker separe (voir le repo infra-postgres).
Il doit etre installe et accessible avant de deployer Lesstime.
Creer la base de donnees pour Lesstime :
cd /var/www/postgres
docker compose exec postgres psql -U admin
-- Si le user n'existe pas encore
CREATE USER malio WITH PASSWORD 'motdepasse';
-- Creer la base
CREATE DATABASE lesstime_prod OWNER malio;
\q
Premiere installation (nouvelle machine)
Guide complet pour mettre en ligne Lesstime sur une machine vierge. Inclut les pre-requis, la BDD et l'app.
1. Installer les pre-requis
Installer Docker, Nginx et PostgreSQL (voir section Pre-requis ci-dessus).
2. Creer le dossier de deploiement
sudo mkdir -p /var/www/lesstime
sudo chown -R $(whoami):$(whoami) /var/www/lesstime
cd /var/www/lesstime
3. Se connecter au registry Docker de Gitea
docker login gitea.malio.fr
- Username : le nom d'utilisateur du compte organisation Gitea
MALIO - Password : le token REGISTRY_TOKEN dispo dans le bitwarden
Le login est sauvegarde dans ~/.docker/config.json, pas besoin de le refaire a chaque deploiement.
4. Creer les fichiers de deploiement
Creer docker-compose.yml :
services:
app:
image: gitea.malio.fr/malio-dev/lesstime:${LESSTIME_IMAGE_TAG:-latest}
container_name: lesstime-app
env_file: .env
ports:
- "8080:80"
volumes:
- ./config/jwt:/var/www/html/config/jwt:ro
- ./uploads:/var/www/html/var/uploads
extra_hosts:
- "host.docker.internal:host-gateway"
restart: unless-stopped
Creer deploy.sh :
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")"
TAG="${1:-latest}"
export LESSTIME_IMAGE_TAG="$TAG"
echo "==> Deploying lesstime:${TAG}..."
echo "==> Enabling maintenance mode..."
touch maintenance.on
echo "==> Pulling image..."
sudo docker compose pull
echo "==> Starting container..."
sudo docker compose up -d
echo "==> Waiting for container to be ready..."
sleep 3
echo "==> Extracting maintenance page..."
mkdir -p public
sudo docker compose cp app:/var/www/html/public/maintenance.html public/maintenance.html
echo "==> Running migrations..."
sudo docker compose exec -T -u www-data app php bin/console doctrine:migrations:migrate --no-interaction
echo "==> Seeding RBAC system roles (idempotent)..."
sudo docker compose exec -T -u www-data app php bin/console app:seed-rbac
echo "==> Syncing RBAC permissions catalog..."
sudo docker compose exec -T -u www-data app php bin/console app:sync-permissions
echo "==> Clearing cache..."
sudo docker compose exec -T -u www-data app php bin/console cache:clear --env=prod
sudo docker compose exec -T -u www-data app php bin/console cache:warmup --env=prod
echo "==> Disabling maintenance mode..."
rm -f maintenance.on
VERSION=$(sudo docker compose exec -T app cat config/version.yaml | grep 'app.version' | awk -F"'" '{print $2}')
echo "==> Deployed v${VERSION}"
Rendre executable :
chmod +x deploy.sh
5. Configurer l'environnement
Creer .env avec les variables suivantes :
# Symfony
APP_ENV=prod
APP_DEBUG=0
APP_SECRET=<generer avec: openssl rand -hex 32>
# Database (host.docker.internal = la machine hote, ou le PG tourne en Docker)
DATABASE_URL="postgresql://malio:password@host.docker.internal:5432/lesstime_prod?serverVersion=16&charset=utf8"
# JWT
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
JWT_PASSPHRASE=<generer avec: openssl rand -hex 32>
JWT_COOKIE_SECURE=1
JWT_COOKIE_SAMESITE=lax
JWT_TOKEN_TTL=86400
JWT_COOKIE_TTL=86400
# CORS
CORS_ALLOW_ORIGIN='^https?://project\.malio-dev\.fr$'
# App
DEFAULT_URI=https://project.malio-dev.fr
6. Generer les cles JWT
mkdir -p config/jwt
openssl genpkey -algorithm RSA -out config/jwt/private.pem -pkeyopt rsa_keygen_bits:4096
openssl rsa -pubout -in config/jwt/private.pem -out config/jwt/public.pem
Rendre les cles lisibles par le conteneur (www-data = uid 33) :
sudo chown 33:33 config/jwt/private.pem config/jwt/public.pem
sudo chmod 644 config/jwt/private.pem config/jwt/public.pem
7. Creer le dossier uploads
mkdir -p uploads
8. Configurer Nginx systeme
Creer /etc/nginx/sites-available/lesstime.conf :
server {
listen 80;
listen [::]:80;
server_name project.malio-dev.fr;
root /var/www/lesstime/public;
# Maintenance mode
if (-f /var/www/lesstime/maintenance.on) {
return 503;
}
error_page 503 @maintenance;
location @maintenance {
rewrite ^(.*)$ /maintenance.html break;
}
location = /maintenance.html {
internal;
}
location / {
proxy_pass http://127.0.0.1:8081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 55m;
}
}
Activer le site :
sudo ln -sf /etc/nginx/sites-available/lesstime.conf /etc/nginx/sites-enabled/lesstime.conf
sudo nginx -t && sudo systemctl reload nginx
9. Deployer
./deploy.sh
10. Importer les donnees (optionnel)
Si tu as un dump SQL a importer :
# Depuis ton PC, envoyer le dump vers le serveur
scp lesstime.sql user@serveur:/tmp/lesstime.sql
# Sur le serveur, vider la base puis importer
cd /var/www/postgres
docker compose exec -T postgres psql -U malio lesstime_prod -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
docker compose exec -T postgres psql -U malio lesstime_prod < /tmp/lesstime.sql
# Creer les tables manquantes (si le dump a des erreurs de syntaxe)
cd /var/www/lesstime
docker compose exec -u www-data app php bin/console doctrine:schema:update --force --env=prod
# Nettoyer
rm /tmp/lesstime.sql
Structure finale du dossier
/var/www/lesstime/
├── docker-compose.yml
├── deploy.sh
├── .env
├── config/jwt/
│ ├── private.pem
│ └── public.pem
├── public/
│ └── maintenance.html # extrait automatiquement par deploy.sh
└── uploads/
Deployer une nouvelle version
Quand l'app est deja installee, deployer une mise a jour :
cd /var/www/lesstime
./deploy.sh # deploie la derniere version (latest)
./deploy.sh v0.3.13 # deploie une version specifique
C'est tout. Le script pull l'image, redemarre le conteneur, lance les migrations, seed les roles systeme RBAC, synchronise le catalogue des permissions et vide le cache.
RBAC : roles & permissions (post-deploiement)
Le module RBAC (entites Role / Permission) repose sur des donnees qui ne sont pas
inserees par les migrations (celles-ci creent uniquement les tables). Deux commandes idempotentes
les peuplent, integrees au deploy.sh :
| Commande | Effet |
|---|---|
app:seed-rbac |
Cree les roles systeme admin (Administrateur) et user (Utilisateur). Idempotent : ne recree rien si deja present. |
app:sync-permissions |
(Re)synchronise le catalogue des permissions a partir des modules actifs. A relancer a chaque ajout de permission dans le code. |
Symptome si elles n'ont pas tourne : la page d'admin Roles affiche « Aucun role trouve ».
Correctif manuel sur une prod deja deployee (sans relancer un deploiement complet) :
cd /var/www/lesstime
sudo docker compose exec -T -u www-data app php bin/console app:seed-rbac
sudo docker compose exec -T -u www-data app php bin/console app:sync-permissions
Rollback
Image seule (pas de changement de schema BDD)
./deploy.sh v0.3.12
Avec rollback de migration
# 1. Rollback schema (pendant que la version actuelle tourne encore)
docker compose exec -T -u www-data app php bin/console doctrine:migrations:migrate prev --no-interaction
# 2. Deployer l'ancienne version
./deploy.sh v0.3.12
CI/CD
Le workflow .gitea/workflows/build-docker.yml se declenche automatiquement sur push de tag v* :
- Build l'image multi-stage
- Push vers
gitea.malio.fr/malio-dev/lesstime:<tag>et:latest
Combine avec auto-tag-develop.yml, chaque push sur develop cree automatiquement un tag → build → image disponible.
Voir les logs
cd /var/www/lesstime
docker compose logs -f # tous les logs
docker compose logs -f --tail=100 # 100 dernieres lignes
Logs Symfony :
docker compose exec app cat var/log/prod.log
Migration depuis l'ancien deploiement (bare-metal)
Si l'application tourne deja en bare metal :
- Installer Docker (voir pre-requis)
- Creer le dossier
/var/www/lesstime-docker/(ne pas ecraser l'ancien) - Copier les fichiers existants :
cp /var/www/lesstime/.env /var/www/lesstime-docker/.env cp -a /var/www/lesstime/config/jwt /var/www/lesstime-docker/config/jwt cp -a /var/www/lesstime/var/uploads /var/www/lesstime-docker/uploads - Creer
docker-compose.ymletdeploy.shdans/var/www/lesstime-docker/(voir etape 4 ci-dessus) - Editer
/var/www/lesstime-docker/.env: changerDATABASE_URLpour utiliserhost.docker.internalau lieu de127.0.0.1 - Se connecter au registry Gitea (voir etape 3 ci-dessus)
- Mettre a jour Nginx systeme avec la conf reverse proxy (voir etape 8 ci-dessus)
- Arreter l'ancien PHP-FPM :
sudo systemctl stop php8.4-fpm - Deployer :
cd /var/www/lesstime-docker && ./deploy.sh - Verifier que tout marche, puis renommer le dossier :
mv /var/www/lesstime-docker /var/www/lesstime