Overview
The original application-backup architecture used Restic to provide encrypted, versioned snapshots, but the authoritative repository remained inside the same production-storage failure domain as the workloads it protected.
That provided useful version history and protection from some logical failures, but it did not provide sufficient separation for disaster recovery.
The migration moved the authoritative recovery chain to an external Windows-hosted backup tier while preserving the existing production application architecture.
The central engineering objective was not simply to move backup files to another machine. It was to make a successful backup prove that data had reached the intended independent recovery tier through the expected security controls and could subsequently be restored.
The problem
The original architecture effectively coupled production state and authoritative recovery:
production applications
+
authoritative Restic repository
↓
same production storage failure domain
A sufficiently severe production-host or storage failure could therefore affect both the workload and its primary recovery repository.
Restic itself was not the weakness.
The problem was the location and failure-domain coupling of the authoritative repository.
Design constraints
The migration had to improve recovery independence without weakening existing controls or rebuilding production simply to simplify the project.
Key constraints included:
- production applications could not be deleted or recreated merely for the migration;
- the Docker host had to preserve its normal production network identity;
- Windows file sharing could not be opened broadly to the application network;
- backup credentials had to remain outside Git;
- backup workflows had to fail if the intended external tier was unavailable;
- database-backed applications required application-consistent capture;
- the previous repository had to remain available temporarily as rollback evidence;
- acceptance required a successful restore, not merely a successful backup.
These constraints made the project a recovery-architecture change rather than a simple storage migration.
Architecture change
The resulting recovery path became:
application state
↓
application-aware staging
↓
integrity validation
↓
fail-closed mount verification
↓
narrow firewall path
↓
encrypted SMB 3.1.1 transport
↓
independent backup tier
↓
Restic repository
↓
isolated restore validation
The backup tier is independent from the production Docker storage failure domain.
It is intentionally not described as a geographically independent disaster-recovery site because the Windows host also performs other administrative roles.
Dedicated backup identity
The production host uses a separate backup-only network identity in addition to its normal production identity.
This allows network policy to express a narrow dependency:
backup identity
↓
backup endpoint
↓
TCP/445
rather than granting an entire application zone access to Windows file sharing.
Normal application traffic, administration, reverse-proxy communication, and Internet egress continue to use the production identity.
The result is a backup transport path that can be identified, restricted, and audited independently from ordinary application traffic.
Narrow firewall policy
The backup path is treated as an explicit infrastructure exception.
Only the required backup source, destination, and service are allowed.
This prevents the recovery requirement from becoming justification for broad east-west access between the production application environment and the Windows administrative host.
The network rule therefore supports the recovery architecture without weakening the surrounding segmentation model.
Encrypted transport
Backup transport uses SMB 3.1.1 with encryption required.
The Linux side incorporates controls including:
- dedicated backup source identity;
- root-controlled credentials;
- hardened CIFS mount options;
nosuid;nodev;noexec;- systemd-managed automount behavior.
The Windows side uses a dedicated service identity constrained to the required backup share.
Credentials and other operational authentication material remain outside the public repository and website.
Fail-closed mount validation
One of the most important controls is proving that the apparent backup directory is actually the intended external recovery tier.
A local directory can still exist when a remote filesystem is absent.
Without additional validation, a backup process can therefore appear successful while writing data back onto production-local storage.
The mount guard checks properties such as:
- expected remote source;
- CIFS filesystem type;
- expected mount point;
- expected source identity;
- SMB version;
- transport encryption;
- a sentinel identifying the correct backup root.
The required safety behavior is:
correct external mount
↓
backup may proceed
missing, wrong, or insecure mount
↓
backup fails
There is no acceptable silent fallback to Docker-local storage.
Application-aware staging
The migration preserved application consistency rather than reducing backup to a recursive filesystem copy.
The recovery chain includes patterns such as:
- application configuration and data archives;
- PostgreSQL logical dumps for database-backed applications;
- source-control-service-aware backup handling;
- application-specific capture where required;
- SHA-256 integrity manifests;
- completion-marker validation.
Raw staging is temporary.
Restic remains responsible for encrypted, versioned retention after the staging set has been validated.
Rollback preservation
The former same-host Restic repository was not immediately deleted during migration.
Instead, it became a frozen rollback artifact.
It ceased to be an authoritative production backup destination and does not participate in normal:
backup
forget
prune
init
operations.
This preserves migration rollback evidence without allowing the environment to drift back into two competing authoritative recovery paths.
Validation
Acceptance required validation of the full recovery chain.
Positive checks included:
- dedicated backup identity present;
- normal production routing preserved;
- narrow TCP/445 policy confirmed;
- SMB encryption confirmed;
- mount guard succeeds against the intended tier;
- application-aware staging completes;
- integrity manifest validates;
- Restic repository check succeeds;
- manual backup succeeds;
- scheduled backup succeeds;
- historical snapshots remain available;
- isolated restore succeeds.
Negative validation was equally important.
The design also verifies conditions such as:
invalid mount
-> backup must fail
missing sentinel
-> backup must fail
wrong SMB source
-> backup must fail
local fallback
-> must not be used
The isolated restore test served as the final acceptance point for the new recovery tier.
Operational outcome
The authoritative recovery chain is now:
application state
-> application-aware staging
-> integrity validation
-> encrypted external transport
-> Restic snapshot
-> retention maintenance
-> isolated restore validation
The active Restic repository resides outside the production Docker storage failure domain.
The old same-host repository remains only as governed migration rollback evidence during its retirement process.
Engineering lessons
A backup path needs identity
Giving backup transport a dedicated source identity makes firewall policy narrower and easier to audit.
A mount point does not prove recovery independence
The existence of a directory proves very little.
Validating the remote source, filesystem, source identity, encryption, and sentinel prevents a dangerous false-success condition.
Recovery systems require security controls
Backup repositories contain concentrated application data.
Transport encryption, constrained service identities, narrow firewall policy, root-controlled credentials, and mount hardening are therefore part of the security architecture rather than optional storage features.
A snapshot is not the acceptance criterion
A successful Restic snapshot proves that data was written.
A successful isolated restore demonstrates that the recovery chain can return usable recovery artifacts.
Rollback and production authority are different concepts
Preserving the old repository during migration reduced migration risk.
Freezing it prevented that rollback artifact from silently becoming a second active production backup system.
Detailed evidence
The public Homelab Security Portfolio contains the detailed sanitized implementation evidence for this project, including:
- the full backup migration case study;
- current backup and recovery architecture;
- trust-boundary documentation;
- security design principles;
- the independent-backup-failure-domain architecture decision.