1. Principe Fondamental : Deux Niveaux

Le système repose sur une séparation claire entre l’orchestration et les applications :

  1. sever-admin (ce repo) — le chef d’orchestre : playbooks Ansible + stack d’infrastructure partagée (broker, monitoring, admin UIs)

  2. Les repos applicatifs — chaque application vit dans son propre repo avec son propre docker-compose.yml ; Ansible les clone/pull et pilote leur cycle de vie

                    Poste de dev (make deploy/backup/restore)
                                    │  Ansible over SSH
                                    ▼
        ┌──────────────────────────────────────────────────────────┐
        │        AWS Lightsail — Debian — 18.158.207.98            │
        │        user: admin — tous les repos dans /home/admin/app │
        │                                                          │
        │  /home/admin/app/                                        │
        │  ├── sever-admin/          ← ce repo (orchestration +    │
        │  │                            stack infra partagée)      │
        │  ├── clarajob_sa/          ← repo appli ClaraJob         │
        │  │     └── docker-compose.yml (à la racine)              │
        │  ├── marketisia/           ← repo appli PredictX         │
        │  │     └── docker/docker-compose.yml                     │
        │  ├── auth-server/          ← repo Keycloak + sa DB       │
        │  │     └── docker-compose.yml                            │
        │  └── main-server-proxy/    ← repo Traefik                │
        │        └── docker-compose.yml                            │
        │                                                          │
        │  Tous les containers partagent le réseau Docker externe  │
        │  ─────────────  proxy_server_network  ─────────────────  │
        └──────────────────────────────────────────────────────────┘

2. Les 5 Repos Git

Repo URL Git Compose Chemin serveur

sever-admin

git@gitlab.com:app81724/sever-admin.git

docker-compose.yml (racine, via include:)

/home/admin/app/sever-admin

clarajob_sa

git@gitlab.com:app81724/clarajob_sa.git

docker-compose.yml (racine)

/home/admin/app/clarajob_sa

marketisia (PredictX)

git@gitlab.com:app81724/marketisia.git

docker/docker-compose.yml

/home/admin/app/marketisia

auth-server

git@gitlab.com:app81724/auth-server.git

docker-compose.yml

/home/admin/app/auth-server

main-server-proxy

git@gitlab.com:app81724/proxy/main-server-proxy.git

docker-compose.yml

/home/admin/app/main-server-proxy

3. Stack sever-admin (infrastructure partagée)

Le docker-compose.yml racine de sever-admin ne définit aucun service directement — il fusionne 7 fichiers via la directive include: (un seul projet Compose, donc docker compose up -d <service> marche pour n’importe quel service) :

Fichier Services (nom container) Rôle

docker-compose.cache.yml

redis

Cache Redis 7 partagé (AOF, mot de passe requis, maxmemory 32mb LRU)

docker-compose.broker.yml

marketisia-kafka, marketisia-zookeeper, schema-registry, rabbitmq, marketisia-kafka-ui

Source de vérité unique de la stack messaging — consommée par hostname par les services applicatifs, jamais redéployée par eux

docker-compose.db-admin.yml

adminer, marketisia-pgadmin

UIs d’administration des bases de données

docker-compose.doc.yml

server_admin_doc

Documentation statique Nginx (sert ./build/generatedSite)

docker-compose.ansible.yml

semaphore, rundeck

UIs web pour exécuter les playbooks Ansible (Semaphore : BoltDB ; Rundeck : H2, ~1 Go RAM)

docker-compose.monitoring.yml

clarajob-dozzle, beszel-hub, beszel-agent, redisinsight

Logs Docker temps réel (Dozzle), métriques système (Beszel), UI Redis

docker-compose.observability.yml

loki, promtail, grafana

Logs centralisés : Promtail lit les logs des containers → Loki les stocke → Grafana les affiche

# Depuis /home/admin/app/sever-admin :
docker compose up -d                # tout le stack infra
docker compose up -d grafana        # un seul service
docker compose -f docker-compose.observability.yml up -d   # un seul groupe

4. Stacks Applicatifs

4.1. clarajob_sa (docker-compose.yml à la racine)

Services définis dans le compose du repo clarajob_sa :

  • clarajob-ddl — PostgreSQL (migrations dans le sous-dossier clarajob-ddl/)

  • clarajob-mongo — MongoDB

  • clarajob-mongoku — UI web MongoDB (Mongoku)

  • clarajob-redis — Redis applicatif ClaraJob

  • minio-service — Object storage S3 (MinIO)

  • minio-backup — sidecar mc mirror qui sauvegarde MinIO vers clarajob_sa/backups/minio/

  • clarajob-front-api — API Spring Boot (image GitLab Registry)

  • clarajob-front-gui — Frontend Vue.js servi par Nginx (le compose monte clarajob-front-gui/dist)

  • swagger-ui, redoc, rapidoc — documentation API

  • Cible Ansible supplémentaire : clarajob-embedding (FastAPI, image GitLab)

4.2. marketisia / PredictX (docker/docker-compose.yml)

  • marketisia-ddl — PostgreSQL

  • marketisia-redis — Redis

  • marketisia-front-api — API Spring Boot (image GitLab)

  • marketisia-front-gui — Frontend Vue.js (image GitLab)

  • Consomme Kafka/RabbitMQ du broker partagé sever-admin par hostname (marketisia-kafka:29092)

4.3. auth-server

  • auth_server_db — PostgreSQL pour Keycloak

  • keycloak — IAM (authentification ClaraJob & co)

4.4. documentation

  • documentation — site statique AsciiDoc servi par nginx:latest (le compose monte build/generatedSite, pré-généré en local par gradle asciidoctor et versionné dans le repo — aucune image Docker custom, aucun build au deploy). Accessible via documentation.clarajob.com / .marketisia.com / .pretydate.com (un seul router Traefik documentation, 3 hosts dans la rule)

4.5. main-server-proxy

  • traefik-service — reverse proxy Traefik : point d’entrée HTTPS de tous les domaines (adminer.clarajob.com, beszel.marketisia.com, etc. via labels Traefik sur les containers)

5. Couche Orchestration (Ansible)

sever-admin/
├── Makefile                  # 6 cibles : help, ping, backup, restore, deploy, setup-cron
├── Jenkinsfile               # Pipeline CI/CD (backup pre-deploy + deploy)
├── .vault_password           # (racine, non versionné en clair) — copié sur le serveur par setup-cron
└── ansible/
    ├── ansible.cfg           # inventory, vault_password_file=~/.vault_sever_admin,
    │                         # roles_path=roles, host_key_checking=False, pipelining
    ├── inventory/
    │   ├── hosts.yml         # production: vps-main (18.158.207.98, user admin)
    │   │                     # local: localhost (ansible_connection: local)
    │   └── group_vars/
    │       ├── all/
    │       │   ├── vars.yml  # variables publiques (chemins, services, URLs git)
    │       │   └── vault.yml # 🔐 secrets chiffrés (credentials DB, token registry)
    │       └── local/
    │           └── vars.yml  # surcharges pour ENV=local
    ├── playbooks/
    │   ├── deploy.yml        # 19 cibles — validation + backups pre-deploy + déploiement
    │   ├── backup.yml        # 4 bases + all
    │   ├── restore.yml       # 4 bases + minio-service
    │   └── setup-cron.yml    # crons de backup sur le serveur
    └── roles/
        ├── deploy/           # git pull → stop → docker login → pull(si TAG) → up -d
        │                     # → pause 10s → vérif container → rescue/rollback
        ├── deploy_frontend/  # git pull → build dans un container jetable (build_image/
        │                     # build_command, défaut npm ci && npm run build sur node)
        │                     # OU pull image si TAG → restart nginx → vérif → rollback
        ├── backup/           # pg_dump / mongodump / mysqldump dans le container
        │                     # → vérif dump non vide → fichier description
        ├── restore/          # psql / mongorestore --drop / mysql depuis le dump
        └── restore_minio/    # mc mirror backup → volume, avec arrêt/redémarrage MinIO

6. Flux Réels

6.1. Flux 1 : Déploiement d’un stack complet (make deploy APP=clarajob-sa)

make deploy APP=clarajob-sa [TAG=v1.2.0] [BRANCH=develop]
  │
  ▼ ansible-playbook playbooks/deploy.yml (vault auto via ansible.cfg)
  │
  ├─ pre_tasks
  │   ├─ assert : APP ∈ liste des 19 cibles
  │   ├─ si container clarajob-ddl tourne  → backup pre-deploy PostgreSQL ("pre-deploy")
  │   └─ si container clarajob-mongo tourne → backup pre-deploy MongoDB ("pre-deploy")
  │
  ├─ block (déploiement)
  │   ├─ git clone (si absent) ou clean -fd + pull (branche main par défaut)
  │   │    clé SSH serveur : /home/admin/.ssh/id_ed25519
  │   ├─ docker login registry.gitlab.com (deploy token vault)
  │   ├─ IMAGE_TAG=<tag> docker compose pull clarajob-ddl clarajob-front-api
  │   │                                      clarajob-front-gui clarajob-embedding
  │   ├─ IMAGE_TAG=<tag> docker compose up -d      (tout le stack)
  │   ├─ pause 15s
  │   └─ docker ps → liste des containers actifs affichée
  │
  └─ rescue (si échec)
      ├─ docker compose up -d   (rollback : relance le stack)
      └─ fail avec message explicite

6.2. Flux 2 : Backup automatique quotidien (cron installé par make setup-cron)

03:00  backup-marketisia-sa-daily  → pg_dump marketisia-ddl
04:00  backup-clarajob-ddl-daily   → pg_dump clarajob-ddl
05:00  backup-clarajob-mongo-daily → mongodump clarajob-mongo
  │
  │  (exécutés PAR le serveur lui-même : ansible-playbook local,
  │   vault: /opt/.vault_password, logs: /var/log/ansible-backup.log)
  ▼
/home/admin/app/sever-admin/db-config/dump/<service>/<service>-YYYY-MM-DD_HHMMSS.{sql|archive}
/home/admin/app/sever-admin/db-config/dump_description/<service>/..._auto-backup.txt

6.3. Flux 3 : Restauration (make restore APP=clarajob-mongo DUMP=…​)

make restore APP=clarajob-mongo DUMP=clarajob-mongo-2026-07-26_050000.archive
  │
  ├─ vérifie que le container tourne
  ├─ vérifie que db-config/dump/clarajob-mongo/<DUMP> existe (échec sinon)
  └─ docker exec -i clarajob-mongo mongorestore --drop --archive < dump
       (--drop : écrase les collections existantes)

6.4. Flux 4 : CI/CD Jenkins

Jenkins (déclenchement manuel ou webhook GitLab)
  │  paramètres : TARGET_APP ∈ {clarajob-sa, marketisia-sa}, SKIP_BACKUP (bool)
  ├─ stage Checkout
  ├─ stage Backup pre-deploy   (sauf si SKIP_BACKUP)
  │    → ansible-playbook playbooks/backup.yml -e target_app=$TARGET_APP
  └─ stage Deploy
       → ansible-playbook playbooks/deploy.yml -e target_app=$TARGET_APP
  (credential Jenkins "VAULT_PASSWORD_FILE" = fichier secret vault)

7. Modèle de Sécurité

Poste de dev
 ├─ ~/.ssh/serverAdminSSHKeypair.pem    → SSH vers admin@18.158.207.98
 └─ ~/.vault_sever_admin                → déchiffre inventory/group_vars/all/vault.yml

Serveur
 ├─ /home/admin/.ssh/id_ed25519         → le serveur pull les repos GitLab (deploy Ansible)
 ├─ /opt/.vault_password                → utilisé par les crons de backup (root, 600)
 └─ Secrets injectés aux containers via variables d'environnement compose

Vault (vault.yml) contient :
 vault_marketisia_sa_db_{name,user,pass}
 vault_clarajob_ddl_db_{name,user,pass}
 vault_clarajob_mongo_db_{name,user,pass}
 vault_auth_server_db_{name,user,pass}
 vault_gitlab_registry_token             (deploy token read-only registry.gitlab.com)

Registry : registry.gitlab.com, utilisateur group_registry_deploy_token.

8. Ports Exposés (réels)

8.1. Infrastructure sever-admin

Service Container Port hôte → container Variable

Documentation

server_admin_doc

8050 → 80

DOCPORT

Adminer

adminer

9093 → 8080

—

pgAdmin

marketisia-pgadmin

5050 → 80

PGADMIN_PORT

Semaphore

semaphore

3001 → 3000

SEMAPHORE_PORT

Rundeck

rundeck

4440 → 4440

RUNDECK_PORT

Dozzle

clarajob-dozzle

9999 → 8080

DOZZLE_PORT

Beszel Hub

beszel-hub

8090 → 8090

—

Beszel Agent

beszel-agent

host network (45876)

BESZEL_AGENT_KEY

Grafana

grafana

3000 → 3000

GRAFANA_PORT

Loki

loki

interne (3100)

—

Promtail

promtail

interne

—

Redis

redis

6379 → 6379

REDIS_PORT

RedisInsight

redisinsight

5540 → 5540

—

8.2. Broker messaging partagé

Service Container Port hôte → container Variable

Kafka

marketisia-kafka

9092, 29092

KAFKA_PORT

Zookeeper

marketisia-zookeeper

interne (2181)

—

Schema Registry

schema-registry

8081 → 8081

SCHEMA_REGISTRY_PORT

RabbitMQ (AMQP)

rabbitmq

5672 → 5672

RABBITMQ_PORT

RabbitMQ Management

rabbitmq

15672 → 15672

RABBITMQ_UI_PORT

Kafka UI

marketisia-kafka-ui

8091 → 8080

KAFKA_UI_PORT

Le port 8090 est réservé à Beszel — c’est pourquoi Kafka UI est sur 8091. L’accès public passe par Traefik (HTTPS + règles Host() par labels : ex. adminer.clarajob.com, beszel.marketisia.com).

9. Points Clés à Retenir

  1. sever-admin n’héberge pas les applications — il les orchestre. Chaque appli a son compose dans son repo.

  2. Le réseau proxy_server_network (externe) relie tout : les applis consomment Kafka, Redis, les DBs par hostname de container.

  3. Le broker (Kafka/RabbitMQ) appartient à sever-admin — les applis ne le redéploient jamais.

  4. Chaque déploiement de DB fait un backup pre-deploy automatique si le container tourne.

  5. Tous les déploiements ont un rollback automatique (block/rescue Ansible) : en cas d’échec, le service est relancé et le playbook échoue avec un message explicite.

  6. Deux modes d’exécution : ENV=remote (production) et ENV=local (ta machine), même code.