feat: backup improvements — AlbyHub Restic, Gitea dump CronJob, Immich → MinIO #17

Merged
greg merged 5 commits from klaatu/nixos:feature/backup-improvements into main 2026-04-04 18:00:19 +00:00
2 changed files with 38 additions and 41 deletions
Showing only changes of commit 0218447008 - Show all commits
+6 -24
View File
@@ -60,6 +60,12 @@ in
enable = true;
tags = [ "home" ];
};
backup.jobs.albyhub = {
src = "/chain/alby";
dest = "albyhub";
pre = "systemctl stop albyhub || true";
post = "systemctl start albyhub";
};
};
hardware = {
1
@@ -145,24 +151,6 @@ in
};
};
prometheus.exporters.graphite.enable = true;
restic.backups.albyhub = {
# AlbyHub LDK node data — must not be snapshotted live
paths = [ "/chain/alby" ];
environmentFile = config.age.secrets.restic-env.path;
passwordFile = config.age.secrets.restic-pw.path;
initialize = true;
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 4"
"--keep-monthly 12"
];
backupPrepareCommand = "systemctl stop albyhub || true";
backupCleanupCommand = "systemctl start albyhub";
timerConfig = {
OnCalendar = "02:30";
RandomizedDelaySec = "30min";
};
};
# Configure keymap
xserver.xkb = {
layout = "us";
@@ -176,12 +164,6 @@ in
file = ../../../secrets/grafana-api-token.age;
owner = "grafana";
};
age.secrets.restic-pw = {
file = ../../../secrets/restic-pw.age;
};
age.secrets.restic-env = {
file = ../../../secrets/restic-env.age;
};
environment.etc = {
"grafana-dashboards/system-health.json".text = ''
+32 -17
View File
@@ -19,10 +19,8 @@ spec:
- name: gitea-data
persistentVolumeClaim:
claimName: gitea-shared-storage
- name: dump-output
nfs:
path: /mnt/all/backups/gitea-dumps
server: nas1.shire-zebra.ts.net
- name: dump-staging
emptyDir: {}
initContainers:
- name: gitea-dump
image: "gitea/gitea:1.25.4"
@@ -32,30 +30,47 @@ spec:
- |
set -e
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
OUTFILE="/dump-output/gitea-dump-${TIMESTAMP}.zip"
OUTFILE="/dump-staging/gitea-dump-${TIMESTAMP}.zip"
gitea dump \
--config /data/gitea/conf/app.ini \
--file "${OUTFILE}" \
--type zip \
--skip-log \
--skip-custom-dir \
--skip-db
--type zip
echo "Dump written to ${OUTFILE}"
volumeMounts:
- name: gitea-data
mountPath: /data
readOnly: true
greg marked this conversation as resolved
Review

There is no need to skip items. Let's make the backup complete.

There is no need to skip items. Let's make the backup complete.
- name: dump-output
mountPath: /dump-output
- name: dump-staging
mountPath: /dump-staging
containers:
- name: cleanup
image: "busybox:1.36"
- name: upload-to-s3
image: "minio/mc:latest"
command:
- /bin/sh
- "-c"
- |
ls -t /dump-output/gitea-dump-*.zip 2>/dev/null | tail -n +31 | xargs rm -f
echo "Cleanup done."
set -e
# Configure mc alias for MinIO
mc alias set nas1 http://nas1.shire-zebra.ts.net:9000 \
"${MINIO_ACCESS_KEY}" "${MINIO_SECRET_KEY}"
# Upload dump to backup-gitea bucket
DUMP_FILE=$(ls /dump-staging/gitea-dump-*.zip | head -1)
greg marked this conversation as resolved Outdated
Outdated
Review

Let's change this to use the S3 backups as well, where we can set the items with a 30 day expiration time. I've created the bucket backup-gitea for holding them. No need for the NFS loading.

Let's change this to use the S3 backups as well, where we can set the items with a 30 day expiration time. I've created the bucket `backup-gitea` for holding them. No need for the NFS loading.
mc cp "${DUMP_FILE}" "nas1/backup-gitea/$(basename ${DUMP_FILE})"
echo "Uploaded $(basename ${DUMP_FILE}) to backup-gitea"
# Set 30-day lifecycle on the bucket (idempotent)
mc ilm rule add --expire-days 30 nas1/backup-gitea 2>/dev/null || true
volumeMounts:
- name: dump-output
mountPath: /dump-output
- name: dump-staging
mountPath: /dump-staging
readOnly: true
env:
- name: MINIO_ACCESS_KEY
valueFrom:
secretKeyRef:
name: gitea-config
key: minio_key
- name: MINIO_SECRET_KEY
valueFrom:
secretKeyRef:
name: gitea-config
key: minio_secret