Release v1.0.0
Some checks failed
CI / Migrations, tests, build, and audit (push) Failing after 10m7s
CI / Production gate and container images (push) Successful in 20m35s

This commit is contained in:
2026-07-31 14:21:43 +08:00
commit 36f466ba11
187 changed files with 98907 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
# Copy to /etc/frameflow/backup.env and keep it readable only by root and the
# FrameFlow service group. These paths must match the installed application,
# encrypted backup mount, and Node Exporter textfile collector configuration.
FRAMEFLOW_ENV_FILE=/srv/frameflow/.env.production
FRAMEFLOW_BACKUP_MOUNTPOINT=/mnt/encrypted-backups
FRAMEFLOW_BACKUP_DESTINATION=/mnt/encrypted-backups/frameflow
FRAMEFLOW_BACKUP_METRICS_DIR=/var/lib/frameflow/metrics
FRAMEFLOW_RESTORE_METRICS_DIR=/var/lib/frameflow/metrics
FRAMEFLOW_RESTORE_TIMEOUT_SECONDS=300

View File

@@ -0,0 +1,35 @@
[Unit]
Description=FrameFlow verified PostgreSQL, Redis, and MinIO backup
Documentation=file:///srv/frameflow/docs/deployment.md
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
RequiresMountsFor=/mnt/encrypted-backups
AssertPathIsMountPoint=/mnt/encrypted-backups
ConditionPathExists=/srv/frameflow/scripts/scheduled-maintenance.sh
ConditionPathExists=/etc/frameflow/backup.env
[Service]
Type=oneshot
User=frameflow
Group=frameflow
SupplementaryGroups=docker
EnvironmentFile=/etc/frameflow/backup.env
WorkingDirectory=/srv/frameflow
ExecStart=/srv/frameflow/scripts/scheduled-maintenance.sh backup
UMask=0077
TimeoutStartSec=6h
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=6
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
ReadWritePaths=/mnt/encrypted-backups/frameflow /var/lib/frameflow/metrics /var/run/docker.sock

View File

@@ -0,0 +1,12 @@
[Unit]
Description=Run the FrameFlow verified backup every day
[Timer]
OnCalendar=*-*-* 03:15:00
RandomizedDelaySec=15m
AccuracySec=1m
Persistent=true
Unit=frameflow-backup.service
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,36 @@
[Unit]
Description=FrameFlow isolated restore rehearsal of the latest verified backup
Documentation=file:///srv/frameflow/docs/deployment.md
Requires=docker.service frameflow-backup.service
After=docker.service frameflow-backup.service network-online.target
Wants=network-online.target
RequiresMountsFor=/mnt/encrypted-backups
AssertPathIsMountPoint=/mnt/encrypted-backups
ConditionPathExists=/srv/frameflow/scripts/scheduled-maintenance.sh
ConditionPathExists=/etc/frameflow/backup.env
[Service]
Type=oneshot
User=frameflow
Group=frameflow
SupplementaryGroups=docker
EnvironmentFile=/etc/frameflow/backup.env
WorkingDirectory=/srv/frameflow
ExecStart=/srv/frameflow/scripts/scheduled-maintenance.sh restore-latest
UMask=0077
TimeoutStartSec=6h
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=6
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ProtectControlGroups=true
ProtectKernelModules=true
ProtectKernelTunables=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
ReadOnlyPaths=/mnt/encrypted-backups/frameflow
ReadWritePaths=/var/lib/frameflow/metrics /var/run/docker.sock

View File

@@ -0,0 +1,12 @@
[Unit]
Description=Run a FrameFlow isolated restore rehearsal every month
[Timer]
OnCalendar=*-*-01 05:15:00
RandomizedDelaySec=30m
AccuracySec=1m
Persistent=true
Unit=frameflow-restore-rehearsal.service
[Install]
WantedBy=timers.target