mirror of
https://github.com/xCyanGrizzly/DragonsStash.git
synced 2026-09-21 05:21:43 +00:00
Backup: switch NAS transport to SMB/CIFS, fix crond/OOM/live-tar defects
Wire the backup service against the Synology share over SMB/CIFS (the NAS authenticates with a user/password; NFS is IP-allowlist only). Also fixes three defects found bringing the service up live: - entrypoint crash-loop: dcron's crond fails "setpgid: Operation not permitted" in this runtime -> use busybox crond; make repo-init idempotent (check via `restic cat config`, tolerate init-on-existing) so a transient CIFS/lock hiccup can't kill PID 1. - OOM: pg_dump of a ~276MB DB + tar + restic exceeded the 256M cap -> 1G. - live tar abort: GNU tar exits 1 when TDLib files change mid-read (worker is live); per design this is best-effort, so tolerate exit 1, fatal only >=2. Kuma push is now optional (empty URL disables alerting) since it's deferred. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+5
-3
@@ -37,9 +37,11 @@ WORKER_MAX_ZIP_SIZE_MB=4096
|
|||||||
MULTIPART_TIMEOUT_HOURS=0
|
MULTIPART_TIMEOUT_HOURS=0
|
||||||
LOG_LEVEL="info"
|
LOG_LEVEL="info"
|
||||||
|
|
||||||
# Backup (NAS via NFS + restic)
|
# Backup (NAS via SMB/CIFS + restic)
|
||||||
NAS_HOST="" # Synology NAS IP or hostname reachable from this host
|
NAS_HOST="" # Synology NAS IP or hostname reachable from this host
|
||||||
NAS_EXPORT_PATH="" # NFS export path, e.g. /volume1/dragonsstash-backups
|
NAS_SHARE="" # SMB share name, e.g. dragonsstash_backups
|
||||||
|
NAS_USERNAME="" # SMB user with read/write on the share
|
||||||
|
NAS_PASSWORD="" # SMB user password (avoid commas — they delimit cifs mount opts)
|
||||||
RESTIC_PASSWORD="" # generate with: openssl rand -base64 32
|
RESTIC_PASSWORD="" # generate with: openssl rand -base64 32
|
||||||
KUMA_PUSH_URL="" # Uptime Kuma Push monitor URL (create the monitor first)
|
KUMA_PUSH_URL="" # optional: Uptime Kuma Push monitor URL; leave empty to disable alerting
|
||||||
TZ="Etc/UTC"
|
TZ="Etc/UTC"
|
||||||
|
|||||||
+3
-1
@@ -1,6 +1,8 @@
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.20
|
||||||
|
|
||||||
RUN apk add --no-cache restic postgresql16-client curl tzdata dcron tar bash
|
# Note: use busybox's built-in crond (Alpine base), NOT the dcron package —
|
||||||
|
# dcron's crond fails with "setpgid: Operation not permitted" in this runtime.
|
||||||
|
RUN apk add --no-cache restic postgresql16-client curl tzdata tar bash
|
||||||
|
|
||||||
COPY backup/backup.sh /backup.sh
|
COPY backup/backup.sh /backup.sh
|
||||||
COPY backup/entrypoint.sh /entrypoint.sh
|
COPY backup/entrypoint.sh /entrypoint.sh
|
||||||
|
|||||||
+8
-1
@@ -2,6 +2,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
report_failure() {
|
report_failure() {
|
||||||
|
[ -n "${KUMA_PUSH_URL:-}" ] || return 0
|
||||||
curl -fsS "$KUMA_PUSH_URL" --get \
|
curl -fsS "$KUMA_PUSH_URL" --get \
|
||||||
--data-urlencode "status=down" \
|
--data-urlencode "status=down" \
|
||||||
--data-urlencode "msg=$BASH_COMMAND failed" || true
|
--data-urlencode "msg=$BASH_COMMAND failed" || true
|
||||||
@@ -15,11 +16,17 @@ trap 'rm -f "$DUMP_FILE" "$TAR_FILE"' EXIT
|
|||||||
|
|
||||||
pg_dump -h dragonsstash-db -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc -f "$DUMP_FILE"
|
pg_dump -h dragonsstash-db -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc -f "$DUMP_FILE"
|
||||||
|
|
||||||
tar czf "$TAR_FILE" -C /data tdlib-worker tdlib-bot
|
# TDLib volumes are tarred live (best-effort, per design). A file changing
|
||||||
|
# mid-read makes GNU tar exit 1 (warning) — that is expected here and must not
|
||||||
|
# abort the backup. Only a genuine error (exit >= 2) is fatal.
|
||||||
|
tar --warning=no-file-changed -czf "$TAR_FILE" -C /data tdlib-worker tdlib-bot \
|
||||||
|
|| { rc=$?; [ "$rc" -le 1 ] || exit "$rc"; }
|
||||||
|
|
||||||
restic backup "$DUMP_FILE" "$TAR_FILE"
|
restic backup "$DUMP_FILE" "$TAR_FILE"
|
||||||
restic forget --keep-daily 14 --prune
|
restic forget --keep-daily 14 --prune
|
||||||
|
|
||||||
|
if [ -n "${KUMA_PUSH_URL:-}" ]; then
|
||||||
curl -fsS "$KUMA_PUSH_URL" --get \
|
curl -fsS "$KUMA_PUSH_URL" --get \
|
||||||
--data-urlencode "status=up" \
|
--data-urlencode "status=up" \
|
||||||
--data-urlencode "msg=OK"
|
--data-urlencode "msg=OK"
|
||||||
|
fi
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -euo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
if ! restic snapshots >/dev/null 2>&1; then
|
# Ensure the repo exists, but never crash-loop on it: a transient error reading
|
||||||
restic init
|
# the repo (CIFS hiccup, stale lock) must not kill PID 1. `restic init` failing
|
||||||
|
# because the repo already exists is expected and harmless here.
|
||||||
|
if ! restic cat config >/dev/null 2>&1; then
|
||||||
|
restic init || echo "restic init skipped (repo already exists or temporarily unreachable)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec crond -f -l 2
|
exec crond -f -l 2
|
||||||
|
|||||||
+5
-5
@@ -109,7 +109,7 @@ services:
|
|||||||
- POSTGRES_DB=${POSTGRES_DB:-dragonsstash}
|
- POSTGRES_DB=${POSTGRES_DB:-dragonsstash}
|
||||||
- RESTIC_REPOSITORY=/backups/restic-repo
|
- RESTIC_REPOSITORY=/backups/restic-repo
|
||||||
- RESTIC_PASSWORD=${RESTIC_PASSWORD:?Set RESTIC_PASSWORD in .env}
|
- RESTIC_PASSWORD=${RESTIC_PASSWORD:?Set RESTIC_PASSWORD in .env}
|
||||||
- KUMA_PUSH_URL=${KUMA_PUSH_URL:?Set KUMA_PUSH_URL in .env}
|
- KUMA_PUSH_URL=${KUMA_PUSH_URL:-}
|
||||||
- TZ=${TZ:-Etc/UTC}
|
- TZ=${TZ:-Etc/UTC}
|
||||||
volumes:
|
volumes:
|
||||||
- tdlib_state:/data/tdlib-worker:ro
|
- tdlib_state:/data/tdlib-worker:ro
|
||||||
@@ -122,7 +122,7 @@ services:
|
|||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 256M
|
memory: 1G
|
||||||
networks:
|
networks:
|
||||||
- backend
|
- backend
|
||||||
|
|
||||||
@@ -158,9 +158,9 @@ volumes:
|
|||||||
manual_uploads:
|
manual_uploads:
|
||||||
nas_backups:
|
nas_backups:
|
||||||
driver_opts:
|
driver_opts:
|
||||||
type: nfs
|
type: cifs
|
||||||
o: "addr=${NAS_HOST},rw,nfsvers=4,soft,timeo=100"
|
o: "username=${NAS_USERNAME},password=${NAS_PASSWORD},vers=3.0,uid=0,gid=0,file_mode=0660,dir_mode=0770"
|
||||||
device: ":${NAS_EXPORT_PATH}"
|
device: "//${NAS_HOST}/${NAS_SHARE}"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
frontend:
|
frontend:
|
||||||
|
|||||||
Reference in New Issue
Block a user