usb drive fix, docs

This commit is contained in:
2026-02-20 21:58:27 +01:00
parent 133f2a816a
commit 00e47f0db5
2 changed files with 102 additions and 1 deletions

View File

@@ -18,4 +18,56 @@ Check the wiki here for more information: [wikimd/wiki/homepage.md](wikimd/wiki/
## Backup Strategies ## Backup Strategies
TODO Two scripts handle backups. Both must be run as **root** (`sudo`) because the backup destination is owned by root.
### File Backup — [`backup.sh`](backup.sh)
Incremental rsync snapshot backup of `/home/oster/server` to the extension drive.
- **Destination:** `/media/extension/backup/ubuntu/`
- **Method:** Hard-link incremental snapshots (`--link-dest`) — each daily run creates a new `YYYY-MM-DD/` directory; unchanged files are hard-linked from the previous snapshot, so each snapshot looks complete but only new/changed files consume extra space.
- **Retention:** Configurable at the top of the script:
```bash
readonly KEEP_DAILY=3 # keep this many daily snapshots
readonly KEEP_WEEKLY=2 # keep this many weekly (Sunday) snapshots
```
- **Exclusions:** `.cache`, `node_modules`, `*.tmp`, and DB-related directories (`postgresql`, `mysql`, `db`, `database`) — those are handled separately by `backup-db.sh`.
- **Locking:** A lockfile at `/media/extension/backup/ubuntu/.backup.lock` prevents concurrent runs. Stale locks (from crashed runs) are detected by PID check and removed automatically.
**Run manually:**
```bash
sudo ./backup.sh
```
**Cron example** (daily at 04:00, in root's crontab via `sudo crontab -e`):
```
0 4 * * * /home/oster/git/homeserver/backup.sh >> /var/log/backup.log 2>&1
```
---
### Database Backup — [`backup-db.sh`](backup-db.sh)
Dumps all PostgreSQL databases from running Docker containers using `pg_dumpall`.
- **Destination:** `/home/oster/server/backup/` (on the system disk, picked up by `backup.sh` on the next run)
- **Databases backed up:**
| Container | DB User | Label |
|---|---|---|
| `immich_postgres` | `postgres` | `immich` |
| `authentik-postgresql-1` | `authentik` | `authentik` |
| `paperless-db-1` | `paperless` | `paperless` |
- **Output format:** `YYYY-MM-DD_HH:MM:SS-<label>.sql.gz` (gzip-compressed SQL dump)
- **Retention:** Dumps older than 7 days are automatically deleted.
**Run manually:**
```bash
sudo ./backup-db.sh
```
**Cron example** (daily at 03:30, before the file backup):
```
30 3 * * * /home/oster/git/homeserver/backup-db.sh >> /var/log/backup-db.log 2>&1
```

View File

@@ -15,6 +15,11 @@ readonly LATEST="${BACKUP_BASE}/latest"
readonly KEEP_DAILY=3 # keep this many daily snapshots readonly KEEP_DAILY=3 # keep this many daily snapshots
readonly KEEP_WEEKLY=2 # keep this many weekly (Sunday) snapshots readonly KEEP_WEEKLY=2 # keep this many weekly (Sunday) snapshots
# USB backup drive — ASMedia ASM1153E bridge (174c:55aa)
# Used to disable UAS (which causes resets under load) and spin-down
readonly USB_VENDOR_PRODUCT="174c:55aa"
readonly UAS_QUIRKS_FILE="/etc/modprobe.d/usb-backup-uas-quirk.conf"
# Directories (or files) to back up (without DB volumes) # Directories (or files) to back up (without DB volumes)
declare -a SOURCE_ITEMS=( declare -a SOURCE_ITEMS=(
"/home/oster/server" "/home/oster/server"
@@ -59,6 +64,48 @@ check_mount() {
fi fi
} }
# Ensure the UAS quirk is configured for the backup drive.
# UAS causes device resets under sustained write load with the ASM1153E bridge.
# If the config is missing, write it and update initramfs (requires reboot to take effect).
ensure_uas_quirk() {
local vid="${USB_VENDOR_PRODUCT%%:*}"
local pid="${USB_VENDOR_PRODUCT##*:}"
local expected="options usb-storage quirks=${vid}:${pid}:u"
if grep -qsF "$expected" "$UAS_QUIRKS_FILE" 2>/dev/null; then
# Check if the drive is still bound to uas (quirk active only after reboot)
if ls /sys/bus/usb/drivers/uas/ 2>/dev/null | grep -q .; then
log "WARNING: UAS quirk is configured but drive is still using the uas driver."
log " A reboot is required for the quirk to take effect."
log " Backup will proceed but may encounter USB resets."
else
log "UAS quirk active — drive is using usb-storage driver."
fi
else
log "UAS quirk not found — writing $UAS_QUIRKS_FILE and updating initramfs."
echo "$expected" > "$UAS_QUIRKS_FILE"
update-initramfs -u
log "Initramfs updated. Please reboot for the UAS quirk to take effect."
log "Continuing backup with current (uas) driver — may encounter resets."
fi
}
# Disable drive spin-down and APM for the duration of the backup.
# The drive going to standby mid-write causes "Logical unit not ready" errors.
disable_spindown() {
local dev
# Resolve the underlying block device from the mount point (strip partition number)
dev=$(findmnt -n -o SOURCE "$MOUNT_POINT" | sed 's/[0-9]*$//')
if [[ -b "$dev" ]]; then
log "Disabling spin-down and APM on $dev for backup duration."
hdparm -B 255 -S 0 "$dev" > /dev/null \
&& log " hdparm: spin-down disabled on $dev." \
|| log "WARNING: hdparm failed on $dev — drive may still spin down."
else
log "WARNING: Could not determine block device for $MOUNT_POINT (got: $dev) — skipping hdparm."
fi
}
# Rotation: keep KEEP_DAILY daily and KEEP_WEEKLY weekly snapshots # Rotation: keep KEEP_DAILY daily and KEEP_WEEKLY weekly snapshots
rotate_old() { rotate_old() {
log "Applying retention policy (${KEEP_DAILY} daily, ${KEEP_WEEKLY} weekly)." log "Applying retention policy (${KEEP_DAILY} daily, ${KEEP_WEEKLY} weekly)."
@@ -92,6 +139,8 @@ rotate_old() {
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
log "=== Starting backup run: $NOW ===" log "=== Starting backup run: $NOW ==="
check_mount check_mount
ensure_uas_quirk
disable_spindown
# Fail early if the backup base directory doesn't exist (drive not mounted / path wrong) # Fail early if the backup base directory doesn't exist (drive not mounted / path wrong)
[ -d "$BACKUP_BASE" ] || die "Backup base directory $BACKUP_BASE does not exist." [ -d "$BACKUP_BASE" ] || die "Backup base directory $BACKUP_BASE does not exist."