Refactor: Unify interface with manage and install scripts at root

- Move backup/manage to root with auto-sourcing configuration
- Create consolidated ./install script (replaces gen-conf.sh + init-restic.sh)
- Add protection against direct execution of backup/ scripts
- Update documentation (README.md, CLAUDE.md) for new architecture
- Remove obsolete gen-conf.sh and init-restic.sh

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Nicolas Duhamel 2025-06-23 21:41:09 +02:00
parent f82a913bdd
commit 17414fee4a
9 changed files with 318 additions and 208 deletions

View File

@ -4,19 +4,23 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Critical Convention
**ALL scripts must be executed in an environment that has sourced the configuration:**
**Use the unified interface scripts that auto-source configuration:**
```bash
# Always start by sourcing configuration
source backup.env
# Installation and setup
./install # Complete setup (config + repository)
./install config # Generate configuration only
./install repo # Initialize repository only
# Then execute any script
./backup/manage list
./backup/gen-conf.sh
sudo ./backup/install-service paperless
# All backup operations via manage
./manage list # List backup timers
./manage install <service> # Install service timer
./manage run <service> # Manual backup
./manage restore <service> # Restore (test mode)
./manage restore-prod <service> # Restore (production)
```
This is the core architectural pattern of this codebase. Scripts do NOT auto-source configuration files.
**NEVER call scripts in backup/ directly** - they are protected and will error. Always use `./manage` or `./install`.
## Common Commands
@ -24,31 +28,29 @@ This is the core architectural pattern of this codebase. Scripts do NOT auto-sou
```bash
cp backup.env.sample backup.env # Copy configuration template
# Edit backup.env to match environment
source backup.env
./backup/gen-conf.sh # Generate secure Restic configuration
./backup/init-restic.sh # Initialize Restic repository
./install # Complete installation (config + repository)
```
### Service Management
```bash
source backup.env
./backup/manage list # List all backup timers
./backup/manage status <service> # Service backup status
./backup/manage run <service> # Manual backup execution
./backup/manage logs <service> # View backup logs
sudo ./backup/install-service <service> # Install systemd timer
./manage list # List all backup timers
./manage status <service> # Service backup status
./manage run <service> # Manual backup execution
./manage logs <service> # View backup logs
./manage available # List services with backup.sh
sudo ./manage install <service> # Install systemd timer
```
### Backup Operations
```bash
source backup.env
./backup/list-snapshots [service] # List available snapshots
./backup/restore <service> --test # Test restoration
./backup/restore <service> --production # Production restoration
./manage snapshots [service] # List available snapshots
./manage restore <service> # Test restoration
./manage restore-prod <service> # Production restoration
```
### Configuration Testing
```bash
# Source configuration manually for utility functions
source backup.env
show_config # Display current configuration
validate_paths # Check directory existence
@ -62,9 +64,10 @@ validate_paths # Check directory existence
- **Variable substitution**: systemd templates use `${VAR}` placeholders replaced during installation
### Core Components
- **`backup/manage`**: Primary interface for all backup operations and service management
- **`backup/install-service`**: Systemd timer installer that performs variable substitution in templates
- **`backup/restore`**: Advanced restoration tool with test/production modes and safety checks
- **`./manage`**: Primary interface for all backup operations and service management (auto-sources config)
- **`./install`**: Installation script consolidating configuration generation and repository initialization
- **`backup/install-service`**: Systemd timer installer (called via `./manage install`)
- **`backup/restore`**: Advanced restoration tool (called via `./manage restore/restore-prod`)
- **Templates**: `service-backup@.service` and `service-backup@.timer` are systemd unit templates
### Variable Override Pattern
@ -94,25 +97,36 @@ Users can customize by setting environment variables before sourcing `backup.env
- `config/restic.conf`: Generated Restic authentication and repository settings
### Operational Scripts
- `backup/manage`: Main interface (list, status, run, logs commands)
- `backup/gen-conf.sh`: Secure configuration generator
- `backup/init-restic.sh`: Repository initialization
- `./manage`: Main interface (list, status, run, logs commands) - auto-sources configuration
- `./install`: Consolidated installation script (config + repository)
- `backup/install-service`: Systemd timer installation with template substitution
- `backup/list-snapshots`: Snapshot browsing utility
- `backup/restore`: Production-grade restoration tool
### Templates and Restoration
- `backup/service-backup@.{service,timer}`: Systemd unit templates with variable placeholders
- `backup/restore`: Production-grade restoration with test mode and extensive validation
- `backup/list-snapshots`: Snapshot browsing utility
## Development Guidelines
When adding new scripts:
1. Add comment: `# Configuration should be sourced before running: source backup.env`
2. Use variables from `backup.env` directly (do not auto-source)
3. Follow the pattern of existing scripts for error handling and logging
4. For systemd integration, use template substitution pattern from `install-service`
### Script Protection
All scripts in `backup/` are protected against direct execution:
- Use `CALLED_FROM_MANAGE` environment variable check
- Scripts error with helpful message if called directly
- Always route through `./manage` interface
When modifying configuration:
### Adding New Scripts
1. If adding scripts to `backup/`, include protection check:
```bash
if [ "${CALLED_FROM_MANAGE:-}" != "true" ]; then
echo "ERROR: Use ./manage <command> instead"
exit 1
fi
```
2. Add corresponding command to `./manage` with `CALLED_FROM_MANAGE=true`
3. Follow existing error handling and logging patterns
### Configuration Changes
- All path variables should have environment override capability
- Maintain backward compatibility with default values
- Update both `backup.env` and this documentation if adding new variables
- Test with both `./manage` and `./install` interfaces

View File

@ -7,12 +7,11 @@ Système de sauvegarde automatisé basé sur Restic avec intégration systemd po
```
quantumrick/
├── 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/
├── manage # Interface principale de gestion
├── gen-conf.sh # Génération de configuration Restic
├── init-restic.sh # Initialisation repository
├── install-service # Installation timers systemd
├── list-snapshots # Liste des snapshots
├── restore # Restauration
@ -20,20 +19,6 @@ quantumrick/
└── service-backup@.timer # Template timer systemd
```
## Prérequis
**IMPORTANT:** Tous les scripts doivent être exécutés dans un environnement ayant sourcé la configuration :
```bash
# Toujours commencer par sourcer la configuration
source backup.env
# Puis exécuter les scripts
./backup/manage list
./backup/gen-conf.sh
./backup/init-restic.sh
```
## Installation
1. **Configuration initiale**
@ -41,22 +26,21 @@ source backup.env
# Copier et adapter la configuration
cp backup.env.sample backup.env
# Éditer backup.env selon votre environnement
# Puis générer la configuration Restic
source backup.env
./backup/gen-conf.sh
```
2. **Initialisation du repository**
2. **Installation complète**
```bash
source backup.env
./backup/init-restic.sh
# 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
source backup.env
sudo ./backup/install-service <nom_service>
sudo ./manage install <nom_service>
```
## Configuration
@ -78,55 +62,57 @@ export BACKUP_HOME="/home/myuser"
source backup.env
# Puis utiliser normalement
./backup/manage list
./manage list
```
## Utilisation
### Gestion des sauvegardes
```bash
source backup.env
# Lister les timers
./backup/manage list
# Lister les timers (configuration auto-sourcée)
./manage list
# Statut d'un service
./backup/manage status paperless
./manage status paperless
# Lancer une sauvegarde manuelle
./backup/manage run paperless
./manage run paperless
# Voir les logs
./backup/manage logs paperless
./manage logs paperless
# Services disponibles
./manage available
```
### Restauration
```bash
source backup.env
# Lister les snapshots
./backup/list-snapshots paperless
./manage snapshots paperless
# Restaurer en mode test
./backup/restore paperless --test
./manage restore paperless
# Restaurer en production
./backup/restore paperless --production
```
## Développement
Pour contribuer au projet, respectez la convention de sourcer `backup.env` dans tous vos scripts :
```bash
#!/bin/bash
# Source configuration (scripts doivent être dans backup/)
source "$(dirname "$(dirname "$0")")/backup.env"
./manage restore-prod paperless
```
## Architecture
- **Configuration centralisée** : `backup.env` contient toutes les variables
- **Scripts modulaires** : Chaque script a une responsabilité spécifique
- **Templates systemd** : Variables substituées à l'installation
- **Sécurité** : Mots de passe générés automatiquement
### 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.

View File

@ -1,56 +0,0 @@
#!/bin/bash
# Script to generate Restic configuration with secure password
set -e
# Configuration should be sourced before running: source backup.env
CONFIG_FILE="$RESTIC_CONFIG_FILE"
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"
read -p "Do you want to overwrite it? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborted."
exit 1
fi
fi
# Generate secure password (32 characters)
echo "Generating secure password..."
RESTIC_PASSWORD=$(openssl rand -base64 32)
# Create configuration file
echo "Creating configuration file..."
cat > "$CONFIG_FILE" << EOF
# Restic configuration for quantumrick backups
# Generated on $(date)
# Repository path
export RESTIC_REPOSITORY="$REPO_PATH"
# Repository password
export RESTIC_PASSWORD="$RESTIC_PASSWORD"
# Cache directory (optional)
export RESTIC_CACHE_DIR="$RESTIC_CACHE_DIR"
EOF
# Set secure permissions
chmod 600 "$CONFIG_FILE"
echo "✅ Configuration file created at $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 ""

View File

@ -1,52 +0,0 @@
#!/bin/bash
# Script to initialize Restic repository for quantumrick backups
set -e
# Configuration should be sourced before running: source backup.env
REPO_PATH="$BACKUP_REPOSITORY"
CONFIG_FILE="$RESTIC_CONFIG_FILE"
echo "=== Initializing Restic Repository ==="
# Check if repository directory exists
if [ ! -d "$(dirname "$REPO_PATH")" ]; then
echo "Creating backup directory..."
sudo mkdir -p "$(dirname "$REPO_PATH")"
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!"
echo "Please run generate-restic-config.sh first to create the configuration."
exit 1
fi
# Source the configuration
source "$CONFIG_FILE"
# Check if repository is already initialized
if restic -r "$REPO_PATH" cat config &>/dev/null; then
echo "Repository already initialized at $REPO_PATH"
exit 0
fi
echo "Initializing new Restic repository at $REPO_PATH"
# Initialize the repository
restic init -r "$REPO_PATH"
if [ $? -eq 0 ]; then
echo "✅ Repository successfully initialized!"
echo "Repository path: $REPO_PATH"
echo "Configuration: $CONFIG_FILE"
else
echo "❌ Failed to initialize repository"
exit 1
fi
echo "=== Repository Information ==="
restic -r "$REPO_PATH" stats

View File

@ -1,10 +1,17 @@
#!/bin/bash
# Generic script to install systemd timer for any service backup
# Usage: sudo ./install-service.sh <service_name> [schedule]
# This script should only be called via ./manage install <service>
set -e
# Check if called via manage script
if [ "${CALLED_FROM_MANAGE:-}" != "true" ]; then
echo "ERROR: This script should not be called directly."
echo "Use: ./manage install <service_name>"
exit 1
fi
# Configuration should be sourced before running: source backup.env
# Check arguments

View File

@ -1,10 +1,17 @@
#!/bin/bash
# Script to list available snapshots from Restic repository
# Usage: ./list-snapshots [service_name]
# This script should only be called via ./manage snapshots [service]
set -e
# Check if called via manage script
if [ "${CALLED_FROM_MANAGE:-}" != "true" ]; then
echo "ERROR: This script should not be called directly."
echo "Use: ./manage snapshots [service_name]"
exit 1
fi
# Configuration should be sourced before running: source backup.env
# Configuration

View File

@ -1,10 +1,17 @@
#!/bin/bash
# Restic backup restore script
# Usage: ./restore <service_name> [--test|--production]
# This script should only be called via ./manage restore/restore-prod <service>
set -euo pipefail # Strict mode: exit on error, undefined vars, pipe failures
# Check if called via manage script
if [ "${CALLED_FROM_MANAGE:-}" != "true" ]; then
echo "ERROR: This script should not be called directly."
echo "Use: ./manage restore <service_name> or ./manage restore-prod <service_name>"
exit 1
fi
# Configuration should be sourced before running: source backup.env
# Configuration

186
install Executable file
View File

@ -0,0 +1,186 @@
#!/bin/bash
# QuantumRick Installation Script
# Consolidates configuration generation and repository initialization
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"
else
echo "ERROR: Configuration file backup.env not found in $SCRIPT_DIR"
echo "Please ensure backup.env exists in project root directory"
exit 1
fi
show_help() {
echo "Usage: $0 [command]"
echo ""
echo "Commands:"
echo " config Generate Restic configuration with secure password"
echo " repo Initialize Restic repository"
echo " setup Complete setup (config + repo)"
echo " help Show this help message"
echo ""
echo "Examples:"
echo " $0 setup # Full installation (recommended)"
echo " $0 config # Generate configuration only"
echo " $0 repo # Initialize repository only"
}
generate_config() {
local CONFIG_FILE="$RESTIC_CONFIG_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"
read -p "Do you want to overwrite it? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Aborted."
return 1
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
# Restic configuration for quantumrick backups
# Generated on $(date)
# Repository path
export RESTIC_REPOSITORY="$REPO_PATH"
# Repository password
export RESTIC_PASSWORD="$RESTIC_PASSWORD"
# Cache directory (optional)
export RESTIC_CACHE_DIR="$RESTIC_CACHE_DIR"
EOF
# Set secure permissions
chmod 600 "$CONFIG_FILE"
echo "✅ Configuration file created at $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 ""
return 0
}
initialize_repository() {
local REPO_PATH="$BACKUP_REPOSITORY"
local CONFIG_FILE="$RESTIC_CONFIG_FILE"
echo "=== Initializing Restic Repository ==="
# Check if repository directory exists
if [ ! -d "$(dirname "$REPO_PATH")" ]; then
echo "Creating backup directory..."
sudo mkdir -p "$(dirname "$REPO_PATH")"
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!"
echo "Please run '$0 config' first to create the configuration."
return 1
fi
# Source the configuration
source "$CONFIG_FILE"
# Check if repository is already initialized
if restic -r "$REPO_PATH" cat config &>/dev/null; then
echo "Repository already initialized at $REPO_PATH"
return 0
fi
echo "Initializing new Restic repository at $REPO_PATH"
# Initialize the repository
restic init -r "$REPO_PATH"
if [ $? -eq 0 ]; then
echo "✅ Repository successfully initialized!"
echo "Repository path: $REPO_PATH"
echo "Configuration: $CONFIG_FILE"
echo ""
echo "=== Repository Information ==="
restic -r "$REPO_PATH" stats
return 0
else
echo "❌ Failed to initialize repository"
return 1
fi
}
complete_setup() {
echo "=== QuantumRick Complete Setup ==="
echo ""
# Step 1: Generate configuration
if ! generate_config; then
echo "❌ Configuration generation failed"
return 1
fi
echo ""
# Step 2: Initialize repository
if ! initialize_repository; then
echo "❌ Repository initialization failed"
return 1
fi
echo ""
echo "🎉 QuantumRick setup completed successfully!"
echo ""
echo "Next steps:"
echo "1. Install a service timer: ./manage install <service_name>"
echo "2. Check available services: ./manage available"
echo "3. View backup status: ./manage list"
}
# Main script logic
case "${1:-setup}" in
config)
generate_config
;;
repo)
initialize_repository
;;
setup)
complete_setup
;;
help|--help|-h)
show_help
;;
*)
echo "ERROR: Unknown command '${1:-}'"
echo ""
show_help
exit 1
;;
esac

View File

@ -1,10 +1,21 @@
#!/bin/bash
# Script to manage backup timers for all services
# QuantumRick Backup Management Interface
# Automatically sources configuration from project root
set -e
# Configuration should be sourced before running: source backup.env
# 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"
else
echo "ERROR: Configuration file backup.env not found in $SCRIPT_DIR"
echo "Please ensure backup.env exists in project root directory"
exit 1
fi
BACKUP_DIR="$BACKUP_BASE_DIR"
SERVICES_DIR="$SERVICES_BASE_DIR"
@ -168,7 +179,7 @@ install_timer() {
exit 1
fi
"$BACKUP_DIR/install" "$service"
CALLED_FROM_MANAGE=true "$SCRIPT_DIR/backup/install-service" "$service"
}
list_available() {
@ -220,16 +231,16 @@ case "${1:-}" in
list_available
;;
snapshots)
"$BACKUP_DIR/list-snapshots" "$2"
CALLED_FROM_MANAGE=true "$SCRIPT_DIR/backup/list-snapshots" "$2"
;;
restore)
"$BACKUP_DIR/restore" "$2" --test
CALLED_FROM_MANAGE=true "$SCRIPT_DIR/backup/restore" "$2" --test
;;
restore-prod)
"$BACKUP_DIR/restore" "$2" --production
CALLED_FROM_MANAGE=true "$SCRIPT_DIR/backup/restore" "$2" --production
;;
cleanup-test)
"$BACKUP_DIR/cleanup-test" "$2"
CALLED_FROM_MANAGE=true "$SCRIPT_DIR/backup/cleanup-test" "$2"
;;
help|--help|-h)
show_help