Understanding Snapshots
Snapshots are one of mirrorctl’s key features. They allow you to maintain multiple versions of your repository, enabling rollback, reproducible builds, and safe testing of updates before deploying to production.
What Are Snapshots?
A snapshot is a point-in-time copy of your mirror. mirrorctl creates snapshots using hardlinks, which means:
- Snapshots take minimal additional disk space (only new/changed files consume extra space)
- Snapshots are created instantly, even for large repositories
- Each snapshot is a complete, consistent view of the repository at a specific time
Think of snapshots like Git commits for your mirror - each one captures the exact state at a moment in time.
Why Use Snapshots?
Snapshots enable several important capabilities:
- Rollback: If an update breaks something, quickly revert to a previous working version
- Testing: Test new mirror content in staging before promoting to production
- Reproducible builds: Pin build environments to specific snapshot versions
- Zero-downtime updates: Switch between versions atomically via symlink changes
- Audit trail: Maintain a history of repository changes over time
Enabling Automatic Snapshots
Update your /etc/mirrorctl/mirror.toml configuration to enable automatic snapshot creation after each sync:
# Base directory for all mirrored repositories
dir = "/var/www/apt/"
# Snapshot configuration
[snapshot]
path = "/var/lib/mirrorctl/snapshots"
default_name_format = "2006-01-02T15-04-05Z" # Timestamp format
[snapshot.prune]
keep_last = 5 # Keep the 5 most recent snapshots
# Mirror configuration
[mirrors.ubuntu-noble]
url = "https://archive.ubuntu.com/ubuntu/"
suites = ["noble"]
sections = ["main"]
architectures = ["amd64"]
publish_to_staging = false # We'll enable this in the next sectionThe default_name_format uses Go’s time format. The example format creates names like:
2025-10-14T09-30-45Z2025-10-15T14-22-10Z
Understanding the snapshot path
The snapshot.path setting determines where snapshots are stored. The default is /var/lib/mirrorctl/snapshots.
For our ubuntu-noble mirror, snapshots will be stored at:
/var/lib/mirrorctl/snapshots/ubuntu-noble/2025-10-14T09-30-45Z/Each snapshot is a complete mirror structure with dists/ and pool/ directories.
Create Your First Snapshot
Create the snapshot directory:
sudo mkdir -p /var/lib/mirrorctl/snapshotsNow run a sync. mirrorctl will automatically create a snapshot after syncing:
sudo mirrorctl sync ubuntu-nobleYou’ll see additional output about snapshot creation:
INFO Starting sync for mirror: ubuntu-noble
INFO Downloading Release file
...
INFO Sync completed successfully for ubuntu-noble
INFO Creating snapshot: 2025-10-14T09-30-45Z
INFO Snapshot created successfullyList Your Snapshots
View all snapshots for a mirror:
mirrorctl snapshot list ubuntu-nobleOutput:
MIRROR SNAPSHOT NAME CREATED SIZE
ubuntu-noble 2025-10-14T09-30-45Z 2025-10-14 09:30:45 45.3 GBWhere are snapshots stored?
Check the snapshot directory structure:
ls -l /var/lib/mirrorctl/snapshots/ubuntu-noble/You’ll see:
drwxr-xr-x. 2025-10-14T09-30-45ZEach snapshot directory contains a complete mirror:
tree -L 2 /var/lib/mirrorctl/snapshots/ubuntu-noble/2025-10-14T09-30-45Z//var/lib/mirrorctl/snapshots/ubuntu-noble/2025-10-14T09-30-45Z/
├── dists
│ └── noble
└── pool
└── mainCreate Additional Snapshots
Run another sync to create a second snapshot:
sudo mirrorctl sync ubuntu-nobleSince the mirror hasn’t changed much, the sync will be quick:
INFO Starting sync for mirror: ubuntu-noble
INFO Checking for updates
INFO 42 new packages available
INFO Downloading 42 packages
INFO Sync completed successfully for ubuntu-noble
INFO Creating snapshot: 2025-10-15T14-22-10Z
INFO Snapshot created successfullyList snapshots again:
mirrorctl snapshot list ubuntu-nobleMIRROR SNAPSHOT NAME CREATED SIZE
ubuntu-noble 2025-10-15T14-22-10Z 2025-10-15 14:22:10 45.4 GB
ubuntu-noble 2025-10-14T09-30-45Z 2025-10-14 09:30:45 45.3 GBNotice the second snapshot only added 100 MB despite being a “complete” copy - this is the efficiency of hardlinks!
Manual Snapshot Creation
You can also create snapshots manually without syncing:
mirrorctl snapshot create ubuntu-nobleThis creates a snapshot of the current mirror state with an auto-generated name.
Or specify a custom name:
mirrorctl snapshot create ubuntu-noble "before-upgrade"Custom names are useful for marking significant events:
"before-upgrade""known-good-config""2025-q1-baseline"
Snapshot Pruning
Over time, you’ll accumulate many snapshots. The keep_last setting in your config automatically prunes old snapshots when creating new ones.
With keep_last = 5, only the 5 most recent snapshots are retained. When a 6th snapshot is created, the oldest is automatically deleted.
You can also manually prune snapshots:
mirrorctl snapshot prune ubuntu-nobleThis applies the retention policy configured in your TOML file.
Advanced pruning configuration
You can use time-based retention instead of count-based:
[snapshot.prune]
keep_within = "30d" # Keep snapshots from the last 30 daysOr combine both:
[snapshot.prune]
keep_last = 5 # Keep at least 5 recent snapshots
keep_within = "30d" # Also keep anything within 30 daysThis ensures you keep at least 5 snapshots, but also preserve all snapshots from the last 30 days (even if that’s more than 5).
Deleting Specific Snapshots
To delete a specific snapshot:
mirrorctl snapshot delete ubuntu-noble "2025-10-14T09-30-45Z"Use this carefully - deleted snapshots cannot be recovered!
Snapshots vs. Working Mirror
It’s important to understand the relationship:
- Working mirror (
/var/www/apt/ubuntu-noble/): The actively synced repository - Snapshots (
/var/lib/mirrorctl/snapshots/ubuntu-noble/*/): Frozen point-in-time copies
When you run mirrorctl sync, it updates the working mirror. If snapshots are enabled, it then creates a snapshot of that updated state.
The working mirror is what gets updated. Snapshots are created from it and never change.
What’s Next?
Now that you understand snapshots, learn how to use them in a Staging and Production Workflow for safe, tested mirror updates.