diff --git a/README.md b/README.md new file mode 100644 index 0000000..4d2140f --- /dev/null +++ b/README.md @@ -0,0 +1,389 @@ +# Infrastructure qpismont.fr + +Infrastructure self-hosted complète hébergée sur serveur dédié, fournissant une plateforme DevOps avec Git, CI/CD, reverse proxy, VPN et monitoring. + +**Domaine :** qpismont.fr +**Stack :** Docker Swarm +**Repository :** https://gitea.qpismont.fr/qpismont/infra + +--- + +## Vue d'ensemble + +Cette infrastructure héberge l'ensemble des services nécessaires pour le développement et le déploiement de projets personnels : + +- **Hébergement Git** avec interface web (Gitea) +- **CI/CD automatisé** pour builds et déploiements (Woodpecker) +- **Reverse proxy** avec HTTPS automatique (Caddy) +- **Accès VPN sécurisé** pour l'administration (WireGuard) +- **Monitoring** des services et ressources (Prometheus + Perses) +- **Backups automatisés** quotidiens vers serveur FTP + +--- + +## Services déployés + +### Production + +| Service | Version | Description | URL | +|---------|---------|-------------|-----| +| **Gitea** | 1.24.7 | Hébergement Git (alternative GitHub) | https://gitea.qpismont.fr | +| **Woodpecker CI** | 3.11.0 | Plateforme CI/CD (fork de Drone) | https://woodpecker.qpismont.fr | +| **Caddy** | 2-alpine | Reverse proxy + HTTPS automatique | - | +| **WireGuard** | latest | Serveur VPN pour accès distant | UDP:51820 | +| **Prometheus** | 3.7.2 | Collecte de métriques | (interne) | +| **Perses** | latest | Dashboards de monitoring | (via VPN) | +| **cAdvisor** | latest | Métriques des containers | (interne) | +| **Backup** | latest | Sauvegarde quotidienne (4h00) | (interne) | + +### Configuration + +- **Timezone** : Europe/Paris +- **OAuth** : Gitea ↔ Woodpecker intégré +- **Admin** : qpismont +- **Backup retention** : 14 jours +- **Monitoring scrape** : 10 secondes + +--- + +## Architecture + +``` + Internet + │ + ┌────────────┼────────────┐ + │ │ │ + Port 80/443 Port 443/udp Port 51820/udp + │ │ │ + ▼ ▼ ▼ + [Caddy Proxy] [HTTP/3] [WireGuard VPN] + │ │ + ┌───────────┼──────────┐ │ + │ │ │ │ + gitea:3000 woodpecker:8000 │ [Perses] + │ │ + www.qpismont.fr [Prometheus] + (désactivé) │ + [cAdvisor] + +┌──────────────────────────────────────────────────────────────┐ +│ CI/CD Pipeline │ +│ │ +│ [Gitea] ←──── OAuth ────→ [Woodpecker Server] │ +│ │ │ +│ ▼ │ +│ [Woodpecker Agent] │ +│ │ │ +│ ▼ │ +│ [Docker-in-Docker] │ +│ (build containers) │ +└──────────────────────────────────────────────────────────────┘ + +┌──────────────────────────────────────────────────────────────┐ +│ Monitoring Stack │ +│ │ +│ [Prometheus] ←─ scrape ─┬─ prometheus:9090 (self) │ +│ │ ├─ reverse_caddy:2019 (metrics) │ +│ │ └─ cadvisor:8080 (containers) │ +│ │ │ +│ └──→ [Perses] (visualisation via VPN) │ +└──────────────────────────────────────────────────────────────┘ + +┌──────────────────────────────────────────────────────────────┐ +│ Backup System │ +│ │ +│ [Backup Service] ──→ rclone/FTP ──→ [Serveur FTP distant] │ +│ │ │ │ +│ └─ Volumes Docker: └─ /backups/infra/│ +│ • giteadata Format: .tar.gz │ +│ • woodpeckerdata (désactivé) Rétention: 14j │ +│ • caddy configs (désactivé) Cron: 4h00 │ +│ • wireguard (désactivé) │ +└──────────────────────────────────────────────────────────────┘ +``` + +### Réseaux Docker Swarm + +| Réseau | Type | Services | +|--------|------|----------| +| `reverse` | overlay | Caddy, Gitea, Woodpecker | +| `wireguard_network` | overlay | WireGuard, Perses | +| `prometheus_network` | overlay | Prometheus, Perses, cAdvisor, Caddy, Backup | + +--- + +## Stack technique + +### Orchestration +- **Docker Engine** avec Docker Swarm mode +- **Docker Compose** v3 (Stack deployment) +- **Docker Secrets** pour credentials sensibles +- **Docker Configs** pour configurations versionnées + +### Infrastructure as Code +- Configuration : `docker-compose.yml` +- Déploiement : `./deploy.sh` (génère timestamp pour versioning) +- Contexte Docker distant : `prod` + +### Networking +- **3 réseaux overlay** isolés +- **Reverse proxy** : Caddy avec Let's Encrypt automatique +- **HTTP/3** (QUIC) activé sur port 443/udp +- **VPN** : WireGuard pour services internes + +### Storage +- **Volumes Docker** : giteadata, woodpeckerdata, reversecaddydata, reversecaddyconfig, backuptemp +- **Host mounts** : /home/user/wireguard-config, /var/run/docker.sock (CI/CD) + +### Monitoring +- **Métriques** : Prometheus avec 10s scrape interval +- **Dashboards** : Perses (accessible via VPN) +- **Container metrics** : cAdvisor +- **Proxy metrics** : Caddy admin API (:2019) + +### Backups +- **Solution** : docker-volume-backup avec rclone +- **Fréquence** : Quotidien à 4h00 +- **Destination** : Serveur FTP distant +- **Rétention** : 14 jours +- **Format** : .tar.gz compressé + +--- + +## Fonctionnalités + +### Gitea +- Hébergement de repositories Git illimité +- Issues, Pull Requests, Wikis +- OAuth provider pour Woodpecker +- Interface web complète +- API REST + +### Woodpecker CI +- Pipelines CI/CD automatisés +- Intégration native avec Gitea +- Agent Docker-in-Docker +- Limite : 1 workflow concurrent, CPU core 1 +- Support multi-architectures + +### Caddy +- HTTPS automatique avec Let's Encrypt +- HTTP/3 (QUIC) support +- Renouvellement automatique des certificats +- Métriques Prometheus exposées +- Configuration simple (Caddyfile) + +### WireGuard +- VPN moderne et rapide +- Configuration : 1 peer (extensible) +- Accès sécurisé aux services internes +- Faible overhead + +### Monitoring +- **Prometheus** : Collecte et stockage des métriques +- **Perses** : Visualisation moderne (alternative Grafana) +- **cAdvisor** : Métriques CPU, RAM, I/O des containers +- Scrape automatique toutes les 10 secondes + +### Backups +- Sauvegarde automatique quotidienne +- Support FTP/SFTP via rclone +- Compression gzip +- Notifications optionnelles (Discord, Slack, Email) +- Rétention configurable + +--- + +## URLs et accès + +### Services publics +- **Gitea** : https://gitea.qpismont.fr +- **Woodpecker** : https://woodpecker.qpismont.fr +- **Portfolio** : ~~https://www.qpismont.fr~~ (désactivé) + +### Services internes (VPN requis) +- **Perses** : http://perses:8080 (via WireGuard) +- **Prometheus** : http://prometheus:9090 (via WireGuard) +- **Caddy Admin** : http://reverse_caddy:2019 (métriques) + +### VPN +- **Protocole** : WireGuard +- **Port** : 51820/udp +- **Config** : `/home/user/wireguard-config/peer1/` + +--- + +## Déploiement + +Le déploiement se fait via un contexte Docker distant vers le serveur de production : + +```bash +./deploy.sh +``` + +Le script génère un timestamp pour versionner les configs et secrets, puis déploie le stack `core` sur le contexte `prod`. + +**Prérequis :** +- Contexte Docker `prod` configuré +- Réseaux overlay créés (`reverse`, `wireguard_network`, `prometheus_network`) +- Secrets configurés dans `./secrets/` + +--- + +## Configuration + +### Secrets Docker + +| Secret | Usage | +|--------|-------| +| `woodpecker_agent_secret` | Communication server/agent Woodpecker | +| `woodpecker_gitea_client` | OAuth client ID Gitea | +| `woodpecker_gitea_secret` | OAuth client secret Gitea | +| `backup_ftp_config` | Configuration rclone pour FTP | + +### Configs Docker + +| Config | Fichier source | +|--------|----------------| +| `caddy_config` | `./Caddyfile` | +| `prometheus_config` | `./prometheus.yml` | + +Les configs et secrets sont versionnés avec `${DATETIME}` pour forcer les mises à jour lors du déploiement. + +--- + +## Problèmes connus + +### ⚠️ Service my_cv désactivé +Le Caddyfile contient des routes vers `my_cv:80` mais le service n'existe plus dans docker-compose.yml (retiré dans commit f047317). + +**Impact :** Routes `qpismont.fr` et `www.qpismont.fr` ne fonctionnent pas. + +### ⚠️ Prometheus non-persistant +Prometheus n'a pas de volume Docker, les métriques sont perdues à chaque redémarrage du container. + +**Impact :** Pas d'historique des métriques sur le long terme. + +### ⚠️ Volumes backup partiellement désactivés +Seul `giteadata` est actuellement sauvegardé. Les autres volumes (woodpecker, caddy, wireguard) sont commentés dans docker-compose.yml. + +**Impact :** Perte de données possible en cas d'incident sur ces volumes. + +--- + +## Documentation + +### Fichiers de documentation + +- **[README.md](./README.md)** : Ce fichier - présentation générale +- **[ANALYSE.md](./ANALYSE.md)** : Analyse détaillée de l'infrastructure + recommandations d'amélioration +- **[BACKUP.md](./BACKUP.md)** : Documentation complète du système de backup (configuration, utilisation, restauration) + +### Documentation externe + +- [Docker Swarm](https://docs.docker.com/engine/swarm/) +- [Caddy](https://caddyserver.com/docs/) +- [Gitea](https://docs.gitea.io/) +- [Woodpecker CI](https://woodpecker-ci.org/docs/) +- [WireGuard](https://www.wireguard.com/) +- [Prometheus](https://prometheus.io/docs/) +- [Perses](https://perses.dev/docs/) + +--- + +## Maintenance + +### Routine + +- **Quotidien** : Backup automatique à 4h00 +- **Hebdomadaire** : Vérification logs et backups +- **Mensuel** : Mise à jour des images Docker +- **Trimestriel** : Test de restauration des backups + +### Monitoring + +```bash +# Status des services +docker --context prod ps + +# Logs d'un service +docker --context prod logs -f $(docker --context prod ps -q -f name=core_SERVICE) + +# Métriques système +docker --context prod stats +``` + +### Mises à jour + +Modifier les versions dans `docker-compose.yml` puis : + +```bash +./deploy.sh +``` + +Docker Swarm appliquera les changements de manière progressive. + +--- + +## Sécurité + +### Mesures en place + +✅ HTTPS automatique (Let's Encrypt) +✅ Secrets Docker (credentials chiffrés) +✅ Network isolation (3 réseaux séparés) +✅ VPN pour services internes (WireGuard) +✅ Resource limits sur CI/CD agent +✅ Backups automatisés quotidiens +✅ Non-root user pour Gitea (UID 1000) + +### Recommandations + +Voir [ANALYSE.md](./ANALYSE.md) pour la liste complète des améliorations de sécurité suggérées. + +--- + +## Historique + +### 2025-10-27 +- ✅ Upgrade vers Debian 13 (devcontainer) +- ✅ Update Woodpecker v3.11.0 +- ✅ Update Gitea v1.24.7 +- ✅ Ajout WireGuard VPN +- ✅ Ajout stack monitoring (Prometheus + Perses + cAdvisor) +- ✅ Ajout système de backup automatique + +### 2025-06-23 +- ✅ Retrait service my_cv (portfolio) +- ✅ Update images Woodpecker et Gitea + +### Antérieur +- Déploiement devcontainer Debian +- Upgrades réguliers des services +- Ajout Woodpecker CI +- Migration vers Docker Swarm + +--- + +## Statistiques + +- **Services actifs** : 8 +- **Réseaux overlay** : 3 +- **Volumes Docker** : 5 +- **Secrets Docker** : 4 +- **Configs Docker** : 2 +- **Ports exposés** : 4 (80, 443/tcp, 443/udp, 51820/udp) +- **Backup size** : ~50-500 MB (dépend des données Gitea) +- **Uptime target** : 99%+ + +--- + +## Licence et Auteur + +**Propriétaire** : qpismont +**Usage** : Personnel +**Repository** : https://gitea.qpismont.fr/qpismont/infra + +--- + +**Dernière mise à jour :** 27 octobre 2025 diff --git a/docker-compose.yml b/docker-compose.yml index c6b8efb..684d647 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -108,6 +108,25 @@ services: networks: - prometheus_network + backup: + image: offen/docker-volume-backup:latest + environment: + BACKUP_CRON_EXPRESSION: "0 4 * * *" + BACKUP_RETENTION_DAYS: "14" + BACKUP_COMPRESSION: "gz" + BACKUP_FILENAME: "backup-infra-%Y-%m-%dT%H-%M-%S.tar.gz" + + BACKUP_BACKEND: "rclone" + RCLONE_REMOTE_NAME: "ftp" + RCLONE_REMOTE_PATH: "/backups/infra" + secrets: + - backup_ftp_config + entrypoint: /bin/sh -c "mkdir -p /root/.config/rclone && cat /run/secrets/backup_ftp_config > /root/.config/rclone/rclone.conf && /usr/bin/backup -foreground" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - giteadata:/backup/gitea:ro + - backuptemp:/tmp/backup + secrets: woodpecker_agent_secret: name: woodpecker_agent_secret_${DATETIME} @@ -118,6 +137,9 @@ secrets: woodpecker_gitea_client: name: woodpecker_gitea_client_${DATETIME} file: ./secrets/woodpecker_gitea_client + backup_ftp_config: + name: backup_ftp_config_${DATETIME} + file: ./secrets/backup_ftp_config configs: caddy_config: @@ -132,6 +154,7 @@ volumes: woodpeckerdata: reversecaddyconfig: reversecaddydata: + backuptemp: networks: reverse: