From de21cbd4d26a999c160cf279b8892c85fdec82dc Mon Sep 17 00:00:00 2001 From: Nicolas Duhamel Date: Thu, 26 Jun 2025 17:54:08 +0200 Subject: [PATCH] WIP many change in logic for simplify --- README.md | 118 ------------------------------ backup/service-script-template.sh | 34 +++------ claude.md | 41 ++++++++--- install | 87 ++++++++++++++-------- manage | 13 ++-- services/paperless/backup.sh | 15 ++-- todo.md | 117 +++++++++++++++++++++++++++++ 7 files changed, 237 insertions(+), 188 deletions(-) delete mode 100644 README.md create mode 100644 todo.md diff --git a/README.md b/README.md deleted file mode 100644 index f148af4..0000000 --- a/README.md +++ /dev/null @@ -1,118 +0,0 @@ -# Citadel Backup System - -Système de sauvegarde automatisé basé sur Restic avec intégration systemd pour services containerisés. - -## Structure du Projet - -``` -citadel/ -├── backup.env # Configuration centralisée -├── manage # Interface principale de gestion -├── install # Script d'installation et configuration -├── config/ -│ └── restic.conf # Configuration Restic (générée) -└── backup/ - ├── install-service # Installation timers systemd - ├── list-snapshots # Liste des snapshots - ├── restore # Restauration - ├── service-backup@.service # Template service systemd - └── service-backup@.timer # Template timer systemd -``` - -## Installation - -1. **Configuration initiale** - ```bash - # Copier et adapter la configuration - cp backup.env.sample backup.env - # Éditer backup.env selon votre environnement - ``` - -2. **Installation complète** - ```bash - # Installation automatique (configuration + repository) - ./install - - # Ou étape par étape - ./install config # Génération configuration Restic - ./install repo # Initialisation repository - ``` - -3. **Installation d'un service** - ```bash - sudo ./manage install - ``` - -## Configuration - -### Variables principales (backup.env) - -- `BACKUP_USER` : Utilisateur système (défaut: citadel) -- `PROJECT_ROOT` : Racine du projet -- `SERVICES_BASE_DIR` : Répertoire des services à sauvegarder -- `BACKUP_REPOSITORY` : Chemin du repository Restic -- `DEFAULT_BACKUP_SCHEDULE` : Planning par défaut (défaut: *-*-* 03:00:00) - -### Personnalisation - -```bash -# Exemple pour un autre utilisateur -export BACKUP_USER="myuser" -export BACKUP_HOME="/home/myuser" -source backup.env - -# Puis utiliser normalement -./manage list -``` - -## Utilisation - -### Gestion des sauvegardes -```bash -# Lister les timers (configuration auto-sourcée) -./manage list - -# Statut d'un service -./manage status paperless - -# Lancer une sauvegarde manuelle -./manage run paperless - -# Voir les logs -./manage logs paperless - -# Services disponibles -./manage available -``` - -### Restauration -```bash -# Lister les snapshots -./manage snapshots paperless - -# Restaurer en mode test -./manage restore paperless - -# Restaurer en production -./manage restore-prod paperless -``` - -## Architecture - -### Principes de conception - -- **Interface unifiée** : Toutes les opérations via `./manage` et `./install` -- **Configuration auto-sourcée** : Plus besoin de sourcer manuellement -- **Scripts protégés** : Scripts dans `backup/` non exécutables directement -- **Sécurité** : Mots de passe générés automatiquement, permissions restreintes - -### Composants - -- **`./manage`** : Interface principale pour toutes les opérations de sauvegarde -- **`./install`** : Script d'installation consolidé (config + repository) -- **`backup.env`** : Configuration centralisée avec variables d'environnement -- **`backup/`** : Scripts internes appelés via `./manage` uniquement - -### Développement - -Les scripts dans `backup/` utilisent la variable `CALLED_FROM_MANAGE` pour empêcher l'exécution directe et garantir l'utilisation de l'interface unifiée. \ No newline at end of file diff --git a/backup/service-script-template.sh b/backup/service-script-template.sh index df644f6..576d458 100644 --- a/backup/service-script-template.sh +++ b/backup/service-script-template.sh @@ -4,36 +4,26 @@ # This template provides standardized configuration for all service scripts # Usage: Source this template at the beginning of service backup/restore scripts -# Auto-configure via backup.env -# Calculate PROJECT_ROOT based on where template is sourced from -# Template is in backup/, so from services/service_name/ we need to go ../../ -if [[ "${BASH_SOURCE[1]}" == */services/* ]]; then - # Sourced from a service script - PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[1]}")/../.." && pwd)" -else - # Sourced from backup/ directory or elsewhere - SCRIPT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - PROJECT_ROOT="$(cd "$SCRIPT_ROOT/.." && pwd)" -fi +# Auto-configure via backup.env from standard location +CONFIG_DIR="$HOME/.config/citadel" +CONFIG_FILE="$CONFIG_DIR/backup.env" -# Source centralized configuration -if [ -f "$PROJECT_ROOT/backup.env" ]; then - source "$PROJECT_ROOT/backup.env" +if [ -f "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" else - echo "ERROR: Configuration file backup.env not found in $PROJECT_ROOT" >&2 - echo "Please ensure backup.env exists in project root directory" >&2 + echo "ERROR: Configuration not found at $CONFIG_FILE" >&2 + echo "Please run './install setup' to initialize configuration" >&2 exit 1 fi # Variables universelles pour tout service (auto-dérivées) -# Detect service name from the script that sources this template -if [[ "${BASH_SOURCE[1]}" == */services/* ]]; then +# Use service name if set explicitly, otherwise detect from calling script +if [ -z "$SERVICE_NAME" ]; then + # BASH_SOURCE[1] is the script that sourced this template SERVICE_NAME="$(basename "$(dirname "${BASH_SOURCE[1]}")")" -else - SERVICE_NAME="$(basename "$(dirname "$0")")" fi SERVICE_DIR="$SERVICES_BASE_DIR/$SERVICE_NAME" -CONFIG_FILE="$RESTIC_CONFIG_FILE" +RESTIC_CONFIG_FILE="$CONFIG_DIR/restic.conf" LOG_FILE="$LOG_DIR/$SERVICE_NAME-backup.log" DATA_DIR="${DATA_DIR:-$(dirname "$SERVICES_BASE_DIR")/data/$SERVICE_NAME}" TEMP_BACKUP_DIR="$TEMP_DIR/$SERVICE_NAME-backup" @@ -96,7 +86,7 @@ cleanup_on_exit() { # Export commonly used variables export SERVICE_NAME export SERVICE_DIR -export CONFIG_FILE +export RESTIC_CONFIG_FILE export LOG_FILE export DATA_DIR export TEMP_BACKUP_DIR \ No newline at end of file diff --git a/claude.md b/claude.md index 2baa901..71de6d4 100644 --- a/claude.md +++ b/claude.md @@ -1,12 +1,35 @@ -#My name is Nicolas +# Claude Code Guidance - Citadel Project -This file provides guidance to Claude Code when working with this repository. +**Maintainer:** Nicolas -This is a pack of script named citadel for manage a self hosted server, for personnal usage. -IMPORTANT Keep things simple. Ne rajoute pas de fonctionnalitée non spécifiquement souhaité. Si tu penses qu'une nouvelle fonctionnalitée est fortement souhaitable demande moi avant. -Use shell script. -Ne prévoit pas de script ou documentation de migration sauf si demandé explicitement. +## Project Overview -I interact with you in french, you can anwser in french -IMPORTANT all code comment and documentation must be write in english -IMPORTANT do not analyse file mentioned in .gitignore +Citadel is a collection of shell scripts for managing a self-hosted server for personal usage. It provides automated backup management using Restic with systemd integration for containerized services. + +## Deployment Structure + +- **Development:** `/home/nicolas/dev/citadel` +- **Production:** `$HOME/citadel` (default user: "citadel") +- **Configuration:** `$HOME/.config/citadel` + +## Development Guidelines + +### Core Principles +- **Simplicity first:** Keep solutions minimal and focused +- **No unsolicited features:** Only implement specifically requested functionality +- **Ask before enhancing:** If a feature seems beneficial, ask before implementing +- **Shell scripts only:** Use bash/shell scripting as the primary technology +- **No migration scripts:** Unless explicitly requested + +### Code Standards +- **Comments & Documentation:** English only +- **Error handling:** Use consistent patterns across scripts +- **Security:** Follow secure coding practices, especially for password/secret handling +- **Integration:** Prefer using the centralized template system for new services + +### File Exclusions +- **Do not analyze:** Files listed in `.gitignore` + +## Communication +- **Interaction language:** French (Nicolas preference) +- **Code language:** English (comments, documentation, variable names) diff --git a/install b/install index 10f91d0..a50b550 100755 --- a/install +++ b/install @@ -8,13 +8,15 @@ set -e # Get the directory where this script is located (project root) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# Auto-source configuration -if [ -f "$SCRIPT_DIR/backup.env" ]; then - source "$SCRIPT_DIR/backup.env" +# Auto-source configuration from standard location +CONFIG_DIR="$HOME/.config/citadel" +CONFIG_FILE="$CONFIG_DIR/backup.env" + +if [ -f "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" else - echo "ERROR: Configuration file backup.env not found in $SCRIPT_DIR" - echo "Please ensure backup.env exists in project root directory" - exit 1 + echo "Configuration not found at $CONFIG_FILE" + echo "Will create configuration during setup..." fi show_help() { @@ -33,14 +35,34 @@ show_help() { } generate_config() { - local CONFIG_FILE="$RESTIC_CONFIG_FILE" + local RESTIC_CONFIG_FILE="$CONFIG_DIR/restic.conf" + local BACKUP_ENV_FILE="$CONFIG_DIR/backup.env" + + echo "=== Generating Citadel Configuration ===" + + # Create config directory + mkdir -p "$CONFIG_DIR" + + # Copy backup.env.sample if backup.env doesn't exist + if [ ! -f "$BACKUP_ENV_FILE" ]; then + if [ -f "$SCRIPT_DIR/backup.env.sample" ]; then + echo "Creating configuration from sample..." + cp "$SCRIPT_DIR/backup.env.sample" "$BACKUP_ENV_FILE" + echo "✅ Configuration created at $BACKUP_ENV_FILE" + echo "Please edit this file to match your environment" + else + echo "ERROR: backup.env.sample not found in $SCRIPT_DIR" + return 1 + fi + fi + + # Source the configuration to get variables + source "$BACKUP_ENV_FILE" local REPO_PATH="$BACKUP_REPOSITORY" - echo "=== Generating Restic Configuration ===" - - # Check if config already exists - if [ -f "$CONFIG_FILE" ]; then - echo "Configuration file already exists at $CONFIG_FILE" + # Check if restic config already exists + if [ -f "$RESTIC_CONFIG_FILE" ]; then + echo "Restic configuration already exists at $RESTIC_CONFIG_FILE" read -p "Do you want to overwrite it? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then @@ -49,16 +71,13 @@ generate_config() { fi fi - # Ensure config directory exists - mkdir -p "$(dirname "$CONFIG_FILE")" - # Generate secure password (32 characters) echo "Generating secure password..." local RESTIC_PASSWORD=$(openssl rand -base64 32) - # Create configuration file - echo "Creating configuration file..." - cat > "$CONFIG_FILE" << EOF + # Create restic configuration file + echo "Creating restic configuration file..." + cat > "$RESTIC_CONFIG_FILE" << EOF # Restic configuration for citadel backups # Generated on $(date) @@ -73,24 +92,34 @@ export RESTIC_CACHE_DIR="$RESTIC_CACHE_DIR" EOF # Set secure permissions - chmod 600 "$CONFIG_FILE" + chmod 600 "$RESTIC_CONFIG_FILE" - echo "✅ Configuration file created at $CONFIG_FILE" + echo "✅ Restic configuration file created at $RESTIC_CONFIG_FILE" echo "🔒 Password generated and saved securely" echo "" echo "⚠️ IMPORTANT: Save this password somewhere safe!" echo " If you lose it, you won't be able to restore your backups!" echo "" - echo "📁 Password saved in: $CONFIG_FILE" - echo " Use 'cat $CONFIG_FILE' to view the password if needed" + echo "📁 Password saved in: $RESTIC_CONFIG_FILE" + echo " Use 'cat $RESTIC_CONFIG_FILE' to view the password if needed" echo "" return 0 } initialize_repository() { + local RESTIC_CONFIG_FILE="$CONFIG_DIR/restic.conf" + + # Source backup.env to get repository path + if [ -f "$CONFIG_DIR/backup.env" ]; then + source "$CONFIG_DIR/backup.env" + else + echo "Error: backup.env not found at $CONFIG_DIR/backup.env" + echo "Please run '$0 config' first to create the configuration." + return 1 + fi + local REPO_PATH="$BACKUP_REPOSITORY" - local CONFIG_FILE="$RESTIC_CONFIG_FILE" echo "=== Initializing Restic Repository ===" @@ -101,15 +130,15 @@ initialize_repository() { sudo chown $(whoami):$(whoami) "$(dirname "$REPO_PATH")" fi - # Check if config file exists - if [ ! -f "$CONFIG_FILE" ]; then - echo "Error: Configuration file $CONFIG_FILE not found!" + # Check if restic config file exists + if [ ! -f "$RESTIC_CONFIG_FILE" ]; then + echo "Error: Restic configuration file $RESTIC_CONFIG_FILE not found!" echo "Please run '$0 config' first to create the configuration." return 1 fi - # Source the configuration - source "$CONFIG_FILE" + # Source the restic configuration + source "$RESTIC_CONFIG_FILE" # Check if repository is already initialized if restic -r "$REPO_PATH" cat config &>/dev/null; then @@ -125,7 +154,7 @@ initialize_repository() { if [ $? -eq 0 ]; then echo "✅ Repository successfully initialized!" echo "Repository path: $REPO_PATH" - echo "Configuration: $CONFIG_FILE" + echo "Configuration: $RESTIC_CONFIG_FILE" echo "" echo "=== Repository Information ===" restic -r "$REPO_PATH" stats diff --git a/manage b/manage index 1c0d512..6a38601 100755 --- a/manage +++ b/manage @@ -8,12 +8,15 @@ set -e # Get the directory where this script is located (project root) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# Auto-source configuration -if [ -f "$SCRIPT_DIR/backup.env" ]; then - source "$SCRIPT_DIR/backup.env" +# Auto-source configuration from standard location +CONFIG_DIR="$HOME/.config/citadel" +CONFIG_FILE="$CONFIG_DIR/backup.env" + +if [ -f "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" else - echo "ERROR: Configuration file backup.env not found in $SCRIPT_DIR" - echo "Please ensure backup.env exists in project root directory" + echo "ERROR: Configuration not found at $CONFIG_FILE" + echo "Please run './install setup' to initialize configuration" exit 1 fi diff --git a/services/paperless/backup.sh b/services/paperless/backup.sh index 72b497c..cdd42c7 100755 --- a/services/paperless/backup.sh +++ b/services/paperless/backup.sh @@ -6,7 +6,12 @@ set -e # Load template configuration -source "$(dirname "$(dirname "$(dirname "$0")")")/backup/service-script-template.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# Set service name explicitly for template +export SERVICE_NAME="paperless" +source "$PROJECT_ROOT/backup/service-script-template.sh" # Setup logging and cleanup setup_logging @@ -17,14 +22,14 @@ COMPOSE_FILE="$SERVICE_DIR/docker-compose.yml" log "=== Starting $SERVICE_NAME Backup ===" -# Check if configuration exists -if [ ! -f "$CONFIG_FILE" ]; then - error "Configuration file $CONFIG_FILE not found!" +# Check if restic configuration exists +if [ ! -f "$RESTIC_CONFIG_FILE" ]; then + error "Restic configuration file $RESTIC_CONFIG_FILE not found!" exit 1 fi # Source Restic configuration -source "$CONFIG_FILE" +source "$RESTIC_CONFIG_FILE" # Create temporary backup directory log "Creating temporary backup directory: $TEMP_BACKUP_DIR" diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..ae3b75a --- /dev/null +++ b/todo.md @@ -0,0 +1,117 @@ +# Plan de Migration vers $HOME/.config/citadel + +## Objectif +Migrer la configuration du projet vers `$HOME/.config/citadel` pour respecter les standards de configuration système et séparer clairement le code de la configuration en production. + +## Architecture Cible + +### Structure de configuration +``` +$HOME/.config/citadel/ +├── backup.env # Configuration principale (était à la racine) +├── restic.conf # Configuration Restic générée (était dans config/) +└── services/ # Configurations spécifiques par service (futures extensions) +``` + +### Fichiers sample conservés dans le projet +``` +backup.env.sample # Guide d'installation (reste à la racine) +config/restic.conf # Devient un exemple/template +``` + +## Plan d'action détaillé + +### Phase 1 : Modification du système de sourcing + +#### 1.1 Modifier `manage` +- **Fichier** : `manage` (lignes 12-18) +- **Action** : Remplacer le sourcing conditionnel par un chemin fixe +- **Nouveau code** : + ```bash + CONFIG_DIR="$HOME/.config/citadel" + CONFIG_FILE="$CONFIG_DIR/backup.env" + + if [ -f "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" + else + echo "ERROR: Configuration not found at $CONFIG_FILE" + echo "Please run './install setup' to initialize configuration" + exit 1 + fi + ``` + +#### 1.2 Modifier `install` +- **Fichier** : `install` (lignes 12-18) +- **Action** : Même modification que `manage` + création du répertoire config +- **Ajout** : Fonction de création/migration de la configuration +- **Nouveau comportement** : + - Créer `$HOME/.config/citadel/` si inexistant + - Copier `backup.env.sample` vers `$HOME/.config/citadel/backup.env` si absent + - Générer `restic.conf` dans le nouveau répertoire + +#### 1.3 Modifier `service-script-template.sh` +- **Fichier** : `backup/service-script-template.sh` (lignes 8-26) +- **Action** : Supprimer la détection automatique de PROJECT_ROOT +- **Nouveau code** : + ```bash + CONFIG_DIR="$HOME/.config/citadel" + CONFIG_FILE="$CONFIG_DIR/backup.env" + + if [ -f "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" + else + echo "ERROR: Configuration not found at $CONFIG_FILE" >&2 + exit 1 + fi + ``` + +### Phase 2 : Adaptation des variables de configuration + +#### 2.1 Modifier `backup.env.sample` +- **Action** : Mettre à jour les chemins par défaut +- **Variables à modifier** : + ```bash + # Nouveau chemin de configuration + RESTIC_CONFIG_FILE="${RESTIC_CONFIG_FILE:-$HOME/.config/citadel/restic.conf}" + + # PROJECT_ROOT devient optionnel (pour les templates systemd seulement) + PROJECT_ROOT="${PROJECT_ROOT:-/home/nicolas/dev/citadel}" + ``` + +#### 2.2 Modifier la génération de `restic.conf` +- **Fichier** : `install` (fonction `generate_config`) +- **Action** : Générer le fichier dans `$HOME/.config/citadel/restic.conf` +- **Chemin cible** : `$CONFIG_DIR/restic.conf` + +### Phase 3 : Tests et validation + +#### 3.1 Tests de non-régression +- `./manage list` fonctionne +- `./manage install ` fonctionne +- Scripts de backup sourcent correctement la configuration +- Installation initiale crée la structure correcte + +### Phase 4 : Documentation + +#### 4.1 Mettre à jour README.md +- Documenter le nouveau chemin de configuration +- Ajouter la procédure de setup initial + +#### 4.2 Messages d'erreur informatifs +- Guider l'utilisateur vers la bonne commande d'installation +- Indiquer clairement les chemins de configuration + +## Avantages de cette migration + +1. **Standard système** : Respect de la convention `$HOME/.config/` +2. **Séparation claire** : Code et configuration indépendants +3. **Sécurité** : Configuration hors du répertoire de développement +4. **Simplicité** : Plus de détection automatique hasardeuse +5. **Maintenance** : Configuration centralisée et prévisible + +## Risques identifiés et mitigations + +- **Risque** : Scripts cassés après migration + - **Mitigation** : Tests de non-régression complets +- **Risque** : Confusion utilisateur + - **Mitigation** : Messages d'erreur explicites et documentation claire \ No newline at end of file