diff --git a/.env.example b/.env.example index e75b0f5..bd264e9 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,56 @@ -POSTGRES_DATABASE= -POSTGRES_USER= -POSTGRES_PASSWORD= +# ============================================ +# CONFIGURATION GITEA DOCKER +# ============================================ +# Copiez ce fichier vers .env et remplissez les valeurs +# cp .env.example .env -GITEA_DOMAIN=domain.tld -GITEA_SSH_DOMAIN=domain.tld -GITEA_ROOT_URL=https://domain.tld +# ============================================ +# MODE DE DÉPLOIEMENT +# ============================================ +# Décommentez la section qui vous concerne (dev OU prod) -REDIS_PASSWORD= +# --- DÉVELOPPEMENT (local) --- +# GITEA_DOMAIN=localhost +# GITEA_SSH_DOMAIN=localhost +# GITEA_ROOT_URL=http://localhost:3000 + +# --- PRODUCTION --- +GITEA_DOMAIN=git.domain.tld +GITEA_SSH_DOMAIN=git.domain.tld +GITEA_ROOT_URL=https://git.domain.tld + +# ============================================ +# BASE DE DONNÉES POSTGRESQL +# ============================================ +# Nom de la base de données +POSTGRES_DATABASE=gitea + +# Utilisateur PostgreSQL +POSTGRES_USER=gitea + +# Mot de passe PostgreSQL (CHANGEZ-MOI EN PRODUCTION!) +# Générez un mot de passe sécurisé: openssl rand -base64 32 +POSTGRES_PASSWORD=changeme_secure_password_here + +# ============================================ +# CACHE REDIS +# ============================================ +# Mot de passe Redis (CHANGEZ-MOI EN PRODUCTION!) +# Générez un mot de passe sécurisé: openssl rand -base64 32 +REDIS_PASSWORD=changeme_redis_password_here + +# ============================================ +# SAUVEGARDES +# ============================================ +# Nombre de jours de rétention des sauvegardes +BACKUP_RETENTION_DAYS=7 + +# ============================================ +# NOTES +# ============================================ +# 1. Ne commitez JAMAIS le fichier .env dans Git +# 2. Utilisez des mots de passe forts en production (32+ caractères) +# 3. Pour générer des mots de passe: openssl rand -base64 32 +# 4. En développement, Gitea est accessible sur http://localhost:3000 +# 5. SSH est accessible sur le port 2223 (ssh -p 2223 git@localhost) +# 6. En production, utilisez un reverse proxy (nginx/traefik) avec SSL diff --git a/.gitignore b/.gitignore index db65459..b3905cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,51 @@ -postgres -data +# ============================================ +# Gitea Docker .gitignore +# ============================================ + +# Fichiers de configuration sensibles .env + +# Données de base de données PostgreSQL +postgres/ +*.sql +*.dump + +# Données Gitea (dépôts, uploads, etc.) +data/ + +# Données Redis +redis/ + +# Sauvegardes +backups/ +*.tar.gz +*.zip + +# Logs +logs/ +*.log + +# Fichiers temporaires +tmp/ +temp/ +*.tmp +*.swp +*.swo +*~ + +# Système d'exploitation +.DS_Store +Thumbs.db +desktop.ini + +# IDE et éditeurs +.vscode/ +.idea/ +*.iml +.project +.settings/ +.classpath + +# Docker +.docker/ +docker-compose.override.yml diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c3d8787 --- /dev/null +++ b/Makefile @@ -0,0 +1,86 @@ +.PHONY: help up down restart ps logs logs-f backup restore update health shell-gitea shell-db clean + +# Include .env file if it exists +-include .env +export + +help: ## Afficher cette aide + @echo "Commandes disponibles pour Gitea Docker :" + @echo "" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' + +up: ## Démarrer tous les services + @echo "Démarrage des services Gitea..." + @docker compose up -d + @echo "Services démarrés. Accédez à Gitea sur http://localhost:3000" + +down: ## Arrêter tous les services + @echo "Arrêt des services..." + @docker compose down + +restart: ## Redémarrer tous les services + @echo "Redémarrage des services..." + @docker compose restart + +ps: ## Afficher le statut des services + @docker compose ps + +logs: ## Afficher les logs (dernières 100 lignes) + @docker compose logs --tail=100 + +logs-f: ## Suivre les logs en temps réel + @docker compose logs -f + +backup: ## Créer une sauvegarde complète (DB + repositories) + @bash scripts/backup.sh + +restore: ## Restaurer depuis une sauvegarde (usage: make restore FILE=backups/gitea_backup_YYYYMMDD_HHMMSS.tar.gz) + @if [ -z "$(FILE)" ]; then \ + echo "Erreur: Spécifiez le fichier de sauvegarde avec FILE="; \ + echo "Usage: make restore FILE=backups/gitea_backup_YYYYMMDD_HHMMSS.tar.gz"; \ + exit 1; \ + fi + @bash scripts/restore.sh "$(FILE)" + +update: ## Mettre à jour Gitea (avec backup automatique) + @bash scripts/update.sh + +health: ## Vérifier la santé des services + @echo "État de santé des services:" + @echo "" + @docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Health}}" + @echo "" + @echo "Détails des health checks:" + @docker inspect --format='{{.Name}}: {{.State.Health.Status}}' $$(docker compose ps -q) 2>/dev/null || echo "Aucun service en cours d'exécution" + +shell-gitea: ## Ouvrir un shell dans le conteneur Gitea + @docker compose exec gitea /bin/sh + +shell-db: ## Ouvrir un shell PostgreSQL + @docker compose exec db psql -U $(POSTGRES_USER) -d $(POSTGRES_DATABASE) + +clean: ## Nettoyer les conteneurs arrêtés et volumes non utilisés + @echo "Nettoyage des conteneurs arrêtés..." + @docker compose down -v + @echo "Nettoyage terminé" + +pull: ## Télécharger les dernières images Docker + @docker compose pull + +build: ## Rebuild les images si nécessaire + @docker compose build + +config: ## Valider et afficher la configuration docker-compose + @docker compose config + +# Commandes avancées +admin-create: ## Créer un utilisateur admin (usage: make admin-create USER=admin EMAIL=admin@example.com) + @if [ -z "$(USER)" ] || [ -z "$(EMAIL)" ]; then \ + echo "Usage: make admin-create USER=username EMAIL=email@example.com"; \ + exit 1; \ + fi + @docker compose exec gitea gitea admin user create --admin --username $(USER) --email $(EMAIL) --password "ChangeMe123!" + @echo "Utilisateur admin créé. Mot de passe par défaut: ChangeMe123!" + +stats: ## Afficher les statistiques d'utilisation des ressources + @docker stats --no-stream $$(docker compose ps -q) diff --git a/README.md b/README.md new file mode 100644 index 0000000..8497883 --- /dev/null +++ b/README.md @@ -0,0 +1,519 @@ +# Gitea Docker - Instance Auto-hébergée + +Déploiement Docker de Gitea avec PostgreSQL et Redis, conçu pour être stable, maintenable et facilement déployable. + +## Table des matières + +- [Architecture](#architecture) +- [Prérequis](#prérequis) +- [Installation](#installation) +- [Configuration](#configuration) +- [Démarrage](#démarrage) +- [Maintenance](#maintenance) + - [Sauvegardes](#sauvegardes) + - [Restauration](#restauration) + - [Mises à jour](#mises-à-jour) +- [Commandes Make](#commandes-make) +- [Dépannage](#dépannage) +- [Sécurité](#sécurité) +- [Structure du projet](#structure-du-projet) + +## Architecture + +Cette installation comprend 3 services Docker orchestrés : + +### Services + +1. **Gitea** - Serveur Git auto-hébergé + - Port web: `127.0.0.1:3000` (localhost uniquement) + - Port SSH: `2223` + - Base de données: PostgreSQL + - Cache: Redis + - Health check: API `/api/healthz` + +2. **PostgreSQL 15** - Base de données + - Stockage: `./postgres` + - Configuration personnalisée: `./db-config/postgresql.conf` + - Health check: `pg_isready` + +3. **Redis** - Cache et sessions + - Stockage: `./redis` (persistence AOF) + - Limite mémoire: 256MB + - Politique d'éviction: allkeys-lru + +### Réseaux + +- **gitea** (bridge) - Réseau interne pour la communication entre services + +## Prérequis + +### Logiciels requis + +- Docker >= 20.10 +- Docker Compose >= 2.0 +- Make (optionnel mais recommandé) +- Bash >= 4.0 + +### Ressources matérielles recommandées + +| Composant | Minimum | Recommandé | +| --------- | ------- | ---------- | +| CPU | 2 cœurs | 4+ cœurs | +| RAM | 2 GB | 4+ GB | +| Stockage | 10 GB | 50+ GB SSD | + +### Système d'exploitation + +- Linux (Ubuntu 20.04+, Debian 11+, etc.) +- macOS 10.15+ +- Windows 10/11 avec WSL2 + +## Installation + +### 1. Cloner le dépôt + +```bash +git clone +cd agence66-gitea +``` + +### 2. Créer le fichier de configuration + +```bash +cp .env.example .env +``` + +### 3. Configurer les variables d'environnement + +Éditez le fichier `.env` et modifiez les valeurs : + +```bash +nano .env # ou vim, code, etc. +``` + +**IMPORTANT**: Changez tous les mots de passe par défaut ! + +```bash +# Générer des mots de passe sécurisés +openssl rand -base64 32 +``` + +## Configuration + +### Variables d'environnement + +| Variable | Description | Exemple | +| ----------------------- | ------------------------- | ------------------------------- | +| `GITEA_DOMAIN` | Domaine principal | `git.example.com` | +| `GITEA_SSH_DOMAIN` | Domaine SSH | `git.example.com` | +| `GITEA_ROOT_URL` | URL complète | `https://git.example.com` | +| `POSTGRES_DATABASE` | Nom de la BDD | `gitea` | +| `POSTGRES_USER` | Utilisateur PostgreSQL | `gitea` | +| `POSTGRES_PASSWORD` | Mot de passe BDD | `changeme_secure_password_here` | +| `REDIS_PASSWORD` | Mot de passe Redis | `changeme_redis_password_here` | +| `BACKUP_RETENTION_DAYS` | Rétention des sauvegardes | `7` | + +### Configuration Développement vs Production + +#### Mode Développement (local) + +Dans `.env`, utilisez : + +```env +GITEA_DOMAIN=localhost +GITEA_SSH_DOMAIN=localhost +GITEA_ROOT_URL=http://localhost:3000 +``` + +Accès : + +- Web: http://localhost:3000 +- SSH: `ssh -p 2223 git@localhost` + +#### Mode Production + +Dans `.env`, utilisez : + +```env +GITEA_DOMAIN=domain.tld +GITEA_SSH_DOMAIN=domain.tld +GITEA_ROOT_URL=https://domain.tld +``` + +**IMPORTANT**: En production, utilisez un reverse proxy (nginx/traefik) avec SSL/TLS. + +### Configuration PostgreSQL + +La configuration optimisée se trouve dans `db-config/postgresql.conf`. + +Ajustez selon vos ressources : + +- `shared_buffers`: 25% de la RAM disponible +- `effective_cache_size`: 50-75% de la RAM disponible + +## Démarrage + +### Première installation + +```bash +# Démarrer tous les services +make up + +# Ou avec docker compose directement +docker compose up -d +``` + +### Accéder à Gitea + +1. Ouvrez votre navigateur sur http://localhost:3000 +2. Suivez l'assistant de configuration initial +3. Créez le premier utilisateur administrateur + +**Note**: La plupart des paramètres sont déjà configurés via les variables d'environnement. + +### Vérifier l'état des services + +```bash +make health +``` + +Ou : + +```bash +docker compose ps +``` + +## Maintenance + +### Sauvegardes + +#### Créer une sauvegarde manuelle + +```bash +make backup +``` + +Ou : + +```bash +bash scripts/backup.sh +``` + +**Contenu de la sauvegarde** : + +- Base de données PostgreSQL (dump compressé) +- Dépôts Git +- Configuration Gitea +- Données utilisateur + +**Emplacement** : `./backups/gitea_backup_YYYYMMDD_HHMMSS.tar.gz` + +#### Rétention automatique + +Les sauvegardes de plus de `BACKUP_RETENTION_DAYS` jours (défaut: 7) sont automatiquement supprimées. + +#### Sauvegardes automatiques (cron) + +Ajoutez une tâche cron pour des sauvegardes quotidiennes : + +```bash +crontab -e +``` + +Ajoutez : + +```cron +# Sauvegarde quotidienne à 3h du matin +0 3 * * * cd /chemin/vers/agence66-gitea && make backup >> /var/log/gitea-backup.log 2>&1 +``` + +### Restauration + +#### Restaurer depuis une sauvegarde + +```bash +make restore FILE=backups/gitea_backup_20240101_120000.tar.gz +``` + +Ou : + +```bash +bash scripts/restore.sh backups/gitea_backup_20240101_120000.tar.gz +``` + +**ATTENTION** : Cette opération est destructive et écrasera toutes les données actuelles ! + +Le script vous demandera confirmation avant de procéder. + +#### Processus de restauration + +1. Extraction de l'archive +2. Arrêt des services +3. Restauration de la base de données +4. Restauration des fichiers +5. Redémarrage des services + +### Mises à jour + +#### Mettre à jour Gitea + +```bash +make update +``` + +Ou : + +```bash +bash scripts/update.sh +``` + +**Le script effectue** : + +1. Sauvegarde automatique de sécurité +2. Téléchargement des nouvelles images +3. Arrêt des services +4. Démarrage avec les nouvelles versions +5. Vérification de l'état + +**En cas de problème**, restaurez la sauvegarde créée automatiquement : + +```bash +make restore FILE=backups/gitea_backup_YYYYMMDD_HHMMSS.tar.gz +``` + +## Commandes Make + +| Commande | Description | +| ----------------------- | ---------------------------------------- | +| `make help` | Afficher l'aide | +| `make up` | Démarrer tous les services | +| `make down` | Arrêter tous les services | +| `make restart` | Redémarrer les services | +| `make ps` | Afficher le statut des services | +| `make logs` | Afficher les logs (100 dernières lignes) | +| `make logs-f` | Suivre les logs en temps réel | +| `make backup` | Créer une sauvegarde | +| `make restore FILE=...` | Restaurer une sauvegarde | +| `make update` | Mettre à jour Gitea | +| `make health` | Vérifier la santé des services | +| `make shell-gitea` | Ouvrir un shell dans Gitea | +| `make shell-db` | Ouvrir un shell PostgreSQL | +| `make clean` | Nettoyer les conteneurs arrêtés | +| `make pull` | Télécharger les dernières images | +| `make config` | Valider la configuration Docker | +| `make stats` | Afficher les statistiques de ressources | + +### Créer un utilisateur admin en ligne de commande + +```bash +make admin-create USER=admin EMAIL=admin@example.com +``` + +Le mot de passe par défaut sera `ChangeMe123!` (à changer immédiatement). + +## Dépannage + +### Gitea ne démarre pas + +**Vérifier les logs** : + +```bash +make logs-f +``` + +Ou : + +```bash +docker compose logs -f gitea +``` + +**Causes courantes** : + +- Base de données non prête : attendez que PostgreSQL soit healthy +- Permissions de fichiers : vérifiez `./data` (UID/GID 1000) +- Port déjà utilisé : vérifiez si le port 3000 ou 2223 est disponible + +### Erreurs de base de données + +**Vérifier PostgreSQL** : + +```bash +make shell-db +``` + +**Vérifier la connexion** : + +```bash +docker compose exec db pg_isready -U gitea -d gitea +``` + +### Problèmes de performance + +**Vérifier l'utilisation des ressources** : + +```bash +make stats +``` + +**Optimisations** : + +1. Augmentez `shared_buffers` dans `db-config/postgresql.conf` +2. Ajustez la limite mémoire Redis dans `docker-compose.yml` +3. Activez la compression dans Gitea + +### Redis ne fonctionne pas + +**Vérifier Redis** : + +```bash +docker compose exec redis redis-cli --raw incr ping +``` + +### Réinitialisation complète + +**ATTENTION** : Cela supprimera toutes les données ! + +```bash +make down +sudo rm -rf data/ postgres/ redis/ backups/ +make up +``` + +## Sécurité + +### Bonnes pratiques + +1. **Mots de passe forts** : Utilisez des mots de passe de 32+ caractères + + ```bash + openssl rand -base64 32 + ``` + +2. **Fichier .env** : Ne le commitez JAMAIS dans Git (déjà dans .gitignore) + +3. **Mises à jour régulières** : Mettez à jour Gitea régulièrement + + ```bash + make update + ``` + +4. **Reverse proxy** : En production, utilisez nginx/traefik avec SSL/TLS + +5. **Firewall** : Limitez l'accès aux ports nécessaires + - 3000 : Web (via reverse proxy uniquement) + - 2223 : SSH Git + +6. **Sauvegardes** : Automatisez les sauvegardes et testez la restauration + +7. **Logs** : Surveillez les logs pour détecter les activités suspectes + ```bash + make logs-f + ``` + +### Exposition sécurisée (Production) + +**Avec nginx** : + +```nginx +server { + listen 80; + server_name git.domain.tld; + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + server_name git.domain.tld; + + ssl_certificate /etc/letsencrypt/live/git.domain.tld/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/git.domain.tld/privkey.pem; + + location / { + proxy_pass http://127.0.0.1:3000; + 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; + } +} +``` + +### SSH Git + +Le service SSH Gitea est exposé sur le port **2223**. + +**Cloner un dépôt** : + +```bash +git clone ssh://git@domain.tld:2223/username/repository.git +``` + +**Configuration SSH** (`~/.ssh/config`) : + +``` +Host git.domain.tld + Port 2223 + User git +``` + +Après cette configuration : + +```bash +git clone git@git.domain.tld:username/repository.git +``` + +## Structure du projet + +``` +agence66-gitea/ +├── .env # Configuration (ne pas committer) +├── .env.example # Template de configuration +├── .gitignore # Fichiers à ignorer par Git +├── docker-compose.yml # Orchestration Docker +├── Makefile # Commandes simplifiées +├── README.md # Cette documentation +├── backups/ # Sauvegardes (généré) +│ └── gitea_backup_*.tar.gz +├── data/ # Données Gitea (généré) +│ ├── git/ # Dépôts Git +│ ├── gitea/ # Configuration Gitea +│ └── ... +├── db-config/ # Configuration PostgreSQL +│ └── postgresql.conf +├── postgres/ # Données PostgreSQL (généré) +├── redis/ # Données Redis (généré) +└── scripts/ # Scripts de maintenance + ├── backup.sh # Sauvegarde complète + ├── restore.sh # Restauration + └── update.sh # Mise à jour +``` + +## Support + +### Problèmes et questions + +- Issues GitHub : Créez une issue sur le dépôt +- Documentation Gitea : https://docs.gitea.io/ +- Docker : https://docs.docker.com/ + +### Logs utiles + +```bash +# Tous les logs +make logs + +# Logs Gitea uniquement +docker compose logs -f gitea + +# Logs PostgreSQL +docker compose logs -f db + +# Logs Redis +docker compose logs -f redis +``` + +--- + +**Auteur** : Agence66 +**Licence** : À définir +**Version** : 1.0.0 diff --git a/db-config/postgresql.conf b/db-config/postgresql.conf new file mode 100644 index 0000000..f7e9faf --- /dev/null +++ b/db-config/postgresql.conf @@ -0,0 +1,77 @@ +# ============================================ +# Configuration PostgreSQL optimisée pour Gitea +# ============================================ +# Cette configuration est adaptée pour une instance Gitea +# avec une charge modérée (petit à moyen serveur) + +# CONNEXIONS +# ------------------------------------------- +max_connections = 100 +superuser_reserved_connections = 3 + +# MÉMOIRE +# ------------------------------------------- +# Ajustez selon la RAM disponible +# Recommandation: 25% de la RAM pour shared_buffers +shared_buffers = 256MB +effective_cache_size = 1GB +maintenance_work_mem = 64MB +work_mem = 4MB + +# WRITE AHEAD LOG (WAL) +# ------------------------------------------- +wal_buffers = 16MB +min_wal_size = 1GB +max_wal_size = 4GB +checkpoint_completion_target = 0.9 + +# QUERY TUNING +# ------------------------------------------- +random_page_cost = 1.1 +effective_io_concurrency = 200 +default_statistics_target = 100 + +# LOGGING +# ------------------------------------------- +logging_collector = on +log_directory = 'log' +log_filename = 'postgresql-%Y-%m-%d.log' +log_rotation_age = 1d +log_rotation_size = 100MB +log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' +log_timezone = 'UTC' + +# Logs des requêtes lentes (> 1 seconde) +log_min_duration_statement = 1000 + +# LOCALE ET FORMATAGE +# ------------------------------------------- +datestyle = 'iso, mdy' +timezone = 'UTC' +lc_messages = 'en_US.utf8' +lc_monetary = 'en_US.utf8' +lc_numeric = 'en_US.utf8' +lc_time = 'en_US.utf8' +default_text_search_config = 'pg_catalog.english' + +# AUTOVACUUM +# ------------------------------------------- +# Important pour maintenir les performances +autovacuum = on +autovacuum_max_workers = 3 +autovacuum_naptime = 1min +autovacuum_vacuum_threshold = 50 +autovacuum_analyze_threshold = 50 +autovacuum_vacuum_scale_factor = 0.1 +autovacuum_analyze_scale_factor = 0.05 + +# SÉCURITÉ +# ------------------------------------------- +# Les connexions sont limitées au réseau Docker +listen_addresses = '*' +ssl = off + +# AUTRES PARAMÈTRES +# ------------------------------------------- +shared_preload_libraries = '' +dynamic_shared_memory_type = posix diff --git a/docker-compose.yml b/docker-compose.yml index 9e7f348..d8eb8d2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,8 +4,10 @@ services: container_name: gitea restart: unless-stopped depends_on: - - db - - redis + db: + condition: service_healthy + redis: + condition: service_started environment: - USER_UID=1000 - USER_GID=1000 @@ -34,9 +36,16 @@ services: - /etc/localtime:/etc/localtime:ro networks: - gitea + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s db: image: postgres:15-alpine + container_name: gitea-db restart: unless-stopped environment: - POSTGRES_DB=${POSTGRES_DATABASE} @@ -44,15 +53,30 @@ services: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} volumes: - ./postgres:/var/lib/postgresql/data + - ./db-config/postgresql.conf:/etc/postgresql/postgresql.conf:ro networks: - gitea + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DATABASE}"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s redis: image: redis:alpine + container_name: gitea-redis restart: unless-stopped networks: - gitea - command: redis-server --requirepass ${REDIS_PASSWORD} + command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 256mb --maxmemory-policy allkeys-lru --appendonly yes + volumes: + - ./redis:/data + healthcheck: + test: ["CMD", "redis-cli", "--raw", "incr", "ping"] + interval: 10s + timeout: 3s + retries: 5 networks: gitea: diff --git a/scripts/backup.sh b/scripts/backup.sh new file mode 100755 index 0000000..2e7a56e --- /dev/null +++ b/scripts/backup.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# ============================================ +# Script de sauvegarde Gitea +# ============================================ +# Ce script crée une sauvegarde complète de: +# - Base de données PostgreSQL +# - Dépôts Git +# - Configuration Gitea +# - Données utilisateur + +set -e # Arrêter en cas d'erreur + +# Couleurs pour l'affichage +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Charger les variables d'environnement +if [ -f .env ]; then + source .env +else + echo -e "${RED}Erreur: Fichier .env non trouvé${NC}" + exit 1 +fi + +# Variables +BACKUP_DIR="./backups" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +BACKUP_NAME="gitea_backup_${TIMESTAMP}" +TEMP_DIR="${BACKUP_DIR}/${BACKUP_NAME}" +RETENTION_DAYS=${BACKUP_RETENTION_DAYS:-7} + +# Vérifier que les variables nécessaires sont définies +if [ -z "$POSTGRES_DATABASE" ] || [ -z "$POSTGRES_USER" ] || [ -z "$POSTGRES_PASSWORD" ]; then + echo -e "${RED}Erreur: Variables PostgreSQL non définies dans .env${NC}" + exit 1 +fi + +# Fonction de nettoyage en cas d'erreur +cleanup() { + if [ -d "$TEMP_DIR" ]; then + echo -e "${YELLOW}Nettoyage des fichiers temporaires...${NC}" + rm -rf "$TEMP_DIR" + fi +} + +# Piège pour nettoyer en cas d'erreur +trap cleanup EXIT + +echo -e "${GREEN}=== Début de la sauvegarde Gitea ===${NC}" +echo "Timestamp: $TIMESTAMP" + +# Créer les répertoires si nécessaire +mkdir -p "$BACKUP_DIR" +mkdir -p "$TEMP_DIR" + +# Vérifier que les conteneurs sont en cours d'exécution +if ! docker compose ps | grep -q "gitea.*running"; then + echo -e "${RED}Erreur: Le conteneur Gitea n'est pas en cours d'exécution${NC}" + exit 1 +fi + +echo -e "${YELLOW}[1/4] Sauvegarde de la base de données PostgreSQL...${NC}" +# Exporter la base de données +export PGPASSWORD="$POSTGRES_PASSWORD" +docker compose exec -T db pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DATABASE" \ + --format=custom \ + --compress=9 \ + --no-owner \ + --no-acl \ + > "${TEMP_DIR}/database.dump" + +if [ ! -s "${TEMP_DIR}/database.dump" ]; then + echo -e "${RED}Erreur: Le dump de la base de données est vide${NC}" + exit 1 +fi +echo -e "${GREEN}✓ Base de données sauvegardée${NC}" + +echo -e "${YELLOW}[2/4] Sauvegarde des dépôts Git et données...${NC}" +# Créer une archive des dépôts et données +docker compose exec -T gitea tar czf - \ + -C /data \ + --exclude='./log' \ + --exclude='./cache' \ + --exclude='./tmp' \ + --exclude='./sessions' \ + . > "${TEMP_DIR}/gitea_data.tar.gz" + +if [ ! -s "${TEMP_DIR}/gitea_data.tar.gz" ]; then + echo -e "${RED}Erreur: L'archive des données est vide${NC}" + exit 1 +fi +echo -e "${GREEN}✓ Dépôts et données sauvegardés${NC}" + +echo -e "${YELLOW}[3/4] Création de l'archive finale...${NC}" +# Créer l'archive finale +cd "$BACKUP_DIR" +tar czf "${BACKUP_NAME}.tar.gz" "${BACKUP_NAME}/" + +if [ ! -s "${BACKUP_NAME}.tar.gz" ]; then + echo -e "${RED}Erreur: L'archive finale est vide${NC}" + exit 1 +fi + +# Supprimer le répertoire temporaire +rm -rf "${BACKUP_NAME}" +cd - > /dev/null + +BACKUP_SIZE=$(du -h "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" | cut -f1) +echo -e "${GREEN}✓ Archive créée: ${BACKUP_NAME}.tar.gz (${BACKUP_SIZE})${NC}" + +echo -e "${YELLOW}[4/4] Nettoyage des anciennes sauvegardes (>$RETENTION_DAYS jours)...${NC}" +# Supprimer les sauvegardes plus anciennes que RETENTION_DAYS +find "$BACKUP_DIR" -name "gitea_backup_*.tar.gz" -type f -mtime +$RETENTION_DAYS -delete +REMAINING_BACKUPS=$(find "$BACKUP_DIR" -name "gitea_backup_*.tar.gz" -type f | wc -l) +echo -e "${GREEN}✓ Sauvegardes restantes: $REMAINING_BACKUPS${NC}" + +echo -e "${GREEN}=== Sauvegarde terminée avec succès ===${NC}" +echo "Fichier: ${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" +echo "Taille: $BACKUP_SIZE" diff --git a/scripts/restore.sh b/scripts/restore.sh new file mode 100755 index 0000000..750e289 --- /dev/null +++ b/scripts/restore.sh @@ -0,0 +1,191 @@ +#!/bin/bash +# ============================================ +# Script de restauration Gitea +# ============================================ +# Ce script restaure une sauvegarde complète de Gitea +# ATTENTION: Cette opération est destructive! + +set -e # Arrêter en cas d'erreur + +# Couleurs pour l'affichage +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Vérifier qu'un fichier de sauvegarde a été fourni +if [ -z "$1" ]; then + echo -e "${RED}Erreur: Aucun fichier de sauvegarde spécifié${NC}" + echo "Usage: $0 " + echo "Exemple: $0 backups/gitea_backup_20240101_120000.tar.gz" + exit 1 +fi + +BACKUP_FILE="$1" + +# Vérifier que le fichier existe +if [ ! -f "$BACKUP_FILE" ]; then + echo -e "${RED}Erreur: Le fichier $BACKUP_FILE n'existe pas${NC}" + exit 1 +fi + +# Vérifier que c'est bien un fichier gzip +if ! file "$BACKUP_FILE" | grep -q "gzip compressed"; then + echo -e "${RED}Erreur: Le fichier n'est pas une archive gzip valide${NC}" + exit 1 +fi + +# Validation du chemin (sécurité contre path traversal) +BACKUP_FILE=$(realpath "$BACKUP_FILE") +if [[ "$BACKUP_FILE" == *".."* ]]; then + echo -e "${RED}Erreur: Chemin invalide (path traversal détecté)${NC}" + exit 1 +fi + +# Charger les variables d'environnement +if [ -f .env ]; then + source .env +else + echo -e "${RED}Erreur: Fichier .env non trouvé${NC}" + exit 1 +fi + +# Vérifier que les variables nécessaires sont définies +if [ -z "$POSTGRES_DATABASE" ] || [ -z "$POSTGRES_USER" ] || [ -z "$POSTGRES_PASSWORD" ]; then + echo -e "${RED}Erreur: Variables PostgreSQL non définies dans .env${NC}" + exit 1 +fi + +# Variables +TEMP_DIR=$(mktemp -d) +BACKUP_NAME=$(basename "$BACKUP_FILE" .tar.gz) + +# Fonction de nettoyage +cleanup() { + if [ -d "$TEMP_DIR" ]; then + echo -e "${YELLOW}Nettoyage des fichiers temporaires...${NC}" + rm -rf "$TEMP_DIR" + fi +} + +# Piège pour nettoyer en cas d'erreur ou d'interruption +trap cleanup EXIT INT TERM + +echo -e "${RED}=== ATTENTION: Restauration de Gitea ===${NC}" +echo "Fichier de sauvegarde: $BACKUP_FILE" +echo -e "${RED}Cette opération va ÉCRASER toutes les données actuelles!${NC}" +echo "" +read -p "Êtes-vous sûr de vouloir continuer? (oui/non) " -r +if [[ ! $REPLY =~ ^[Oo][Uu][Ii]$ ]]; then + echo "Restauration annulée." + exit 0 +fi + +echo -e "${GREEN}=== Début de la restauration ===${NC}" + +echo -e "${YELLOW}[1/5] Extraction de l'archive...${NC}" +tar xzf "$BACKUP_FILE" -C "$TEMP_DIR" + +# Trouver le répertoire de sauvegarde +BACKUP_DIR=$(find "$TEMP_DIR" -maxdepth 1 -type d -name "gitea_backup_*" | head -n 1) +if [ -z "$BACKUP_DIR" ]; then + echo -e "${RED}Erreur: Structure de sauvegarde invalide${NC}" + exit 1 +fi + +# Vérifier que les fichiers nécessaires existent +if [ ! -f "$BACKUP_DIR/database.dump" ] || [ ! -f "$BACKUP_DIR/gitea_data.tar.gz" ]; then + echo -e "${RED}Erreur: Fichiers de sauvegarde manquants${NC}" + exit 1 +fi +echo -e "${GREEN}✓ Archive extraite${NC}" + +echo -e "${YELLOW}[2/5] Arrêt des services...${NC}" +docker compose down +echo -e "${GREEN}✓ Services arrêtés${NC}" + +echo -e "${YELLOW}[3/5] Démarrage de la base de données...${NC}" +docker compose up -d db +echo "Attente du démarrage de PostgreSQL..." +sleep 10 + +# Attendre que PostgreSQL soit prêt +MAX_TRIES=30 +COUNTER=0 +until docker compose exec -T db pg_isready -U "$POSTGRES_USER" > /dev/null 2>&1; do + COUNTER=$((COUNTER + 1)) + if [ $COUNTER -gt $MAX_TRIES ]; then + echo -e "${RED}Erreur: PostgreSQL ne démarre pas${NC}" + exit 1 + fi + echo "En attente de PostgreSQL... ($COUNTER/$MAX_TRIES)" + sleep 2 +done +echo -e "${GREEN}✓ PostgreSQL prêt${NC}" + +echo -e "${YELLOW}[4/5] Restauration de la base de données...${NC}" +# Supprimer et recréer la base de données +export PGPASSWORD="$POSTGRES_PASSWORD" +docker compose exec -T db psql -U "$POSTGRES_USER" -d postgres -c "DROP DATABASE IF EXISTS $POSTGRES_DATABASE;" +docker compose exec -T db psql -U "$POSTGRES_USER" -d postgres -c "CREATE DATABASE $POSTGRES_DATABASE OWNER $POSTGRES_USER;" + +# Restaurer le dump +docker compose exec -T db pg_restore \ + -U "$POSTGRES_USER" \ + -d "$POSTGRES_DATABASE" \ + --clean \ + --if-exists \ + --no-owner \ + --no-acl \ + < "$BACKUP_DIR/database.dump" + +echo -e "${GREEN}✓ Base de données restaurée${NC}" + +echo -e "${YELLOW}[5/5] Restauration des données Gitea...${NC}" +# Démarrer Gitea +docker compose up -d gitea redis + +# Attendre que Gitea soit prêt +echo "Attente du démarrage de Gitea..." +sleep 15 + +# Arrêter temporairement Gitea pour la restauration des fichiers +docker compose stop gitea + +# Nettoyer les données existantes +if [ -d "./data" ]; then + echo "Suppression des anciennes données..." + rm -rf ./data/* +fi + +# Extraire les données depuis l'archive +mkdir -p ./data +tar xzf "$BACKUP_DIR/gitea_data.tar.gz" -C ./data + +echo -e "${GREEN}✓ Données restaurées${NC}" + +echo -e "${YELLOW}Redémarrage de tous les services...${NC}" +docker compose up -d + +# Attendre que les services soient prêts +sleep 10 +MAX_TRIES=30 +COUNTER=0 +until docker compose ps | grep -q "gitea.*running"; do + COUNTER=$((COUNTER + 1)) + if [ $COUNTER -gt $MAX_TRIES ]; then + echo -e "${YELLOW}Avertissement: Gitea met du temps à démarrer${NC}" + break + fi + echo "En attente de Gitea... ($COUNTER/$MAX_TRIES)" + sleep 2 +done + +echo -e "${GREEN}=== Restauration terminée avec succès ===${NC}" +echo "Gitea devrait être accessible sur: http://localhost:3000" +echo "" +echo "Vérifications recommandées:" +echo " - Vérifier l'accès web" +echo " - Tester l'authentification" +echo " - Vérifier les dépôts" +echo " - Consulter les logs: docker compose logs -f gitea" diff --git a/scripts/update.sh b/scripts/update.sh new file mode 100755 index 0000000..e7b3f46 --- /dev/null +++ b/scripts/update.sh @@ -0,0 +1,106 @@ +#!/bin/bash +# ============================================ +# Script de mise à jour Gitea +# ============================================ +# Ce script met à jour Gitea de manière sécurisée +# avec une sauvegarde automatique avant la mise à jour + +set -e # Arrêter en cas d'erreur + +# Couleurs pour l'affichage +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Charger les variables d'environnement +if [ -f .env ]; then + source .env +else + echo -e "${RED}Erreur: Fichier .env non trouvé${NC}" + exit 1 +fi + +# Fonction de nettoyage en cas d'erreur +cleanup() { + echo -e "${YELLOW}Une erreur s'est produite. Vérifiez l'état des services.${NC}" + echo "Pour revenir à l'état précédent, utilisez la dernière sauvegarde:" + echo " make restore FILE=backups/gitea_backup_*.tar.gz" +} + +trap cleanup ERR + +echo -e "${GREEN}=== Mise à jour de Gitea ===${NC}" +echo "" + +# Vérifier que les services tournent +if ! docker compose ps | grep -q "gitea.*running"; then + echo -e "${YELLOW}Avertissement: Gitea ne semble pas être en cours d'exécution${NC}" + read -p "Continuer quand même? (oui/non) " -r + if [[ ! $REPLY =~ ^[Oo][Uu][Ii]$ ]]; then + echo "Mise à jour annulée." + exit 0 + fi +fi + +echo -e "${YELLOW}[1/6] Création d'une sauvegarde de sécurité...${NC}" +if ! bash scripts/backup.sh; then + echo -e "${RED}Erreur: La sauvegarde a échoué. Mise à jour annulée.${NC}" + exit 1 +fi +echo -e "${GREEN}✓ Sauvegarde créée${NC}" + +echo -e "${YELLOW}[2/6] Téléchargement des nouvelles images...${NC}" +docker compose pull +echo -e "${GREEN}✓ Images téléchargées${NC}" + +echo -e "${YELLOW}[3/6] Arrêt des services...${NC}" +docker compose down +echo -e "${GREEN}✓ Services arrêtés${NC}" + +echo -e "${YELLOW}[4/6] Démarrage avec les nouvelles versions...${NC}" +docker compose up -d +echo -e "${GREEN}✓ Services démarrés${NC}" + +echo -e "${YELLOW}[5/6] Attente du démarrage complet...${NC}" +sleep 10 + +# Attendre que Gitea soit prêt +MAX_TRIES=60 +COUNTER=0 +until docker compose exec -T gitea wget -q --spider http://localhost:3000/api/healthz 2>/dev/null; do + COUNTER=$((COUNTER + 1)) + if [ $COUNTER -gt $MAX_TRIES ]; then + echo -e "${RED}Erreur: Gitea ne répond pas après la mise à jour${NC}" + echo "Vérifiez les logs: docker compose logs gitea" + exit 1 + fi + echo "En attente de Gitea... ($COUNTER/$MAX_TRIES)" + sleep 2 +done +echo -e "${GREEN}✓ Gitea répond${NC}" + +echo -e "${YELLOW}[6/6] Vérification de l'état...${NC}" +# Afficher les versions +echo "" +echo "Versions actuelles:" +docker compose images + +echo "" +echo "État des services:" +docker compose ps + +echo "" +echo -e "${GREEN}=== Mise à jour terminée avec succès ===${NC}" +echo "" +echo "Vérifications recommandées:" +echo " 1. Accéder à l'interface web: http://localhost:3000" +echo " 2. Vérifier les dépôts existants" +echo " 3. Tester les fonctionnalités principales" +echo " 4. Consulter les logs: docker compose logs -f gitea" +echo "" +echo "En cas de problème, restaurez la sauvegarde:" +LATEST_BACKUP=$(ls -t backups/gitea_backup_*.tar.gz 2>/dev/null | head -n 1) +if [ -n "$LATEST_BACKUP" ]; then + echo " make restore FILE=$LATEST_BACKUP" +fi