Repository navigation
Backups: survive a day-long first upload over a home line - #39
Merged
Merged
Conversation
The first real run died 90 seconds into a stall: ServerAliveInterval 30 x CountMax 3, five parallel restic connections saturating a home NAS, and restic cannot reconnect once its ssh exits, so the run was lost. - ssh waits five minutes of real silence (15s x 20), TCPKeepAlive on - two SFTP connections by default (BACKUP_SFTP_CONNECTIONS), and an optional upload cap for restic and the mirror (BACKUP_LIMIT_UPLOAD_KBPS) - one run at a time: an hourly tick during a long run skips itself instead of failing on the repository lock - restic unlock first, so a crashed run's stale lock clears itself README: start the first backup inside the scheduled container, and what to do when a large first upload dies (rerun; restic reuses what landed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XWoa1a1upTria7ntq56x3B
davior
marked this pull request as ready for review
October 22, 2026 03:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The first real backup run died partway through uploading media:
ssh gave up after 90 s of silence (
ServerAliveInterval 30×ServerAliveCountMax 3). Five parallel restic connections were saturating the home NAS and its line for an upload with a ~13 h ETA, so a stall that long was close to certain. restic can't reconnect once its ssh subprocess exits, so the whole run was lost. Notes' small hourly backups over the same link run cleanly.Changes
entrypoint.sh: ssh now waits through 5 minutes of real silence (ServerAliveInterval 15×ServerAliveCountMax 20) instead of 90 seconds, and setsTCPKeepAlive yes.backup.sh:flockin the container's tmpfs). An hourly tick during a long run printsprevious run still going, skippinginstead of failing on restic's repository lock.restic unlockfirst. Without--remove-allit only removes stale locks, so a crashed run can't block the next one.BACKUP_SFTP_CONNECTIONS; restic's default is 5). The mirror's rclone uses the same number of--transfers.BACKUP_LIMIT_UPLOAD_KBPS; empty means no cap).docker-compose.yml/.env.example: pass the two new settings through.exec -dinside the scheduled container, so the run lock covers it.Checked: Alpine 3.20 ships restic 0.16.4, which has the sftp
connectionsoption, and rclone 1.66.Testing
sh -npasses on both scripts.docker compose config -qpasses.backup.shlocally with restic and sqlite3 shims and rclone'slocalremote:unlockruns first, and-o sftp.connections=2is on every restic call.--limit-uploadand--bwlimitappear only when the cap is set.pytest -q: 1272 passed.npm test: 395 passed.npm run buildis clean. Neither suite is touched by this change.Generated by Claude Code