Stores: directory¶
'STORE': {
'BACKEND': 'offsite_backup.stores.filesystem.DirectoryStore',
'ROOT': '/backups',
},
A directory on disk, or a Docker volume mounted into the container that runs the backup. No extra, no driver.
The same object names as on S3 (<ROOT>/<PREFIX>/<kind>/<stamp>...), the same
encryption, the same whole-night rotation, the same morning check.
What it is not¶
No immutability. Whoever can write to the directory can delete from it — the
application, anyone who gets a shell in its container, and a mistaken rm -r. Kept on
the machine it protects, it answers "somebody dropped a table", not "the machine is gone"
and not "somebody got in". manage.py check says so on every start:
?: (offsite_backup.W001) OFFSITE_BACKUP['STORE'] is a directory: backups there can be deleted by whoever can write to it.
HINT: Fine for a fast local copy; keep the disaster copy in an S3 store with Object Lock.
That is a warning, not an error, on purpose: a directory store is a legitimate choice for
a staging machine, or for a disk that is in fact mounted from elsewhere. Silence it with
SILENCED_SYSTEM_CHECKS = ['offsite_backup.W001'] once you have decided.
Kept beside an S3 store rather than instead of one, it is the fast copy: STORE takes a
list — a local volume for last night's restore, S3 with Object Lock for disaster, each with
its own KEEP_NIGHTS (Several stores).
How files are written¶
- Each object is copied to
<name>.part, flushed to disk, set to mode0600, and renamed into place, so a reader never sees half a file; a.partleft by a crash is ignored by listings and rotation. - Every directory the store creates,
ROOTincluded, gets mode0700; directories that already exist keep theirs. - A key that would resolve outside
ROOTis refused. - A directory keeps no history: one "version" per file, and a delete removes it.
Docker volume¶
services:
web:
volumes:
- backups:/backups
worker:
volumes:
- backups:/backups
volumes:
backups: {}
Mount it into every service that runs a pass — the worker that runs the nightly task and the service the deploy pass runs in — or each writes its own, unseen half.