77 lines
2.5 KiB
Bash
Executable File
77 lines
2.5 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
umask 077
|
|
stage="$(cd "$(dirname "$0")" && pwd)"
|
|
mountpoint -q /mnt/data || { echo 'External disk is not mounted'; exit 1; }
|
|
findmnt -n -o OPTIONS /mnt/data | tr ',' '\n' | grep -qx rw
|
|
test -f "$stage/token.sha256"
|
|
if ! id qsafe >/dev/null 2>&1; then useradd --system --home-dir /nonexistent --shell /usr/sbin/nologin qsafe; fi
|
|
install -d -o root -g root -m 755 /opt/qsafe
|
|
install -d -o qsafe -g qsafe -m 700 /mnt/data/qsafe/data
|
|
install -d -o root -g qsafe -m 750 /etc/qsafe
|
|
install -d -o root -g root -m 700 /var/backups/qsafe /var/backups/qsafe-install
|
|
install -m 644 "$stage/server.py" "$stage/backup.py" /opt/qsafe/
|
|
if test -f /etc/qsafe/token.sha256; then
|
|
cmp -s "$stage/token.sha256" /etc/qsafe/token.sha256 || { echo 'Existing connection key differs; refusing to rotate it'; exit 1; }
|
|
else
|
|
install -o root -g qsafe -m 640 "$stage/token.sha256" /etc/qsafe/token.sha256
|
|
fi
|
|
cat > /etc/systemd/system/qsafe.service <<'EOF'
|
|
[Unit]
|
|
Description=QSafe encrypted vault synchronization
|
|
After=network.target
|
|
RequiresMountsFor=/mnt/data/qsafe/data
|
|
[Service]
|
|
Type=simple
|
|
User=qsafe
|
|
Group=qsafe
|
|
UMask=0077
|
|
ExecStart=/usr/bin/python3 /opt/qsafe/server.py --data /mnt/data/qsafe/data --token-hash-file /etc/qsafe/token.sha256
|
|
Restart=on-failure
|
|
RestartSec=3
|
|
NoNewPrivileges=true
|
|
PrivateTmp=true
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
ReadWritePaths=/mnt/data/qsafe/data
|
|
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
|
MemoryMax=256M
|
|
TasksMax=48
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
cat > /etc/systemd/system/qsafe-backup.service <<'EOF'
|
|
[Unit]
|
|
Description=QSafe verified encrypted backup to SD card
|
|
RequiresMountsFor=/mnt/data/qsafe/data
|
|
[Service]
|
|
Type=oneshot
|
|
UMask=0077
|
|
ExecStart=/usr/bin/python3 /opt/qsafe/backup.py /mnt/data/qsafe/data/vault.sqlite3 /var/backups/qsafe
|
|
NoNewPrivileges=true
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
ReadWritePaths=/var/backups/qsafe /mnt/data/qsafe/data
|
|
EOF
|
|
cat > /etc/systemd/system/qsafe-backup.timer <<'EOF'
|
|
[Unit]
|
|
Description=Daily QSafe encrypted backup
|
|
[Timer]
|
|
OnCalendar=*-*-* 04:25:00
|
|
Persistent=true
|
|
RandomizedDelaySec=300
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOF
|
|
: "${QSAFE_LAN_IP:?Set the Pi private IPv4; public vault endpoints are forbidden}"
|
|
python3 "$stage/lan-only.py" --ip "$QSAFE_LAN_IP"
|
|
systemctl daemon-reload
|
|
systemctl enable --now qsafe.service qsafe-backup.timer
|
|
systemctl restart qsafe.service
|
|
for i in $(seq 1 20); do
|
|
if curl -fsS http://127.0.0.1:18792/health; then break; fi
|
|
sleep 1
|
|
done
|
|
systemctl start qsafe-backup.service
|
|
systemctl is-active qsafe.service caddy.service qsafe-backup.timer
|