Compare commits
32 Commits
c6de550329
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc1cac8e5a | ||
|
|
5d610b9177 | ||
|
|
8096d8985b | ||
|
|
8462b10e3b | ||
|
|
6bdd8e918c | ||
|
|
44ec0a004a | ||
|
|
c403419ea1 | ||
|
|
a1b51599c6 | ||
|
|
123f7b6a9c | ||
|
|
f02c9b36b2 | ||
|
|
43517b36cc | ||
|
|
57db8b6111 | ||
|
|
53cc23e153 | ||
|
|
a83426d198 | ||
|
|
6fa7704c13 | ||
|
|
b802c8a5cd | ||
|
|
b3ae8a8622 | ||
|
|
7dcffd2ae0 | ||
|
|
08fdfc3a2e | ||
|
|
51d42c6437 | ||
|
|
bd1e2dca27 | ||
|
|
e055d708a5 | ||
|
|
a7c14f9000 | ||
|
|
01c0db45f5 | ||
|
|
b693ed1364 | ||
|
|
dd27bdebb5 | ||
|
|
fcc60226ca | ||
|
|
fb2a3585d4 | ||
|
|
2ed5314537 | ||
|
|
85ed35923c | ||
|
|
f3c74de015 | ||
|
|
58bc9a47cc |
17
.dockerignore
Normal file
17
.dockerignore
Normal file
@@ -0,0 +1,17 @@
|
||||
# Données Nextcloud
|
||||
data/
|
||||
db/
|
||||
backups/
|
||||
logs/
|
||||
|
||||
# Docker
|
||||
docker-compose*.yml
|
||||
.env*
|
||||
|
||||
# Git
|
||||
.git/
|
||||
.gitignore
|
||||
|
||||
# Documentation
|
||||
README.md
|
||||
*.md
|
||||
@@ -20,6 +20,11 @@ REDIS_HOST_PASSWORD=CHANGEME_GENERATE_STRONG_PASSWORD
|
||||
BACKUP_DESTINATION=./backups
|
||||
BACKUP_RETENTION_DAYS=7
|
||||
|
||||
# Docker Compose
|
||||
# Le nom du projet est auto-détecté depuis le nom du dossier
|
||||
# Vous pouvez le surcharger ici si nécessaire:
|
||||
# COMPOSE_PROJECT_NAME=mon-nextcloud
|
||||
|
||||
# ============================================
|
||||
# DÉVELOPPEMENT (localhost)
|
||||
# ============================================
|
||||
|
||||
7
Dockerfile
Normal file
7
Dockerfile
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM nextcloud:latest
|
||||
|
||||
# Installer ffmpeg pour les previews vidéo
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ffmpeg \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
106
Makefile
106
Makefile
@@ -1,8 +1,11 @@
|
||||
.PHONY: help up down restart logs ps occ backup restore update health check-health recover
|
||||
.PHONY: help up down restart logs logs-all ps shell db-shell redis-shell occ backup restore update health check-health recover clean permissions cron-logs cron-status
|
||||
|
||||
include .env
|
||||
export
|
||||
|
||||
# Detect Docker Compose command
|
||||
DOCKER_COMPOSE := $(shell command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1 && echo "docker compose" || echo "docker-compose")
|
||||
|
||||
help:
|
||||
@echo "Nextcloud Docker - Commandes disponibles:"
|
||||
@echo ""
|
||||
@@ -12,6 +15,7 @@ help:
|
||||
@echo " make restart - Redémarrer tous les services"
|
||||
@echo " make ps - Lister les containers actifs"
|
||||
@echo " make logs - Afficher les logs Nextcloud en temps réel"
|
||||
@echo " make logs-all - Afficher les logs de tous les containers"
|
||||
@echo ""
|
||||
@echo "Maintenance:"
|
||||
@echo " make backup - Backup complet (DB + fichiers + config)"
|
||||
@@ -27,29 +31,64 @@ help:
|
||||
@echo " → Upgrade base de données"
|
||||
@echo " → Optimisations post-update"
|
||||
@echo ""
|
||||
@echo " make restore <file> - Restaurer depuis un backup"
|
||||
@echo " make restore FILE=<backup.tar.gz>"
|
||||
@echo " - Restaurer depuis un backup"
|
||||
@echo " → Arrêt des services"
|
||||
@echo " → Restauration DB + fichiers"
|
||||
@echo " → Redémarrage et réparation"
|
||||
@echo ""
|
||||
@echo " make recover - Récupération après erreur"
|
||||
@echo " → Arrêt/nettoyage des containers"
|
||||
@echo " → Redémarrage propre"
|
||||
@echo " → Désactivation mode maintenance"
|
||||
@echo ""
|
||||
@echo "Monitoring:"
|
||||
@echo " make health - Health check complet du système"
|
||||
@echo " → Docker, containers, Nextcloud, DB, Redis"
|
||||
@echo " → Espace disque, backups, logs"
|
||||
@echo ""
|
||||
@echo "Automatisation:"
|
||||
@echo " make cron-status - Afficher le statut et le planning des backups auto"
|
||||
@echo " make cron-logs - Afficher les logs des tâches cron"
|
||||
@echo ""
|
||||
@echo "Outils:"
|
||||
@echo " make occ <cmd> - Exécuter une commande OCC Nextcloud"
|
||||
@echo " make health - Vérifier l'état (Nextcloud + DB + config)"
|
||||
@echo " make shell - Ouvrir un shell dans le container Nextcloud"
|
||||
@echo " make db-shell - Ouvrir un shell MySQL/MariaDB"
|
||||
@echo " make redis-shell - Ouvrir un shell Redis"
|
||||
@echo " make permissions - Réparer les permissions des fichiers"
|
||||
@echo " make clean - Nettoyer les logs et fichiers temporaires"
|
||||
|
||||
up:
|
||||
docker-compose up -d
|
||||
$(DOCKER_COMPOSE) up -d
|
||||
|
||||
down:
|
||||
docker-compose down
|
||||
$(DOCKER_COMPOSE) down
|
||||
|
||||
restart:
|
||||
docker-compose restart
|
||||
$(DOCKER_COMPOSE) restart
|
||||
|
||||
logs:
|
||||
docker-compose logs -f --tail=100 nextcloud
|
||||
$(DOCKER_COMPOSE) logs -f --tail=100 nextcloud
|
||||
|
||||
logs-all:
|
||||
$(DOCKER_COMPOSE) logs -f --tail=50
|
||||
|
||||
ps:
|
||||
docker-compose ps
|
||||
$(DOCKER_COMPOSE) ps
|
||||
|
||||
shell:
|
||||
$(DOCKER_COMPOSE) exec nextcloud /bin/bash
|
||||
|
||||
db-shell:
|
||||
$(DOCKER_COMPOSE) exec db mysql -u"$$MYSQL_USER" -p"$$MYSQL_PASSWORD" "$$MYSQL_DATABASE"
|
||||
|
||||
redis-shell:
|
||||
@if [ -n "$(REDIS_HOST_PASSWORD)" ]; then \
|
||||
$(DOCKER_COMPOSE) exec redis redis-cli -a "$(REDIS_HOST_PASSWORD)"; \
|
||||
else \
|
||||
$(DOCKER_COMPOSE) exec redis redis-cli; \
|
||||
fi
|
||||
|
||||
occ:
|
||||
@bash scripts/occ.sh $(filter-out $@,$(MAKECMDGOALS))
|
||||
@@ -58,22 +97,61 @@ backup:
|
||||
@bash scripts/backup.sh
|
||||
|
||||
restore:
|
||||
@bash scripts/restore.sh $(filter-out $@,$(MAKECMDGOALS))
|
||||
@if [ -z "$(FILE)" ]; then \
|
||||
echo "❌ Erreur: Spécifiez le fichier de backup avec FILE=<fichier>"; \
|
||||
echo "Exemple: make restore FILE=./backups/nextcloud_backup_20231217_123456.tar.gz"; \
|
||||
echo ""; \
|
||||
echo "Backups disponibles:"; \
|
||||
find ./backups -name "nextcloud_backup_*.tar.gz" -type f -printf '%T+ %p\n' 2>/dev/null | sort -r | head -5; \
|
||||
exit 1; \
|
||||
fi
|
||||
@bash scripts/restore.sh "$(FILE)"
|
||||
|
||||
update:
|
||||
@bash scripts/update.sh
|
||||
|
||||
health:
|
||||
@docker-compose exec nextcloud php occ status
|
||||
@docker-compose exec nextcloud php occ config:list system
|
||||
@docker-compose exec -T db sh -c 'mysql -u"$$MYSQL_USER" -p"$$MYSQL_PASSWORD" -e "SELECT 1"' 2>/dev/null && echo "✅ Base de données accessible" || echo "❌ Erreur base de données"
|
||||
|
||||
check-health:
|
||||
@bash scripts/check-health.sh
|
||||
|
||||
recover:
|
||||
@bash scripts/recover.sh
|
||||
|
||||
permissions:
|
||||
@echo "Réparation des permissions..."
|
||||
$(DOCKER_COMPOSE) exec -u root nextcloud chown -R www-data:www-data /var/www/html/data /var/www/html/config /var/www/html/custom_apps
|
||||
@echo "✅ Permissions réparées"
|
||||
|
||||
clean:
|
||||
@echo "Nettoyage des logs et fichiers temporaires..."
|
||||
@find ./logs -type f -mtime +30 -delete 2>/dev/null && echo "✅ Logs > 30 jours supprimés" || true
|
||||
@rm -f /tmp/nextcloud_*.lock 2>/dev/null && echo "✅ Fichiers lock supprimés" || true
|
||||
@$(DOCKER_COMPOSE) exec -T nextcloud php occ files:cleanup 2>/dev/null && echo "✅ Fichiers orphelins nettoyés" || true
|
||||
@echo "✅ Nettoyage terminé"
|
||||
|
||||
cron-status:
|
||||
@echo "=== Statut du service de backup automatique ==="
|
||||
@echo ""
|
||||
@echo "Container backup-cron:"
|
||||
@$(DOCKER_COMPOSE) ps backup-cron
|
||||
@echo ""
|
||||
@echo "Planning des tâches:"
|
||||
@$(DOCKER_COMPOSE) exec -T backup-cron cat /etc/crontabs/root 2>/dev/null | grep -v "^#" | grep -v "^$$" || echo "⚠ Container non démarré"
|
||||
@echo ""
|
||||
@echo "Heure du container:"
|
||||
@$(DOCKER_COMPOSE) exec -T backup-cron date 2>/dev/null || echo "⚠ Container non démarré"
|
||||
|
||||
cron-logs:
|
||||
@echo "=== Logs des tâches automatiques ==="
|
||||
@echo ""
|
||||
@echo "Logs de backup (10 dernières lignes):"
|
||||
@tail -n 10 ./logs/cron_backup.log 2>/dev/null || echo "Aucun log de backup"
|
||||
@echo ""
|
||||
@echo "Logs de health check (10 dernières lignes):"
|
||||
@tail -n 10 ./logs/cron_health.log 2>/dev/null || echo "Aucun log de health check"
|
||||
@echo ""
|
||||
@echo "Logs de nettoyage (10 dernières lignes):"
|
||||
@tail -n 10 ./logs/cron_clean.log 2>/dev/null || echo "Aucun log de nettoyage"
|
||||
|
||||
# Catch-all target pour permettre les arguments aux commandes occ et restore
|
||||
%:
|
||||
@:
|
||||
|
||||
236
README.md
236
README.md
@@ -16,12 +16,13 @@ Déploiement Nextcloud avec Docker Compose comprenant MariaDB 10.11, Redis (cach
|
||||
|
||||
## Architecture
|
||||
|
||||
Le déploiement comprend 4 services:
|
||||
Le déploiement comprend 5 services:
|
||||
|
||||
- **nextcloud**: Application Nextcloud (port 127.0.0.1:8888:80)
|
||||
- **nextcloud**: Application Nextcloud avec image personnalisée (inclut ffmpeg) - port 127.0.0.1:8888:80
|
||||
- **db**: MariaDB 10.11 avec healthcheck
|
||||
- **redis**: Cache Redis avec politique LRU (512MB max)
|
||||
- **cron**: Tâches planifiées Nextcloud (préviews, nettoyage, etc.)
|
||||
- **backup-cron**: Système de backup automatisé (quotidien)
|
||||
|
||||
**Réseaux**:
|
||||
|
||||
@@ -113,11 +114,126 @@ Les paramètres PHP sont préconfigurés dans docker-compose.yml:
|
||||
|
||||
Ces valeurs permettent l'upload de fichiers jusqu'à 2GB.
|
||||
|
||||
### Image Docker personnalisée
|
||||
|
||||
Le projet utilise une image Docker personnalisée basée sur `nextcloud:latest` qui inclut **ffmpeg** pour la génération de previews vidéo (.mov, .mp4, etc.).
|
||||
|
||||
**Dockerfile:**
|
||||
```dockerfile
|
||||
FROM nextcloud:latest
|
||||
|
||||
# Installer ffmpeg pour les previews vidéo
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ffmpeg \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
**Builder l'image:**
|
||||
|
||||
```bash
|
||||
# Builder l'image custom
|
||||
docker compose build nextcloud
|
||||
|
||||
# Ou forcer le rebuild
|
||||
docker compose build --no-cache nextcloud
|
||||
```
|
||||
|
||||
**Vérifier ffmpeg:**
|
||||
|
||||
```bash
|
||||
docker compose exec nextcloud ffmpeg -version
|
||||
```
|
||||
|
||||
**Activer les previews vidéo:**
|
||||
|
||||
Après le premier démarrage, activez les providers de preview pour les vidéos:
|
||||
|
||||
```bash
|
||||
docker compose exec -u www-data nextcloud php occ config:system:set enabledPreviewProviders 0 --value="OC\\Preview\\Movie"
|
||||
docker compose exec -u www-data nextcloud php occ config:system:set enabledPreviewProviders 1 --value="OC\\Preview\\PNG"
|
||||
docker compose exec -u www-data nextcloud php occ config:system:set enabledPreviewProviders 2 --value="OC\\Preview\\JPEG"
|
||||
docker compose exec -u www-data nextcloud php occ config:system:set enabledPreviewProviders 3 --value="OC\\Preview\\GIF"
|
||||
docker compose exec -u www-data nextcloud php occ config:system:set enabledPreviewProviders 4 --value="OC\\Preview\\BMP"
|
||||
|
||||
# Générer les previews pour un utilisateur
|
||||
docker compose exec -u www-data nextcloud php occ preview:generate-all nom_utilisateur
|
||||
```
|
||||
|
||||
**Note:** L'image est buildée localement et taguée `nextcloud-custom:latest`. Lors des mises à jour Nextcloud, pensez à rebuild l'image.
|
||||
|
||||
# Server Transport Traefik
|
||||
|
||||
Ajouter à traefik.yml :
|
||||
```yml
|
||||
serversTransport:
|
||||
nextcloud-transport:
|
||||
forwardingTimeouts:
|
||||
dialTimeout: 30s
|
||||
responseHeaderTimeout: 0s
|
||||
idleConnTimeout: 3600s
|
||||
```
|
||||
OU au docker-compose.yml
|
||||
```yml
|
||||
command:
|
||||
- "--serverstransport.forwardingtimeouts.dialtimeout=30s"
|
||||
- "--serverstransport.forwardingtimeouts.responseheadertimeout=0"
|
||||
- "--serverstransport.forwardingtimeouts.idleconntimeout=3600s"
|
||||
```
|
||||
### Configuration Apache pour Traefik
|
||||
|
||||
Le fichier `apache/nextcloud.conf` configure Apache pour fonctionner correctement derrière le reverse proxy Traefik.
|
||||
|
||||
**Configuration incluse:**
|
||||
|
||||
- **RemoteIP**: Récupération de l'IP réelle du client (pas celle de Traefik)
|
||||
- **X-Forwarded-Proto**: Détection automatique HTTPS depuis Traefik
|
||||
- **Headers de sécurité**: X-Frame-Options, X-Content-Type-Options, etc.
|
||||
- **WebDAV désactivé**: Évite les conflits (Nextcloud gère son propre WebDAV)
|
||||
|
||||
**Activation des modules Apache:**
|
||||
|
||||
Lors du premier déploiement, activez les modules nécessaires:
|
||||
|
||||
```bash
|
||||
# Activer tous les modules en une commande
|
||||
docker compose exec nextcloud bash -c "a2enmod headers rewrite dir mime remoteip env && apache2ctl graceful"
|
||||
|
||||
# Redémarrer Nextcloud pour appliquer les changements
|
||||
docker compose restart nextcloud
|
||||
```
|
||||
|
||||
**Modules activés:**
|
||||
|
||||
| Module | Utilité |
|
||||
| ---------- | ---------------------------------------------------- |
|
||||
| `headers` | Gestion des headers HTTP (sécurité) |
|
||||
| `rewrite` | URL rewriting (requis pour .htaccess) |
|
||||
| `dir` | DirectoryIndex (index.php, etc.) |
|
||||
| `mime` | Types MIME (CSS, JS, etc.) |
|
||||
| `remoteip` | Récupération IP client via X-Forwarded-For |
|
||||
| `env` | Variables d'environnement (détection HTTPS) |
|
||||
|
||||
**Note**: Les modules `headers`, `rewrite`, `dir`, et `mime` sont normalement activés par défaut dans l'image `nextcloud:latest`. Seuls `remoteip` et `env` doivent être activés manuellement.
|
||||
|
||||
**Vérification:**
|
||||
|
||||
```bash
|
||||
# Vérifier qu'Apache utilise bien la configuration
|
||||
docker compose exec nextcloud apache2ctl -M | grep -E "(headers|rewrite|remoteip|env)"
|
||||
|
||||
# Vérifier les logs avec IP réelle
|
||||
docker compose logs nextcloud --tail=20
|
||||
```
|
||||
|
||||
## Démarrage
|
||||
|
||||
### Première installation
|
||||
|
||||
```bash
|
||||
# Builder l'image personnalisée (inclut ffmpeg)
|
||||
docker compose build nextcloud
|
||||
|
||||
# Démarrer tous les services
|
||||
make up
|
||||
|
||||
@@ -223,7 +339,7 @@ make update
|
||||
1. 💾 **Backup automatique de sécurité**
|
||||
- Exécute `scripts/backup.sh` complet
|
||||
- Archive créée dans `./backups/`
|
||||
2. 📥 Télécharge la nouvelle image Docker Nextcloud
|
||||
2. 🔨 Rebuild l'image personnalisée avec la nouvelle version Nextcloud
|
||||
3. ⏸️ Active le mode maintenance
|
||||
4. 🔄 Redémarre les containers avec `--force-recreate`
|
||||
5. ⏳ Attend que Nextcloud soit prêt (health check jusqu'à 60s)
|
||||
@@ -339,6 +455,119 @@ du -sh ./data # Données Nextcloud
|
||||
du -sh ./db # Base de données MariaDB
|
||||
```
|
||||
|
||||
### Mode débogage
|
||||
|
||||
⚠️ **IMPORTANT**: Le mode débogage ne doit **JAMAIS** être activé en production!
|
||||
|
||||
**Vérifier l'état du mode débogage:**
|
||||
|
||||
```bash
|
||||
make occ config:system:get debug
|
||||
```
|
||||
|
||||
**Désactiver le mode débogage (PRODUCTION):**
|
||||
|
||||
```bash
|
||||
# Via OCC (recommandé)
|
||||
make occ config:system:set debug --value=false --type=boolean
|
||||
|
||||
# OU éditer manuellement config.php
|
||||
docker-compose exec nextcloud nano /var/www/html/config/config.php
|
||||
# Chercher 'debug' => true, et changer en false ou supprimer la ligne
|
||||
```
|
||||
|
||||
**Activer temporairement pour diagnostiquer un problème (DÉVELOPPEMENT UNIQUEMENT):**
|
||||
|
||||
```bash
|
||||
# Activer
|
||||
make occ config:system:set debug --value=true --type=boolean
|
||||
|
||||
# IMPORTANT: Désactiver immédiatement après le diagnostic!
|
||||
make occ config:system:set debug --value=false --type=boolean
|
||||
```
|
||||
|
||||
**Pourquoi c'est dangereux en production:**
|
||||
|
||||
- 🚨 **Sécurité**: Expose des informations sensibles (chemins, configuration, requêtes SQL)
|
||||
- 🐌 **Performance**: Génère énormément de logs et ralentit l'application
|
||||
- 💾 **Espace disque**: Remplit rapidement le disque avec des logs détaillés
|
||||
- 📊 **Conformité**: Peut logger des données personnelles (RGPD)
|
||||
|
||||
### Messages de debug dans la console navigateur
|
||||
|
||||
Si vous voyez des messages `[DEBUG]` dans la console JavaScript du navigateur (F12), même avec `debug => false`:
|
||||
|
||||
**1. Vider tous les caches:**
|
||||
|
||||
```bash
|
||||
# Cache Nextcloud
|
||||
make occ maintenance:repair --include-expensive
|
||||
|
||||
# Cache Redis
|
||||
docker compose exec redis redis-cli -a VOTRE_PASSWORD_REDIS FLUSHALL
|
||||
```
|
||||
|
||||
**2. Vérifier le niveau de log:**
|
||||
|
||||
```bash
|
||||
# Niveau recommandé pour production: 2 (Warning)
|
||||
make occ config:system:set loglevel --value=2 --type=integer
|
||||
```
|
||||
|
||||
**Niveaux de log disponibles:**
|
||||
- 0 = Debug (tous les messages)
|
||||
- 1 = Info
|
||||
- 2 = Warning (recommandé production)
|
||||
- 3 = Error
|
||||
- 4 = Fatal
|
||||
|
||||
**3. Hard refresh dans le navigateur:**
|
||||
|
||||
```bash
|
||||
# Firefox/Chrome: Ctrl + Shift + R
|
||||
# Ou vider le cache du navigateur pour le domaine Nextcloud
|
||||
```
|
||||
|
||||
**4. Redémarrer les services:**
|
||||
|
||||
```bash
|
||||
docker compose restart nextcloud redis
|
||||
```
|
||||
|
||||
### Problèmes de synchronisation client
|
||||
|
||||
Si le client de synchronisation Nextcloud affiche "error transfering, server replied not found":
|
||||
|
||||
**1. Scanner les fichiers pour mettre à jour l'index:**
|
||||
|
||||
```bash
|
||||
# Scanner tous les fichiers d'un utilisateur
|
||||
make occ files:scan nom_utilisateur
|
||||
|
||||
# Scanner uniquement un dossier spécifique
|
||||
make occ files:scan --path="/nom_utilisateur/files/Dossier"
|
||||
```
|
||||
|
||||
**2. Nettoyer les verrous de fichiers:**
|
||||
|
||||
```bash
|
||||
make occ files:cleanup
|
||||
```
|
||||
|
||||
**3. Vérifier les logs pour identifier le fichier problématique:**
|
||||
|
||||
```bash
|
||||
# Logs en temps réel
|
||||
docker compose logs -f nextcloud --tail=50
|
||||
|
||||
# Rechercher les erreurs 404
|
||||
docker compose logs nextcloud | grep "404"
|
||||
```
|
||||
|
||||
**4. En dernier recours, réinitialiser la synchronisation:**
|
||||
- Dans le client Nextcloud: supprimer le compte et le re-configurer
|
||||
- Cela forcera une synchronisation complète
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Vérifications de santé
|
||||
@@ -381,6 +610,7 @@ docker compose exec redis redis-cli -a ${REDIS_HOST_PASSWORD} INFO stats
|
||||
3. **Mises à jour régulières**: Exécutez `make backup` puis `make update` mensuellement
|
||||
4. **Sauvegardes**: Utilisez `make backup` avant toute mise à jour (backup serveur quotidien géré au niveau système)
|
||||
5. **Monitoring**: Vérifiez les logs régulièrement pour détecter les activités suspectes
|
||||
6. **Mode débogage désactivé**: Vérifiez avec `make occ config:system:get debug` (doit être `false` ou absent)
|
||||
|
||||
### Sécuriser l'accès
|
||||
|
||||
|
||||
16
apache/mpm_prefork.conf
Normal file
16
apache/mpm_prefork.conf
Normal file
@@ -0,0 +1,16 @@
|
||||
# prefork MPM
|
||||
# StartServers: number of server processes to start
|
||||
# MinSpareServers: minimum number of server processes which are kept spare
|
||||
# MaxSpareServers: maximum number of server processes which are kept spare
|
||||
# ServerLimit: maximum value for MaxRequestWorkers (must be set before MaxRequestWorkers)
|
||||
# MaxRequestWorkers: maximum number of server processes allowed to start
|
||||
# MaxConnectionsPerChild: maximum number of requests a server process serves
|
||||
|
||||
<IfModule mpm_prefork_module>
|
||||
ServerLimit 400
|
||||
StartServers 10
|
||||
MinSpareServers 10
|
||||
MaxSpareServers 20
|
||||
MaxRequestWorkers 400
|
||||
MaxConnectionsPerChild 1000
|
||||
</IfModule>
|
||||
48
apache/nextcloud.conf
Normal file
48
apache/nextcloud.conf
Normal file
@@ -0,0 +1,48 @@
|
||||
# Configuration pour reverse proxy Traefik
|
||||
# Récupération de l'IP réelle du client via X-Forwarded-For
|
||||
ServerName cloud.agence66.fr
|
||||
|
||||
# Autoriser les caractères spéciaux encodés dans les noms de fichiers
|
||||
AllowEncodedSlashes NoDecode
|
||||
|
||||
RemoteIPHeader X-Forwarded-For
|
||||
RemoteIPTrustedProxy 172.16.0.0/12
|
||||
RemoteIPTrustedProxy 10.0.0.0/8
|
||||
RemoteIPTrustedProxy 192.168.0.0/16
|
||||
|
||||
# Activer la confiance des en-têtes X-Forwarded-Proto
|
||||
SetEnvIf X-Forwarded-Proto "https" HTTPS=on
|
||||
|
||||
# Timeouts pour gros fichiers (>40MB)
|
||||
Timeout 3600
|
||||
KeepAlive On
|
||||
KeepAliveTimeout 300
|
||||
MaxKeepAliveRequests 200
|
||||
|
||||
<Directory /var/www/html/>
|
||||
Options FollowSymLinks MultiViews
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
|
||||
<IfModule mod_dav.c>
|
||||
Dav off
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
# Headers de sécurité (si non gérés par Traefik)
|
||||
<IfModule mod_headers.c>
|
||||
# HSTS sera géré par Traefik
|
||||
# Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
|
||||
|
||||
# Autres headers de sécurité
|
||||
Header always set Referrer-Policy "no-referrer-when-downgrade"
|
||||
Header always set X-Content-Type-Options "nosniff"
|
||||
Header always set X-Frame-Options "SAMEORIGIN"
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
Header always set X-Robots-Tag "noindex, nofollow"
|
||||
</IfModule>
|
||||
|
||||
# Logs avec IP réelle (pas l'IP de Traefik)
|
||||
<IfModule mod_remoteip.c>
|
||||
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
</IfModule>
|
||||
24
cron/Dockerfile
Normal file
24
cron/Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
FROM alpine:latest
|
||||
|
||||
# Installer les dépendances nécessaires
|
||||
RUN apk add --no-cache \
|
||||
docker-cli \
|
||||
docker-cli-compose \
|
||||
bash \
|
||||
tzdata
|
||||
|
||||
# Configurer le fuseau horaire
|
||||
ENV TZ=Europe/Paris
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
# Copier le fichier crontab
|
||||
COPY crontab /etc/crontabs/root
|
||||
|
||||
# Copier le script d'entrée
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
# Créer le répertoire pour les logs
|
||||
RUN mkdir -p /logs
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
147
cron/README.md
Normal file
147
cron/README.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Backup Automatique Nextcloud
|
||||
|
||||
Ce dossier contient la configuration pour les backups automatiques via un container Docker dédié.
|
||||
|
||||
## Architecture
|
||||
|
||||
Le service `backup-cron` est un container Alpine Linux léger qui exécute des tâches planifiées:
|
||||
|
||||
- **Image**: Alpine Linux avec Docker CLI et docker-compose
|
||||
- **Fuseau horaire**: Europe/Paris (configurable via `TZ`)
|
||||
- **Montages**:
|
||||
- `/project`: Projet complet (scripts, config, etc.)
|
||||
- `/var/run/docker.sock`: Socket Docker pour exécuter docker-compose
|
||||
- `/logs`: Répertoire des logs partagé avec l'hôte
|
||||
|
||||
## Planning par défaut
|
||||
|
||||
| Tâche | Fréquence | Heure | Description |
|
||||
|-------|-----------|-------|-------------|
|
||||
| Backup | Quotidien | 5h00 | Backup complet (DB + fichiers) |
|
||||
| Health check | Quotidien | 6h00 | Vérification après backup |
|
||||
| Nettoyage | Hebdomadaire | Dimanche 3h00 | Suppression logs > 30 jours |
|
||||
|
||||
## Utilisation
|
||||
|
||||
### Démarrer le service
|
||||
|
||||
```bash
|
||||
# Build et démarrage
|
||||
docker-compose up -d backup-cron
|
||||
|
||||
# Ou reconstruire si modifié
|
||||
docker-compose up -d --build backup-cron
|
||||
```
|
||||
|
||||
### Vérifier le statut
|
||||
|
||||
```bash
|
||||
# Via Makefile
|
||||
make cron-status
|
||||
|
||||
# Ou directement
|
||||
docker-compose ps backup-cron
|
||||
docker-compose exec backup-cron cat /etc/crontabs/root
|
||||
```
|
||||
|
||||
### Consulter les logs
|
||||
|
||||
```bash
|
||||
# Via Makefile
|
||||
make cron-logs
|
||||
|
||||
# Ou directement
|
||||
tail -f logs/cron_backup.log
|
||||
tail -f logs/cron_health.log
|
||||
tail -f logs/cron_clean.log
|
||||
```
|
||||
|
||||
### Tester manuellement
|
||||
|
||||
```bash
|
||||
# Exécuter un backup immédiatement
|
||||
docker-compose exec backup-cron /bin/bash -c "cd /project && bash scripts/backup.sh"
|
||||
|
||||
# Vérifier l'heure du container
|
||||
docker-compose exec backup-cron date
|
||||
```
|
||||
|
||||
## Personnalisation
|
||||
|
||||
### Modifier le planning
|
||||
|
||||
Éditez `cron/crontab` puis reconstruisez:
|
||||
|
||||
```bash
|
||||
# Format cron: minute hour day month weekday command
|
||||
# Exemple: backup toutes les 6 heures
|
||||
0 */6 * * * cd /project && bash scripts/backup.sh >> /logs/cron_backup.log 2>&1
|
||||
|
||||
# Reconstruire
|
||||
docker-compose up -d --build backup-cron
|
||||
```
|
||||
|
||||
### Changer le fuseau horaire
|
||||
|
||||
Modifiez `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- TZ=America/New_York # ou autre fuseau
|
||||
```
|
||||
|
||||
## Sécurité
|
||||
|
||||
⚠️ **Important**: Le container a accès au socket Docker (`/var/run/docker.sock`), ce qui lui permet d'exécuter des commandes docker-compose. Cela est nécessaire pour les backups mais donne des privilèges élevés.
|
||||
|
||||
**Bonnes pratiques**:
|
||||
- N'exposez pas ce service sur le réseau externe
|
||||
- Gardez les scripts de backup en lecture seule si possible
|
||||
- Surveillez les logs régulièrement
|
||||
- Limitez les ressources du container si nécessaire
|
||||
|
||||
## Dépannage
|
||||
|
||||
### Le container ne démarre pas
|
||||
|
||||
```bash
|
||||
# Vérifier les logs
|
||||
docker-compose logs backup-cron
|
||||
|
||||
# Reconstruire from scratch
|
||||
docker-compose build --no-cache backup-cron
|
||||
docker-compose up -d backup-cron
|
||||
```
|
||||
|
||||
### Les tâches ne s'exécutent pas
|
||||
|
||||
```bash
|
||||
# Vérifier que crond tourne
|
||||
docker-compose exec backup-cron ps aux | grep crond
|
||||
|
||||
# Vérifier le crontab
|
||||
docker-compose exec backup-cron cat /etc/crontabs/root
|
||||
|
||||
# Vérifier l'heure du container
|
||||
docker-compose exec backup-cron date
|
||||
```
|
||||
|
||||
### Problèmes de permissions
|
||||
|
||||
```bash
|
||||
# Le container doit pouvoir écrire dans ./backups et ./logs
|
||||
chmod 755 backups logs
|
||||
|
||||
# Vérifier les montages
|
||||
docker-compose exec backup-cron ls -la /project/backups
|
||||
```
|
||||
|
||||
## Logs
|
||||
|
||||
Tous les logs sont stockés dans `./logs/`:
|
||||
|
||||
- `cron_backup.log`: Sorties des backups quotidiens
|
||||
- `cron_health.log`: Résultats des health checks
|
||||
- `cron_clean.log`: Logs de nettoyage hebdomadaire
|
||||
|
||||
Les logs sont automatiquement nettoyés après 30 jours.
|
||||
11
cron/crontab
Normal file
11
cron/crontab
Normal file
@@ -0,0 +1,11 @@
|
||||
# Nextcloud Docker - Tâches automatisées
|
||||
# Format: minute hour day month weekday command
|
||||
|
||||
# Backup quotidien à 5h00 du matin (heure de Paris)
|
||||
0 5 * * * cd /project && bash scripts/backup.sh >> /logs/cron_backup.log 2>&1
|
||||
|
||||
# Health check quotidien à 6h00 (après le backup)
|
||||
0 6 * * * cd /project && bash scripts/check-health.sh >> /logs/cron_health.log 2>&1
|
||||
|
||||
# Nettoyage hebdomadaire le dimanche à 3h00
|
||||
0 3 * * 0 cd /project && bash scripts/clean-old-logs.sh >> /logs/cron_clean.log 2>&1
|
||||
18
cron/entrypoint.sh
Executable file
18
cron/entrypoint.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "========================================="
|
||||
echo "Nextcloud Backup Cron Container"
|
||||
echo "========================================="
|
||||
echo "Fuseau horaire: ${TZ:-UTC}"
|
||||
echo "Heure actuelle: $(date)"
|
||||
echo ""
|
||||
echo "Tâches programmées:"
|
||||
cat /etc/crontabs/root | grep -v "^#" | grep -v "^$"
|
||||
echo ""
|
||||
echo "Logs disponibles dans /logs/"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Démarrer crond en mode foreground
|
||||
exec crond -f -l 2
|
||||
@@ -13,3 +13,6 @@ binlog_format = ROW
|
||||
|
||||
# Connections
|
||||
max_connections = 200
|
||||
|
||||
# Gros fichiers - augmenter la taille max des paquets
|
||||
max_allowed_packet = 1G
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
services:
|
||||
nextcloud:
|
||||
image: nextcloud:latest
|
||||
build: .
|
||||
image: nextcloud-custom:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:8888:80"
|
||||
volumes:
|
||||
- ./data:/var/www/html
|
||||
- ./apache/nextcloud.conf:/etc/apache2/conf-enabled/nextcloud.conf:ro
|
||||
- ./apache/mpm_prefork.conf:/etc/apache2/mods-available/mpm_prefork.conf:ro
|
||||
- ./logs/apache:/var/log/apache2
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
tag: "nextcloud"
|
||||
environment:
|
||||
# Database
|
||||
- MYSQL_HOST=db
|
||||
@@ -23,12 +33,16 @@ services:
|
||||
- REDIS_HOST_PASSWORD=${REDIS_HOST_PASSWORD}
|
||||
# PHP
|
||||
- PHP_MEMORY_LIMIT=4096M
|
||||
- PHP_UPLOAD_MAX_FILESIZE=2G
|
||||
- PHP_POST_MAX_SIZE=2G
|
||||
- PHP_MAX_EXECUTION_TIME=1800
|
||||
- PHP_MAX_INPUT_TIME=1800
|
||||
- PHP_UPLOAD_MAX_FILESIZE=10G
|
||||
- PHP_POST_MAX_SIZE=10G
|
||||
- PHP_MAX_EXECUTION_TIME=7200
|
||||
- PHP_MAX_INPUT_TIME=7200
|
||||
# - PHP_UPLOAD_MAX_FILESIZE=1024G
|
||||
# - PHP_POST_MAX_SIZE=1024G
|
||||
# - PHP_MAX_EXECUTION_TIME=86400
|
||||
# - PHP_MAX_INPUT_TIME=86400
|
||||
# Apache
|
||||
- APACHE_BODY_LIMIT=2147483648
|
||||
- APACHE_BODY_LIMIT=0
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/status.php"]
|
||||
interval: 30s
|
||||
@@ -42,16 +56,32 @@ services:
|
||||
networks:
|
||||
- nextcloud-net
|
||||
- traefik-net
|
||||
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# Router configuration
|
||||
- "traefik.http.routers.cloud.rule=Host(`${NEXTCLOUD_DOMAIN}`)"
|
||||
- "traefik.http.routers.cloud.entrypoints=websecure"
|
||||
- "traefik.http.routers.cloud.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.routers.cloud.middlewares=nextcloud-headers,nextcloud-redirect"
|
||||
# Service configuration
|
||||
- "traefik.http.services.cloud.loadbalancer.server.port=80"
|
||||
- "traefik.http.services.cloud.loadbalancer.serverstransport=nextcloud-transport"
|
||||
# Middleware: Headers
|
||||
- "traefik.http.middlewares.nextcloud-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||
- "traefik.http.middlewares.nextcloud-headers.headers.customresponseheaders.Strict-Transport-Security=max-age=15552000"
|
||||
# Middleware: Redirect pour CalDAV/CardDAV
|
||||
- "traefik.http.middlewares.nextcloud-redirect.redirectregex.regex=https://(.*)/.well-known/(card|cal)dav"
|
||||
- "traefik.http.middlewares.nextcloud-redirect.redirectregex.replacement=https://$$1/remote.php/dav/"
|
||||
- "traefik.http.middlewares.nextcloud-redirect.redirectregex.permanent=true"
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: unless-stopped
|
||||
command: redis-server --requirepass ${REDIS_HOST_PASSWORD} --maxmemory 512mb --maxmemory-policy allkeys-lru
|
||||
command: redis-server --requirepass ${REDIS_HOST_PASSWORD} --maxmemory 2gb --maxmemory-policy allkeys-lru
|
||||
networks:
|
||||
- nextcloud-net
|
||||
|
||||
cron:
|
||||
image: nextcloud:latest
|
||||
image: nextcloud-custom:latest
|
||||
restart: always
|
||||
volumes_from:
|
||||
- nextcloud
|
||||
@@ -63,6 +93,28 @@ services:
|
||||
networks:
|
||||
- nextcloud-net
|
||||
|
||||
backup-cron:
|
||||
build: ./cron
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
# Monter le projet complet pour accéder aux scripts
|
||||
- .:/project
|
||||
# Monter Docker socket pour exécuter les commandes docker-compose
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
# Partager les volumes avec nextcloud pour les backups
|
||||
- ./data:/var/www/html
|
||||
- ./db:/var/lib/mysql
|
||||
- ./backups:/project/backups
|
||||
- ./logs:/logs
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- COMPOSE_PROJECT_NAME
|
||||
depends_on:
|
||||
- nextcloud
|
||||
- db
|
||||
networks:
|
||||
- nextcloud-net
|
||||
|
||||
db:
|
||||
image: mariadb:10.11
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -8,46 +8,48 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
LOCK_FILE="/tmp/nextcloud_backup.lock"
|
||||
LOG_DIR="./logs"
|
||||
LOG_FILE="$LOG_DIR/backup_$(date +%Y%m%d_%H%M%S).log"
|
||||
MAINTENANCE_ENABLED=false
|
||||
|
||||
# Créer le dossier de logs
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Fonction de logging
|
||||
log() {
|
||||
local level="$1"
|
||||
shift
|
||||
local message="$*"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Charger les variables d'environnement
|
||||
# Charger .env en premier
|
||||
if [ ! -f .env ]; then
|
||||
log "ERROR" "Fichier .env introuvable"
|
||||
echo "ERROR: Fichier .env introuvable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Charger .env de manière sécurisée
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source .env
|
||||
set +a
|
||||
|
||||
# Vérifier les variables requises
|
||||
: "${MYSQL_USER:?Variable MYSQL_USER non définie}"
|
||||
: "${MYSQL_PASSWORD:?Variable MYSQL_PASSWORD non définie}"
|
||||
: "${MYSQL_DATABASE:?Variable MYSQL_DATABASE non définie}"
|
||||
|
||||
# Configuration
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
LOCK_FILE="/tmp/nextcloud_backup.lock"
|
||||
LOG_DIR="./logs"
|
||||
LOG_FILE="$PROJECT_ROOT/logs/backup_$(date +%Y%m%d_%H%M%S).log"
|
||||
BACKUP_DIR="${BACKUP_DESTINATION:-./backups}"
|
||||
BACKUP_RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-7}"
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
BACKUP_NAME="nextcloud_backup_$DATE"
|
||||
BACKUP_PATH="$BACKUP_DIR/$BACKUP_NAME"
|
||||
MAINTENANCE_ENABLED=false
|
||||
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Charger les fonctions communes (log avec couleurs)
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
if [ -z "${MYSQL_DATABASE:-}" ] || [ -z "${MYSQL_USER:-}" ] || [ -z "${MYSQL_PASSWORD:-}" ]; then
|
||||
log "ERROR" "Variables MysqlSQL non définies dans .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier qu'un backup n'est pas déjà en cours
|
||||
if [ -f "$LOCK_FILE" ]; then
|
||||
log "ERROR" "Une sauvegarde est déjà en cours. Si aucune sauvegarde n'est en cours, supprimez le fichier: $LOCK_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
touch "$LOCK_FILE"
|
||||
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Fonction de nettoyage en cas d'erreur
|
||||
cleanup() {
|
||||
@@ -83,27 +85,56 @@ cleanup() {
|
||||
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
# Vérifier qu'un backup n'est pas déjà en cours
|
||||
if [ -f "$LOCK_FILE" ]; then
|
||||
log "ERROR" "Un backup est déjà en cours (lock file: $LOCK_FILE)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Créer le lock file
|
||||
echo $$ > "$LOCK_FILE"
|
||||
|
||||
log "INFO" "=== Démarrage du backup: $BACKUP_NAME ==="
|
||||
log "INFO" "Log file: $LOG_FILE"
|
||||
|
||||
# Vérifier l'espace disque disponible
|
||||
log "INFO" "Vérification de l'espace disque..."
|
||||
REQUIRED_SPACE=$(du -sb ./data ./db 2>/dev/null | awk '{sum+=$1} END {print int(sum*1.2)}' || echo "0")
|
||||
AVAILABLE_SPACE=$(df -B1 "$BACKUP_DIR" | awk 'NR==2 {print $4}')
|
||||
|
||||
log "INFO" "Espace requis (estimé): $(numfmt --to=iec-i --suffix=B "$REQUIRED_SPACE" 2>/dev/null || echo "$REQUIRED_SPACE bytes")"
|
||||
# Calculer l'espace requis (taille data + db avec 20% de marge)
|
||||
# Calculer depuis le container avec les mêmes exclusions que le backup
|
||||
log "INFO" "Calcul de la taille réelle (avec exclusions)..."
|
||||
DATA_SIZE=$(docker-compose exec -T nextcloud du -sb \
|
||||
--exclude='appdata_*/preview' \
|
||||
--exclude='*/cache' \
|
||||
--exclude='*/thumbnails' \
|
||||
/var/www/html/data 2>/dev/null | awk '{print $1}' || echo "0")
|
||||
|
||||
# Note: On n'inclut pas la DB car mysqldump est beaucoup plus petit que les fichiers MySQL bruts
|
||||
# Typiquement: fichiers MySQL = 650MB → dump SQL = 500KB (compression ~99%)
|
||||
# On ajoute juste 10MB fixe pour DB + config + apps (généralement < 1MB au final)
|
||||
DB_ESTIMATE=10485760 # 10MB
|
||||
|
||||
# Additionner avec 20% de marge
|
||||
REQUIRED_SPACE=$(echo "$DATA_SIZE + $DB_ESTIMATE" | awk '{total=$1+$3; print int(total*1.2)}')
|
||||
|
||||
if [ -z "$REQUIRED_SPACE" ] || [ "$REQUIRED_SPACE" = "0" ]; then
|
||||
log "WARN" "Impossible de calculer l'espace requis, estimation à 500MB"
|
||||
REQUIRED_SPACE=500000000 # 500MB par défaut (plus réaliste que 2GB)
|
||||
fi
|
||||
|
||||
# Obtenir l'espace disponible (enlever les espaces/newlines)
|
||||
# Utiliser -P pour format POSIX (garantit une ligne par système de fichiers)
|
||||
AVAILABLE_SPACE=$(df -P -B1 "$BACKUP_DIR" | awk 'NR==2 {print $4}' | tr -d '[:space:]')
|
||||
if [ -z "$AVAILABLE_SPACE" ]; then
|
||||
log "ERROR" "Impossible de déterminer l'espace disque disponible"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Calculer estimation avec compression
|
||||
# Note: Nextcloud a beaucoup de fichiers déjà compressés (images, PDFs)
|
||||
# donc la compression gzip est peu efficace (~30% au lieu de 90%)
|
||||
if [ "$REQUIRED_SPACE" -gt 0 ] 2>/dev/null; then
|
||||
ESTIMATED_COMPRESSED=$((REQUIRED_SPACE * 7 / 10)) # 70% de la taille (30% de compression)
|
||||
log "INFO" "Espace requis (non compressé + 20%): $(numfmt --to=iec-i --suffix=B "$REQUIRED_SPACE" 2>/dev/null || echo "$REQUIRED_SPACE bytes")"
|
||||
log "INFO" "Espace estimé après compression: $(numfmt --to=iec-i --suffix=B "$ESTIMATED_COMPRESSED" 2>/dev/null || echo "$ESTIMATED_COMPRESSED bytes")"
|
||||
else
|
||||
log "INFO" "Espace requis: Impossible à calculer (utilisation du fallback)"
|
||||
fi
|
||||
log "INFO" "Espace disponible: $(numfmt --to=iec-i --suffix=B "$AVAILABLE_SPACE" 2>/dev/null || echo "$AVAILABLE_SPACE bytes")"
|
||||
|
||||
if [ "$AVAILABLE_SPACE" -lt "$REQUIRED_SPACE" ]; then
|
||||
# Comparaison sécurisée avec validation
|
||||
if [ "$AVAILABLE_SPACE" -lt "$REQUIRED_SPACE" ] 2>/dev/null; then
|
||||
log "ERROR" "Espace disque insuffisant"
|
||||
exit 1
|
||||
fi
|
||||
@@ -135,18 +166,18 @@ if ! docker-compose exec -T db sh -c "MYSQL_PWD=\"\$MYSQL_PASSWORD\" mysqldump \
|
||||
fi
|
||||
END_TIME=$(date +%s)
|
||||
DB_SIZE=$(du -h "$BACKUP_PATH/database.sql" | cut -f1)
|
||||
log "INFO" "Base de données sauvegardée: $DB_SIZE ($(( END_TIME - START_TIME ))s)"
|
||||
log "INFO" "Base de données sauvegardée: $DB_SIZE ($((END_TIME - START_TIME))s)"
|
||||
|
||||
# 3. Backup des fichiers de config
|
||||
log "INFO" "Backup de la configuration..."
|
||||
START_TIME=$(date +%s)
|
||||
if ! docker-compose exec -T -u www-data nextcloud tar -czf - -C /var/www/html/config . > "$BACKUP_PATH/config.tar.gz" 2>>"$LOG_FILE"; then
|
||||
if ! docker-compose exec -T -u www-data nextcloud tar -czf - -C /var/www/html/config . >"$BACKUP_PATH/config.tar.gz" 2>>"$LOG_FILE"; then
|
||||
log "ERROR" "Erreur lors du backup de la configuration"
|
||||
exit 1
|
||||
fi
|
||||
END_TIME=$(date +%s)
|
||||
CONFIG_SIZE=$(du -h "$BACKUP_PATH/config.tar.gz" | cut -f1)
|
||||
log "INFO" "Configuration sauvegardée: $CONFIG_SIZE ($(( END_TIME - START_TIME ))s)"
|
||||
log "INFO" "Configuration sauvegardée: $CONFIG_SIZE ($((END_TIME - START_TIME))s)"
|
||||
|
||||
# 4. Backup des données utilisateurs
|
||||
log "INFO" "Backup des données utilisateurs..."
|
||||
@@ -156,19 +187,19 @@ if ! docker-compose exec -T -u www-data nextcloud tar -czf - \
|
||||
--exclude='appdata_*/preview' \
|
||||
--exclude='*/cache' \
|
||||
--exclude='*/thumbnails' \
|
||||
. > "$BACKUP_PATH/data.tar.gz" 2>>"$LOG_FILE"; then
|
||||
. >"$BACKUP_PATH/data.tar.gz" 2>>"$LOG_FILE"; then
|
||||
log "ERROR" "Erreur lors du backup des données"
|
||||
exit 1
|
||||
fi
|
||||
END_TIME=$(date +%s)
|
||||
DATA_SIZE=$(du -h "$BACKUP_PATH/data.tar.gz" | cut -f1)
|
||||
log "INFO" "Données sauvegardées: $DATA_SIZE ($(( END_TIME - START_TIME ))s)"
|
||||
log "INFO" "Données sauvegardées: $DATA_SIZE ($((END_TIME - START_TIME))s)"
|
||||
|
||||
# 5. Backup des apps personnalisées
|
||||
log "INFO" "Backup des apps personnalisées..."
|
||||
if docker-compose exec -T nextcloud [ -d /var/www/html/custom_apps ] 2>>"$LOG_FILE"; then
|
||||
if docker-compose exec -T -u www-data nextcloud tar -czf - \
|
||||
-C /var/www/html/custom_apps . > "$BACKUP_PATH/apps.tar.gz" 2>>"$LOG_FILE"; then
|
||||
-C /var/www/html/custom_apps . >"$BACKUP_PATH/apps.tar.gz" 2>>"$LOG_FILE"; then
|
||||
APPS_SIZE=$(du -h "$BACKUP_PATH/apps.tar.gz" | cut -f1)
|
||||
log "INFO" "Apps sauvegardées: $APPS_SIZE"
|
||||
else
|
||||
@@ -196,14 +227,13 @@ if ! tar -czf "$BACKUP_DIR/$BACKUP_NAME.tar.gz" -C "$BACKUP_DIR" "$BACKUP_NAME/"
|
||||
fi
|
||||
END_TIME=$(date +%s)
|
||||
ARCHIVE_SIZE=$(du -h "$BACKUP_DIR/$BACKUP_NAME.tar.gz" | cut -f1)
|
||||
log "INFO" "Archive créée: $ARCHIVE_SIZE ($(( END_TIME - START_TIME ))s)"
|
||||
log "INFO" "Archive créée: $ARCHIVE_SIZE ($((END_TIME - START_TIME))s)"
|
||||
|
||||
# 8. Générer le checksum SHA256
|
||||
log "INFO" "Génération du checksum SHA256..."
|
||||
if cd "$BACKUP_DIR" && sha256sum "$BACKUP_NAME.tar.gz" > "$BACKUP_NAME.tar.gz.sha256"; then
|
||||
if cd "$BACKUP_DIR" && sha256sum "$BACKUP_NAME.tar.gz" >"$BACKUP_NAME.tar.gz.sha256"; then
|
||||
cd "$PROJECT_ROOT"
|
||||
CHECKSUM=$(cut -d' ' -f1 "$BACKUP_DIR/$BACKUP_NAME.tar.gz.sha256")
|
||||
log "INFO" "Checksum: $CHECKSUM"
|
||||
else
|
||||
cd "$PROJECT_ROOT"
|
||||
log "WARN" "Impossible de générer le checksum"
|
||||
|
||||
@@ -8,11 +8,17 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Couleurs pour l'output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
# Charger .env pour accéder aux variables (Redis password, etc.)
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Charger les couleurs depuis common.sh
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
# Compteurs
|
||||
CHECKS_PASSED=0
|
||||
@@ -133,18 +139,11 @@ echo "▶ Base de données:"
|
||||
if docker-compose exec -T db mysqladmin ping -h localhost --silent 2>/dev/null; then
|
||||
check_ok "MariaDB répond"
|
||||
|
||||
# Charger .env pour tester la connexion
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source .env
|
||||
set +a
|
||||
|
||||
if docker-compose exec -T db sh -c "MYSQL_PWD=\"\$MYSQL_PASSWORD\" mysql -u\"\$MYSQL_USER\" -e 'SELECT 1' >/dev/null 2>&1"; then
|
||||
check_ok "Connexion MySQL fonctionnelle"
|
||||
else
|
||||
check_fail "Impossible de se connecter à MySQL"
|
||||
fi
|
||||
# Tester la connexion MySQL (utilise les variables d'environnement du container)
|
||||
if docker-compose exec -T db sh -c 'MYSQL_PWD="$MYSQL_PASSWORD" mysql -u"$MYSQL_USER" "$MYSQL_DATABASE" -e "SELECT 1"' >/dev/null 2>&1; then
|
||||
check_ok "Connexion MySQL fonctionnelle"
|
||||
else
|
||||
check_fail "Impossible de se connecter à MySQL"
|
||||
fi
|
||||
else
|
||||
check_fail "MariaDB ne répond pas"
|
||||
@@ -154,10 +153,18 @@ echo ""
|
||||
|
||||
# 6. Vérifier Redis
|
||||
echo "▶ Cache Redis:"
|
||||
if docker-compose exec -T redis redis-cli ping 2>/dev/null | grep -q "PONG"; then
|
||||
check_ok "Redis répond"
|
||||
if [ -n "${REDIS_HOST_PASSWORD:-}" ]; then
|
||||
if docker-compose exec -T redis redis-cli -a "$REDIS_HOST_PASSWORD" ping 2>/dev/null | grep -q "PONG"; then
|
||||
check_ok "Redis répond (avec authentification)"
|
||||
else
|
||||
check_fail "Redis ne répond pas ou mot de passe incorrect"
|
||||
fi
|
||||
else
|
||||
check_fail "Redis ne répond pas"
|
||||
if docker-compose exec -T redis redis-cli ping 2>/dev/null | grep -q "PONG"; then
|
||||
check_ok "Redis répond (sans authentification)"
|
||||
else
|
||||
check_fail "Redis ne répond pas"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
@@ -175,14 +182,20 @@ else
|
||||
check_fail "Utilisation disque: ${DISK_USAGE}% (${DISK_AVAIL} disponible) - CRITIQUE"
|
||||
fi
|
||||
|
||||
# Vérifier la taille des données
|
||||
if [ -d ./data ]; then
|
||||
DATA_SIZE=$(du -sh ./data 2>/dev/null | cut -f1 || echo "N/A")
|
||||
check_ok "Taille des données: $DATA_SIZE"
|
||||
# Vérifier la taille des données utilisateurs
|
||||
if [ -d ./data/data ]; then
|
||||
DATA_SIZE=$(du -sh ./data/data 2>/dev/null | cut -f1 || echo "")
|
||||
if [ -z "$DATA_SIZE" ]; then
|
||||
DATA_SIZE="N/A"
|
||||
fi
|
||||
check_ok "Taille des données utilisateurs: $DATA_SIZE"
|
||||
fi
|
||||
|
||||
if [ -d ./db ]; then
|
||||
DB_SIZE=$(du -sh ./db 2>/dev/null | cut -f1 || echo "N/A")
|
||||
DB_SIZE=$(du -sh ./db 2>/dev/null | cut -f1 || echo "")
|
||||
if [ -z "$DB_SIZE" ]; then
|
||||
DB_SIZE="N/A"
|
||||
fi
|
||||
check_ok "Taille de la base: $DB_SIZE"
|
||||
fi
|
||||
|
||||
@@ -234,7 +247,10 @@ if [ -d ./logs ]; then
|
||||
LOG_COUNT=$(find ./logs -type f 2>/dev/null | wc -l)
|
||||
check_ok "$LOG_COUNT fichier(s) de log"
|
||||
|
||||
LOGS_SIZE=$(du -sh ./logs 2>/dev/null | cut -f1 || echo "N/A")
|
||||
LOGS_SIZE=$(du -sh ./logs 2>/dev/null | cut -f1 || echo "")
|
||||
if [ -z "$LOGS_SIZE" ]; then
|
||||
LOGS_SIZE="N/A"
|
||||
fi
|
||||
check_ok "Taille des logs: $LOGS_SIZE"
|
||||
else
|
||||
check_warn "Dossier de logs introuvable"
|
||||
|
||||
26
scripts/clean-old-logs.sh
Executable file
26
scripts/clean-old-logs.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
# scripts/clean-old-logs.sh - Nettoyage automatique des vieux logs
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
LOG_DIR="./logs"
|
||||
RETENTION_DAYS=30
|
||||
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Nettoyage des logs > ${RETENTION_DAYS} jours..."
|
||||
|
||||
# Compter les fichiers avant nettoyage
|
||||
BEFORE=$(find "$LOG_DIR" -type f -name "*.log" 2>/dev/null | wc -l)
|
||||
|
||||
# Supprimer les logs plus vieux que RETENTION_DAYS jours
|
||||
DELETED=$(find "$LOG_DIR" -type f -name "*.log" -mtime +${RETENTION_DAYS} -delete -print 2>/dev/null | wc -l)
|
||||
|
||||
# Compter les fichiers après nettoyage
|
||||
AFTER=$(find "$LOG_DIR" -type f -name "*.log" 2>/dev/null | wc -l)
|
||||
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Fichiers supprimés: $DELETED"
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Fichiers restants: $AFTER"
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Nettoyage terminé"
|
||||
33
scripts/common.sh
Normal file
33
scripts/common.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
# scripts/common.sh - Fonctions communes à tous les scripts
|
||||
|
||||
# Couleurs
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Fonction de logging
|
||||
log() {
|
||||
local level="$1"
|
||||
shift
|
||||
local message="$*"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
local color=""
|
||||
case "$level" in
|
||||
ERROR) color="${RED}" ;;
|
||||
WARN) color="${YELLOW}" ;;
|
||||
SUCCESS) color="${GREEN}" ;;
|
||||
INFO) color="" ;;
|
||||
esac
|
||||
|
||||
echo "[$timestamp] [$level] $message" >>"${LOG_FILE:-/tmp/script.log}"
|
||||
|
||||
if [ -t 1 ]; then
|
||||
echo -e "${color}[$timestamp] [$level] $message${NC}"
|
||||
else
|
||||
echo "[$timestamp] [$level] $message"
|
||||
fi
|
||||
}
|
||||
@@ -8,21 +8,15 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Configuration des logs
|
||||
LOG_DIR="./logs"
|
||||
LOG_FILE="$LOG_DIR/recover_$(date +%Y%m%d_%H%M%S).log"
|
||||
LOG_FILE="$PROJECT_ROOT/logs/recover_$(date +%Y%m%d_%H%M%S).log"
|
||||
|
||||
# Créer le dossier de logs
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Fonction de logging
|
||||
log() {
|
||||
local level="$1"
|
||||
shift
|
||||
local message="$*"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
|
||||
}
|
||||
# Charger les fonctions communes (log avec couleurs)
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
log "INFO" "=== Script de récupération Nextcloud ==="
|
||||
log "INFO" "Log file: $LOG_FILE"
|
||||
|
||||
@@ -8,39 +8,33 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
LOG_DIR="./logs"
|
||||
LOG_FILE="$LOG_DIR/restore_$(date +%Y%m%d_%H%M%S).log"
|
||||
TEMP_DIR=""
|
||||
|
||||
# Créer le dossier de logs
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Fonction de logging
|
||||
log() {
|
||||
local level="$1"
|
||||
shift
|
||||
local message="$*"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Charger les variables d'environnement
|
||||
# Charger .env en premier
|
||||
if [ ! -f .env ]; then
|
||||
log "ERROR" "Fichier .env introuvable"
|
||||
echo "ERROR: Fichier .env introuvable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Charger .env de manière sécurisée
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source .env
|
||||
set +a
|
||||
|
||||
# Configuration des logs
|
||||
LOG_DIR="./logs"
|
||||
LOG_FILE="$PROJECT_ROOT/logs/restore_$(date +%Y%m%d_%H%M%S).log"
|
||||
TEMP_DIR=""
|
||||
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Charger les fonctions communes (log avec couleurs)
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
# Vérifier les variables requises
|
||||
: "${MYSQL_USER:?Variable MYSQL_USER non définie}"
|
||||
: "${MYSQL_PASSWORD:?Variable MYSQL_PASSWORD non définie}"
|
||||
: "${MYSQL_DATABASE:?Variable MYSQL_DATABASE non définie}"
|
||||
if [ -z "${MYSQL_USER:-}" ] || [ -z "${MYSQL_PASSWORD:-}" ] || [ -z "${MYSQL_DATABASE:-}" ]; then
|
||||
log "ERROR" "Variables MySQL non définies dans .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier les arguments
|
||||
if [ -z "${1:-}" ]; then
|
||||
|
||||
@@ -8,23 +8,17 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Configuration des logs
|
||||
LOG_DIR="./logs"
|
||||
LOG_FILE="$LOG_DIR/update_$(date +%Y%m%d_%H%M%S).log"
|
||||
LOG_FILE="$PROJECT_ROOT/logs/update_$(date +%Y%m%d_%H%M%S).log"
|
||||
MAINTENANCE_ENABLED=false
|
||||
COMPOSE_BACKUP=""
|
||||
|
||||
# Créer le dossier de logs
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Fonction de logging
|
||||
log() {
|
||||
local level="$1"
|
||||
shift
|
||||
local message="$*"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
|
||||
}
|
||||
# Charger les fonctions communes (log avec couleurs)
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR/common.sh"
|
||||
|
||||
# Fonction de nettoyage en cas d'erreur
|
||||
cleanup() {
|
||||
@@ -86,10 +80,16 @@ cp docker-compose.yml "$COMPOSE_BACKUP" || {
|
||||
}
|
||||
log "INFO" "docker-compose.yml sauvegardé: $COMPOSE_BACKUP"
|
||||
|
||||
# Pull nouvelle image
|
||||
log "INFO" "Téléchargement de la nouvelle version..."
|
||||
if ! docker-compose pull nextcloud 2>&1 | tee -a "$LOG_FILE"; then
|
||||
log "ERROR" "Erreur lors du téléchargement de l'image"
|
||||
# Pull nouvelle image de base et rebuild image custom
|
||||
log "INFO" "Téléchargement de la nouvelle version de base..."
|
||||
if ! docker pull nextcloud:latest 2>&1 | tee -a "$LOG_FILE"; then
|
||||
log "ERROR" "Erreur lors du téléchargement de l'image de base"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "INFO" "Rebuild de l'image personnalisée (avec ffmpeg)..."
|
||||
if ! docker-compose build --no-cache nextcloud 2>&1 | tee -a "$LOG_FILE"; then
|
||||
log "ERROR" "Erreur lors du rebuild de l'image personnalisée"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user