From 1c2590c3c80e0688056173bc15d62e9009da0538 Mon Sep 17 00:00:00 2001 From: Cabbagec Date: Mon, 3 Aug 2026 09:42:53 +0000 Subject: [PATCH] Add helium archive node deployment manifests --- deploy/production/README.md | 5 ++- deploy/production/helium/README.md | 18 ++++++++ .../helium/archive-control-compose.yaml | 19 +++++++++ deploy/production/helium/client.toml | 42 +++++++++++++++++++ .../helium/qbittorrent-compose.yaml | 24 +++++++++++ deploy/production/helium/start-syncthing.sh | 18 ++++++++ .../production/helium/syncthing-compose.yaml | 19 +++++++++ 7 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 deploy/production/helium/README.md create mode 100644 deploy/production/helium/archive-control-compose.yaml create mode 100644 deploy/production/helium/client.toml create mode 100644 deploy/production/helium/qbittorrent-compose.yaml create mode 100755 deploy/production/helium/start-syncthing.sh create mode 100644 deploy/production/helium/syncthing-compose.yaml diff --git a/deploy/production/README.md b/deploy/production/README.md index 7ad0b4d..4b760a7 100644 --- a/deploy/production/README.md +++ b/deploy/production/README.md @@ -1,12 +1,15 @@ # Production deployment These files are the non-secret, host-specific deployment manifests for the -initial x1/x2/lithium topology. +initial x1/x2/lithium topology and the later helium archive node. - Install the x1 and x2 files as `~/compose/ArchiveControl-cache/{compose.yaml,client.toml}`. - Install the lithium files as `~/compose/ArchiveControl-archive/{compose.yaml,client.toml}`. +- The helium directory contains three isolated compose-project manifests. Install + them under `~/Repositories/compose/{qbittorrent-helium,syncthing-helium,ArchiveControl-archive}` + as described in `helium/README.md`. - Create sibling `state`, `backups`, and `secrets` directories owned by the configured container UID/GID. - Secret files are never committed. Each `secrets` directory contains diff --git a/deploy/production/helium/README.md b/deploy/production/helium/README.md new file mode 100644 index 0000000..62347ef --- /dev/null +++ b/deploy/production/helium/README.md @@ -0,0 +1,18 @@ +# Helium archive-node deployment + +This directory contains the non-secret manifests for the dedicated helium +archive node. Install the files into these separate compose projects: + +- `~/Repositories/compose/qbittorrent-helium/compose.yaml` +- `~/Repositories/compose/syncthing-helium/compose.yaml` +- `~/Repositories/compose/ArchiveControl-archive/{compose.yaml,client.toml}` + +The qBittorrent API and Syncthing GUI/API bind only to loopback. Syncthing +transport/discovery ports are published normally. qBittorrent data and +Syncthing route folders both live under `/media/Data2`; the Archive Control +container therefore mounts `/media/Data2` once at `/data/storage` so archive +placements can hardlink rather than make a full copy. + +`/media/Data2/Downloading` already contains unrelated files. The fresh qB +instance must not import or manage them; only Archive Control-created torrents +are managed. diff --git a/deploy/production/helium/archive-control-compose.yaml b/deploy/production/helium/archive-control-compose.yaml new file mode 100644 index 0000000..f8c8a83 --- /dev/null +++ b/deploy/production/helium/archive-control-compose.yaml @@ -0,0 +1,19 @@ +name: archive-control-helium + +services: + archive-client: + image: sodium/archive-clients:v0.1.19 + user: "1000:1000" + restart: unless-stopped + network_mode: host + command: ["--config", "/etc/archive-control/client.toml"] + environment: + QB_USER: admin + volumes: + - ./client.toml:/etc/archive-control/client.toml:ro + - ./secrets:/run/secrets:ro + - ./state:/var/lib/archive-control + - ./backups:/var/backups/archive-control + # Do not split this into separate qB and Sync bind mounts: hardlinks + # require both trees to resolve within this one mount namespace. + - /media/Data2:/data/storage diff --git a/deploy/production/helium/client.toml b/deploy/production/helium/client.toml new file mode 100644 index 0000000..f9f50d2 --- /dev/null +++ b/deploy/production/helium/client.toml @@ -0,0 +1,42 @@ +client_id = "helium-archive" +display_name = "helium archive" +role = "archive" +control_endpoint = "ws://bot.everdream.xyz:8766/archive_control" +shared_token_file = "/run/secrets/archive_control_token" +state_db = "/var/lib/archive-control/client.db" +backup_dir = "/var/backups/archive-control" + +[connection] +registration_timeout = "10s" +heartbeat_interval = "15s" +offline_timeout = "45s" +reconnect_initial = "1s" +reconnect_max = "60s" +reconnect_reset_after = "60s" +reconnect_jitter = true + +[jobs] +stall_after = "30m" +verification_timeout = "30m" +poll_interval = "1s" +free_space_reserve_bytes = 33554432 + +[backup] +interval = "6h" +recent = 12 +daily = 14 +weekly = 8 + +[qbittorrent] +endpoint = "http://127.0.0.1:8081" +username = "${QB_USER}" +password_file = "/run/secrets/qb_password" +api_root = "/downloads/Downloading" +local_root = "/data/storage/Downloading" + +[syncthing] +endpoint = "http://127.0.0.1:8384" +api_key_file = "/run/secrets/syncthing_api_key" +api_root = "/var/syncthing" +local_root = "/data/storage/Sync" +advertised_addresses = ["dynamic"] diff --git a/deploy/production/helium/qbittorrent-compose.yaml b/deploy/production/helium/qbittorrent-compose.yaml new file mode 100644 index 0000000..171ff42 --- /dev/null +++ b/deploy/production/helium/qbittorrent-compose.yaml @@ -0,0 +1,24 @@ +name: helium-qbittorrent + +services: + qbittorrent: + image: sodium/qbittorrent-nox:5.2.3-lt2-1-proxy-listen-amd64 + environment: + PUID: "1000" + PGID: "1000" + TZ: Etc/UTC + WEBUI_PORT: "8081" + TORRENTING_PORT: "6881" + command: ["--webui-port=8081", "--confirm-legal-notice"] + volumes: + - ./config:/config + # This is deliberately one parent mount. Archive Control maps both the + # qB and Syncthing subtrees through the same mount namespace. + - /media/Data2:/downloads + ports: + # Keep the published and internal WebUI ports identical: qBittorrent + # rejects a forwarded request whose Host header carries a different port. + - "127.0.0.1:8081:8081" + - "6881:6881/tcp" + - "6881:6881/udp" + restart: unless-stopped diff --git a/deploy/production/helium/start-syncthing.sh b/deploy/production/helium/start-syncthing.sh new file mode 100755 index 0000000..6b14a92 --- /dev/null +++ b/deploy/production/helium/start-syncthing.sh @@ -0,0 +1,18 @@ +#!/bin/sh +set -eu + +home=/var/syncthing +api_key=$(cat /run/secrets/syncthing_api_key) + +if [ ! -f "$home/config.xml" ]; then + syncthing generate --home="$home" --no-port-probing +fi + +exec syncthing serve \ + --home="$home" \ + --gui-address=http://0.0.0.0:8384 \ + --gui-apikey="$api_key" \ + --no-browser \ + --no-port-probing \ + --no-restart \ + --no-upgrade diff --git a/deploy/production/helium/syncthing-compose.yaml b/deploy/production/helium/syncthing-compose.yaml new file mode 100644 index 0000000..f0f789d --- /dev/null +++ b/deploy/production/helium/syncthing-compose.yaml @@ -0,0 +1,19 @@ +name: helium-syncthing + +services: + syncthing: + image: syncthing/syncthing:2.1.2@sha256:4464f4161dd0251e20d46bb3aec83363db75d80cef1abdd5d5fd4054b04a004d + user: "1000:1000" + hostname: helium + entrypoint: ["/bootstrap/start-syncthing.sh"] + volumes: + - ./start-syncthing.sh:/bootstrap/start-syncthing.sh:ro + - ./secrets:/run/secrets:ro + - ./config:/var/syncthing + - /media/Data2/Sync:/var/syncthing/Sync + ports: + - "127.0.0.1:8384:8384" + - "22000:22000/tcp" + - "22000:22000/udp" + - "21027:21027/udp" + restart: unless-stopped