Un stack DevOps minimal pour standardiser le provisioning et la configuration de base des serveurs Linux (Debian et RHEL).
- Vue d'ensemble
- Prérequis
- Structure du projet
- Démarrage rapide — Semaphore UI
- Variables de configuration
- Playbooks disponibles
- Lancement CLI (optionnel)
- Ajouter un serveur cible
- CI / Linting
Ce projet fournit une base Ansible réutilisable pour configurer des serveurs Linux de façon répétable et cohérente, pilotable via une interface web Semaphore UI.
L'architecture repose sur trois composants principaux :
| Composant | Rôle |
|---|---|
| Gitea | Dépôt Git interne — héberge les sources Ansible |
| Semaphore UI | Interface web — déclenche les playbooks depuis Gitea |
| debian-client | Serveur Debian cible — appliqué par Ansible |
Semaphore clone les playbooks directement depuis Gitea à chaque exécution. Modifier les sources dans Gitea suffit pour que la prochaine exécution prenne en compte les changements.
Ce que le rôle baseline_common applique :
| Opération | Détail |
|---|---|
| Packages communs | vim, curl, git, unzip |
| Fuseau horaire | Europe/Paris par défaut |
| Utilisateurs admin | Optionnel, via variable |
| SSH — root login | Désactivé |
| SSH — authentification | Par clé uniquement (mot de passe désactivé) |
- Docker
- Docker Compose v2
docker --version
docker compose versionminimal-linux-ops-stack/
│
├── ansible/
│ ├── group_vars/
│ │ └── all.yml # Variables globales (surcharge les defaults du rôle)
│ ├── inventories/
│ │ ├── dev/hosts.yml # Inventaire de développement (container demo)
│ │ └── prod/hosts.yml # Inventaire de production (à compléter)
│ ├── playbooks/
│ │ ├── baseline.yml # Playbook complet (toutes les opérations)
│ │ ├── packages.yml # Packages uniquement
│ │ ├── timezone.yml # Fuseau horaire uniquement
│ │ ├── ssh-hardening.yml # Durcissement SSH uniquement
│ │ └── users.yml # Gestion des utilisateurs uniquement
│ └── roles/
│ └── baseline_common/
│ ├── defaults/main.yml # Valeurs par défaut des variables
│ ├── handlers/main.yml # Handler de rechargement SSH
│ └── tasks/main.yml # Tâches du rôle (taguées par opération)
│
├── bootstrap/
│ ├── bootstrap-gitea.py # Crée le repo et pousse les sources Ansible dans Gitea
│ ├── bootstrap-semaphore.py # Préconfiguration automatique de Semaphore
│ ├── semaphore-bootstrap-config.json # Projets, inventaires et templates à créer
│ └── requirements.txt
│
├── docker/
│ ├── gitea/
│ │ ├── Dockerfile # Image Gitea avec curl + entrypoint personnalisé
│ │ └── entrypoint.sh # Crée/reset l'admin Gitea au démarrage
│ └── debian-client/Dockerfile # Container Debian cible (SSH activé, user ansible)
│
├── ansible.cfg # Configuration Ansible locale (roles_path)
├── docker-compose.yml # Stack complète : Gitea + Semaphore + cible Debian
└── .github/workflows/lint.yml # CI : yamllint + ansible-lint
docker compose up -d --buildCette commande démarre l'ensemble des services. Le démarrage est orchestré automatiquement :
| Service | Rôle | Port |
|---|---|---|
gitea |
Dépôt Git interne | 3001 |
gitea-bootstrap |
Pousse les sources Ansible dans Gitea | — |
semaphore |
Interface web Ansible | 3000 |
semaphore-bootstrap |
Préconfigure Semaphore (projet, templates…) | — |
debian-client |
Serveur cible SSH (Debian 12) | 2223 |
Ordre de démarrage garanti :
- Gitea démarre et crée l'utilisateur admin
gitea/gitea123 gitea-bootstrapattend que Gitea soit prêt, puis pousse tous les fichiersansible/dans le repoansible-baselinesemaphore-bootstrapattend quegitea-bootstrapsoit terminé, puis configure Semaphore pour cloner depuis Gitea
Pour vérifier que tout s'est bien initialisé :
docker compose logs gitea-bootstrap
# doit afficher : Gitea bootstrap complete
docker compose logs semaphore-bootstrap
# doit afficher : Bootstrap completeSemaphore UI (pour lancer les playbooks) : http://localhost:3000
- Utilisateur :
admin/ Mot de passe :admin
Gitea (pour consulter ou modifier les sources Ansible) : http://localhost:3001
- Utilisateur :
gitea/ Mot de passe :gitea123 - Repo :
gitea/ansible-baseline
- Cliquer sur Task Templates dans le menu gauche
- Choisir le template souhaité (ex :
baseline-debian-demo) - Cliquer sur le bouton Run ▶
- Suivre l'exécution en temps réel dans les logs
| Template | Opération | Tags Ansible |
|---|---|---|
baseline-debian-demo |
Stack complète | (tous) |
packages-debian-demo |
Packages seulement | packages |
timezone-debian-demo |
Fuseau horaire seulement | timezone |
ssh-hardening-debian-demo |
Durcissement SSH | ssh |
users-debian-demo |
Utilisateurs admin | users |
Semaphore affiche la sortie Ansible complète. Les statuts possibles pour chaque tâche :
| Statut | Signification |
|---|---|
ok |
L'état est déjà conforme, aucun changement appliqué |
changed |
Une modification a été effectuée sur le serveur |
skipped |
La tâche ne s'applique pas (condition when non remplie) |
failed |
Erreur — l'exécution s'arrête |
Le Dashboard conserve l'historique complet des tâches avec leur statut et leurs logs.
Les sources Ansible sont hébergées dans Gitea. Pour les modifier :
- Éditer les fichiers dans
ansible/localement - Pousser dans Gitea via l'interface web http://localhost:3001 ou en relançant
gitea-bootstrap:docker compose up gitea-bootstrap
- La prochaine exécution dans Semaphore récupérera automatiquement les changements via
git clone
# Arrêter
docker compose down
# Redémarrer (toutes les données sont persistées dans des volumes Docker)
docker compose up -dLes données Gitea (
gitea_data), les credentials et templates Semaphore (semaphore_data) survivent aux redémarrages. La cléSEMAPHORE_ENCRYPTION_KEYdansdocker-compose.ymlgarantit que les credentials Semaphore restent déchiffrables après redémarrage.
Les variables ont des valeurs par défaut dans ansible/roles/baseline_common/defaults/main.yml. Elles peuvent être surchargées dans ansible/group_vars/all.yml.
| Variable | Valeur par défaut | Description |
|---|---|---|
linux_baseline_timezone |
Europe/Paris |
Fuseau horaire |
linux_baseline_common_packages |
[vim, curl, git, unzip] |
Packages à installer |
linux_baseline_admin_users |
[] |
Utilisateurs admin à créer |
linux_baseline_ssh_permit_root_login |
no |
Autoriser root SSH |
linux_baseline_ssh_password_authentication |
no |
Autoriser auth par mot de passe |
Dans ansible/group_vars/all.yml :
linux_baseline_admin_users:
- name: deploy
groups: sudo
shell: /bin/bashPuis relancer le template users-debian-demo dans Semaphore.
Chaque playbook applique le rôle baseline_common avec un tag spécifique :
| Fichier | Tag | Opération |
|---|---|---|
playbooks/baseline.yml |
(tous) | Configuration complète |
playbooks/packages.yml |
packages |
Installer les packages |
playbooks/timezone.yml |
timezone |
Configurer le fuseau horaire |
playbooks/ssh-hardening.yml |
ssh |
Durcir la configuration SSH |
playbooks/users.yml |
users |
Créer les utilisateurs admin |
Il est possible d'exécuter les playbooks directement depuis le terminal, sans interface graphique.
pip install ansible
sudo apt-get install sshpass # Debian/Ubuntudocker compose up -d debian-clientDepuis la racine du projet :
ansible-playbook -i ansible/inventories/dev/hosts.yml ansible/playbooks/baseline.ymlNote — GitHub Codespaces / répertoires world-writable
Si Ansible ignore
ansible.cfg(répertoire en écriture globale), forcer le chemin :ANSIBLE_CONFIG=$(pwd)/ansible.cfg ansible-playbook \ -i ansible/inventories/dev/hosts.yml \ ansible/playbooks/baseline.yml
Éditer ansible/inventories/prod/hosts.yml :
all:
hosts:
mon-serveur:
ansible_host: 192.168.1.10
ansible_port: 22
ansible_user: ubuntu
ansible_ssh_private_key_file: ~/.ssh/id_rsa
ansible_become: truePour l'intégrer dans Semaphore, mettre à jour bootstrap/semaphore-bootstrap-config.json
avec le nouvel inventaire et relancer le bootstrap :
docker compose up semaphore-bootstrapLe dépôt inclut un workflow GitHub Actions qui valide la syntaxe à chaque push :
# Lancer manuellement
yamllint .
ansible-lint ansible/playbooks/baseline.ymlWorkflow : .github/workflows/lint.yml
MIT