# ZFS Snapshot Manager A distributed ZFS snapshot management system with S3-compatible storage support. This project provides client, server, and restore tools for managing ZFS snapshots across multiple machines. ## Features - **S3 Storage Support**: Store snapshots in any S3-compatible storage (AWS S3, MinIO, Backblaze B2, Wasabi, DigitalOcean Spaces) - **Local ZFS Storage**: Option to use local ZFS datasets for maximum performance - **Multi-client Architecture**: Support for multiple clients with isolated storage and per-client quotas - **Automatic Compression**: Gzip compression for reduced storage costs - **Snapshot Rotation**: Automatic cleanup of old snapshots based on quota - **Server-Managed Rotation Policies**: Centralized control of client rotation policies - clients must use server-configured retention settings - **API Key Authentication**: Secure client-server communication ## Project Structure ``` zfs/ ├── cmd/ │ ├── zfs-server/ # Server executable │ ├── zfs-client/ # Client executable │ └── zfs-restore/ # Restore tool executable ├── internal/ │ ├── server/ # Server package (config, storage, HTTP handlers) │ ├── client/ # Client package (snapshot creation, upload) │ └── restore/ # Restore package (download, restore operations) ├── go.mod ├── go.sum ├── .env # Configuration file └── readme.md ``` ## Installation ### Using Go Install ```bash # Install server go install git.ma-al.com/goc_marek/zfs/cmd/zfs-server@latest # Install client go install git.ma-al.com/goc_marek/zfs/cmd/zfs-client@latest # Install restore tool go install git.ma-al.com/goc_marek/zfs/cmd/zfs-restore@latest ``` ### Build from Source ```bash # Clone the repository git clone https://git.ma-al.com/goc_marek/zfs.git cd zfs # Build all binaries go build -o bin/zfs-server ./cmd/zfs-server go build -o bin/zfs-client ./cmd/zfs-client go build -o bin/zfs-restore ./cmd/zfs-restore ``` ## Configuration ### Server Configuration Create a `.env` file in the working directory: ```env # S3 Configuration S3_ENABLED=true S3_ENDPOINT=s3.amazonaws.com S3_ACCESS_KEY=YOUR_ACCESS_KEY S3_SECRET_KEY=YOUR_SECRET_KEY S3_BUCKET=zfs-snapshots S3_USE_SSL=true # Local ZFS fallback ZFS_BASE_DATASET=backup # Server settings CONFIG_FILE=clients.json METADATA_FILE=metadata.json PORT=8080 ``` ### Client Configuration ```env CLIENT_ID=client1 API_KEY=secret123 SERVER_URL=http://backup-server:8080 LOCAL_DATASET=tank/data COMPRESS=true STORAGE_TYPE=s3 ``` ### Restore Tool Configuration ```env CLIENT_ID=client1 API_KEY=secret123 SERVER_URL=http://backup-server:8080 ``` ## Usage ### Server ```bash # Start the backup server zfs-server # The server listens on port 8080 by default # Endpoints: # POST /upload - Request upload authorization # POST /upload-stream/ - Stream snapshot data # GET /status - Check client status # POST /rotate - Rotate old snapshots # GET /download - Download a snapshot # GET /rotation-policy - Get client rotation policy # GET /health - Health check ``` ### Client Commands The `zfs-client` tool provides the following commands for managing ZFS snapshots: #### `backup` Creates a snapshot and sends it to the server. Automatically uses incremental backup if a bookmark exists. ```bash zfs-client backup ``` #### `backup-full` Forces a full backup (no incremental). Use for the initial backup or when you want to resend the complete dataset. ```bash zfs-client backup-full ``` #### `backup-incremental` Creates an incremental backup from the last bookmark. Requires an existing bookmark from a previous full backup. ```bash zfs-client backup-incremental ``` #### `snapshot ` Creates a typed snapshot (hourly, daily, weekly, monthly) with automatic rotation. The rotation policy is fetched from the server if configured. ```bash zfs-client snapshot hourly zfs-client snapshot daily zfs-client snapshot weekly zfs-client snapshot monthly ``` #### `rotate` Rotates local snapshots based on the retention policy. If the server has a rotation policy configured, it will be used; otherwise, default values apply. ```bash zfs-client rotate ``` #### `rotate-remote` Requests the server to rotate (delete old) remote snapshots to free up storage quota. ```bash zfs-client rotate-remote ``` #### `status` Displays the current backup status including storage usage, quota, and snapshot count from the server. ```bash zfs-client status ``` #### `bookmarks` Lists ZFS bookmarks on the local system. Bookmarks are used as reference points for incremental backups. ```bash zfs-client bookmarks ``` #### `help` Shows the help message with all available commands and options. ```bash zfs-client help ``` ### Restore Tool Commands The `zfs-restore` tool provides commands for listing and restoring snapshots from the backup server: #### `list` Lists all available snapshots for the configured client from the server. ```bash zfs-restore list ``` Output example: ``` # Snapshot ID Timestamp Size 1 client1/tank_data_2024-02-13 2024-02-13 14:30 1.2 GB 2 client1/tank_data_2024-02-12 2024-02-12 14:30 1.1 GB ``` #### `restore ` Restores a snapshot by its list number to a specified ZFS dataset. ```bash zfs-restore restore 1 tank/restored ``` Options: - `--force` or `-f` - Overwrite existing dataset if it exists ```bash zfs-restore restore 1 tank/restored --force ``` #### `latest ` Restores the most recent snapshot to a specified dataset. ```bash zfs-restore latest tank/restored ``` #### `save ` Downloads a snapshot and saves it to a local file without restoring. ```bash zfs-restore save 1 backup.zfs.gz ``` #### `mount ` Mounts a restored ZFS dataset to a specified directory for file access. ```bash zfs-restore mount tank/restored /mnt/restore ``` ## S3 Provider Configuration ### AWS S3 ```env S3_ENDPOINT=s3.amazonaws.com S3_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE S3_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY S3_BUCKET=my-zfs-backups S3_USE_SSL=true ``` ### MinIO (Self-Hosted) ```env S3_ENDPOINT=minio.example.com:9000 S3_ACCESS_KEY=minioadmin S3_SECRET_KEY=minioadmin S3_BUCKET=zfs-snapshots S3_USE_SSL=false ``` ### Backblaze B2 ```env S3_ENDPOINT=s3.us-west-000.backblazeb2.com S3_ACCESS_KEY=your_key_id S3_SECRET_KEY=your_application_key S3_BUCKET=zfs-backups S3_USE_SSL=true ``` ### Wasabi ```env S3_ENDPOINT=s3.wasabisys.com S3_ACCESS_KEY=your_access_key S3_SECRET_KEY=your_secret_key S3_BUCKET=zfs-backups S3_USE_SSL=true ``` ## Client Configuration File The server maintains a `clients.json` file with client configurations: ```json [ { "client_id": "client1", "api_key": "hashed_key", "max_size_bytes": 107374182400, "dataset": "backup/client1", "enabled": true, "storage_type": "s3", "rotation_policy": { "keep_hourly": 24, "keep_daily": 7, "keep_weekly": 4, "keep_monthly": 12 } } ] ``` ### Server-Managed Rotation Policy When `rotation_policy` is configured for a client in `clients.json`, the client **must** use this policy and cannot override it. This enables centralized control of snapshot retention policies: - **Server-Managed**: If `rotation_policy` is set, the client fetches the policy from the server and applies it - **Client-Autonomous**: If no `rotation_policy` is set, the client uses its default policy The rotation policy fields are: - `keep_hourly`: Number of hourly snapshots to keep (default: 24) - `keep_daily`: Number of daily snapshots to keep (default: 7) - `keep_weekly`: Number of weekly snapshots to keep (default: 4) - `keep_monthly`: Number of monthly snapshots to keep (default: 12) #### API Endpoint The server exposes a `/rotation-policy` endpoint for clients to fetch their configured policy: ```bash GET /rotation-policy?client_id=client1&api_key=secret123 ``` Response: ```json { "success": true, "message": "Server-managed rotation policy", "rotation_policy": { "keep_hourly": 24, "keep_daily": 7, "keep_weekly": 4, "keep_monthly": 12 }, "server_managed": true } ``` ## Architecture ``` ┌─────────────┐ ZFS send ┌──────────────────┐ │ Client 1 │───────┬─────────▶│ Backup Server │ │ (S3 mode) │ │ │ │ └─────────────┘ │ │ ┌────────────┐ │ │ │ │ S3 Backend │ │ ┌─────────────┐ │ HTTP │ └─────┬──────┘ │ │ Client 2 │───────┤ Stream │ │ │ │ (S3 mode) │ │ │ ▼ │ └─────────────┘ │ │ ┌────────────┐ │ │ │ │ MinIO │ │ ┌─────────────┐ │ │ │ or │ │ │ Client 3 │───────┘ │ │ AWS S3 │ │ │ (Local ZFS) │─────────────────▶│ └────────────┘ │ └─────────────┘ ZFS recv │ │ │ ┌────────────┐ │ │ │ Local ZFS │ │ │ │ Backend │ │ │ └────────────┘ │ └──────────────────┘ ``` ## Storage Format Snapshots are stored in S3 with the following naming convention: ``` s3://bucket/client1/tank_data_2024-02-13_14:30:00.zfs.gz ^ ^ ^ client dataset timestamp ``` ## Security - API keys are hashed using SHA-256 - S3 bucket policies can restrict access to backup server only - Server-side encryption available in S3 - Client-side encryption possible via custom compression pipeline ## Monitoring ### Health Check ```bash curl http://localhost:8080/health ``` ### Server Logs ```bash # SystemD journalctl -u zfs-server -f # Docker docker logs -f zfs-server ``` ## Development ### Project Layout - `cmd/` - Main applications (entry points) - `internal/` - Private application code - `server/` - Server logic, HTTP handlers, storage backends - `client/` - Client logic for creating and uploading snapshots - `restore/` - Restore logic for downloading and restoring snapshots ### Building ```bash # Build all go build ./... # Run tests go test ./... # Lint go vet ./... ``` ## License MIT License