2026-02-26 03:10:13 +03:00
2026-02-26 03:10:13 +03:00
2026-02-25 01:47:35 +03:00
2026-02-26 03:10:13 +03:00
2026-02-25 01:47:35 +03:00
2026-02-25 01:47:35 +03:00

Homelab

Prerequisites

  • Docker and Docker Compose
  • Host paths used by the stacks:
    • /srv/homelab
    • /srv/media
    • /backup

Setup

1. Media dirs

sudo mkdir -p /srv/media/{movies,shows,downloads,immich}
sudo chown -R 1000:1000 /srv/media

2. Monitoring permissions

sudo mkdir -p /srv/homelab/data/monitoring/{prometheus,loki,grafana,alloy}
sudo chown -R 65534:65534 /srv/homelab/data/monitoring/prometheus
sudo chown -R 10001:10001 /srv/homelab/data/monitoring/loki
sudo chown -R 472:472     /srv/homelab/data/monitoring/grafana
sudo chown -R 10001:10001 /srv/homelab/data/monitoring/alloy

3. Env

  • Glance: stacks/monitoring/glance.env
  • Immich: stacks/media/immich.env

Deploying

From the repo root (/srv/homelab):

Stack Command
Media docker compose -f stacks/media/compose.yaml up -d
Monitoring docker compose -f stacks/monitoring/compose.yaml up -d
Storage docker compose -f stacks/storage/compose.yaml up -d

To update images:

docker compose -f stacks/media/compose.yaml pull
docker compose -f stacks/media/compose.yaml up -d

To stop a stack:

docker compose -f stacks/media/compose.yaml down

Ports

Service Port(s) Stack
Media
Sonarr 8989 media
Radarr 7878 media
Lidarr 8686 media
Prowlarr 9696 media
qBittorrent 8081, 6881 (tcp/udp) media
Jellyfin 8096 media
Immich 2283 media
Navidrome 4533 media
Seer 5055 media
Monitoring
Grafana 3034 monitoring
Prometheus 9094 monitoring
Loki 3100 monitoring
Node Exporter 9100 monitoring
Alloy 12345 monitoring
cAdvisor 8088 monitoring
Glance 9090 monitoring
Portainer 9443, 8000 monitoring
Storage
Gitea 3000, 222 storage
Copyparty 3923 storage

Backup

Backups use Restic. The script backs up /srv/homelab (including data/), /etc/caddy/Caddyfile, and /etc/unbound/unbound.conf. It stops all Docker stacks before backup for consistent data, then starts them again—run it manually when you can afford a few minutes of downtime.

One-time setup

  1. Install restic (e.g. pacman -S restic or from restic.net).

  2. Copy the env example and set repository and password:

    cp scripts/restic-backup.env.example scripts/restic-backup.env
    # Edit scripts/restic-backup.env: set RESTIC_REPOSITORY and RESTIC_PASSWORD
    

    Examples for RESTIC_REPOSITORY:

    • Local: RESTIC_REPOSITORY=/backup/restic
    • SFTP: RESTIC_REPOSITORY=sftp:user@backup-host:/restic
    • S3: RESTIC_REPOSITORY=s3:s3.amazonaws.com/bucket-name
  3. Initialize the repo (once):

    export RESTIC_PASSWORD='your-password'
    restic -r /backup/restic init   # use your actual repo path
    

Create a backup

From the repo root, run:

sudo ./scripts/restic-backup.sh

Stacks are stopped, then the backup runs, then they are started again. A failed backup still triggers the start so the homelab comes back up.

Inspect backups

List snapshots (IDs and timestamps):

source scripts/restic-backup.env
sudo restic snapshots -r $RESTIC_REPOSITORY

List files in a snapshot (e.g. latest or by ID):

restic ls latest -r $RESTIC_REPOSITORY
restic ls -r $RESTIC_REPOSITORY <snapshot-id>

Browse a path inside a snapshot:

restic ls latest -r $RESTIC_REPOSITORY /srv/homelab/config 

See diffs between backups

Compare two snapshots (added, changed, removed files and content diff):

restic diff <older-snapshot-id> <newer-snapshot-id> -r $RESTIC_REPOSITORY

Restore

Restore the latest snapshot into a directory (does not overwrite the repo; use a separate target dir):

restic restore latest --target /tmp/restore -r $RESTIC_REPOSITORY

Restore a specific snapshot or path:

restic restore <snapshot-id> --target /tmp/restore -r $RESTIC_REPOSITORY
restic restore latest --path /etc/caddy --target /tmp/restore -r $RESTIC_REPOSITORY

After restore, fix ownership on data/ if needed (see Monitoring permissions).

Description
No description provided
Readme 88 KiB
Languages
Shell 100%