Back up application files, directories, and live SQLite databases into one archive, check it for corruption, and restore it safely
Project description
StateCrate
StateCrate adds backup and restore to Python applications. It puts selected files, directories, and consistent snapshots of live SQLite databases into one signed archive.
Before restoring anything, StateCrate checks the signer, every file, the archive layout, and each SQLite database. Unsafe paths, links, oversized archives, unexpected files, and damaged content are rejected.
StateCrate supports POSIX systems and Python 3.11 or newer.
Install
python -m pip install statecrate
Use
Create a signing key once and keep it somewhere separate from the backups:
from statecrate import SigningKey
key = SigningKey.generate()
key.save("backup-signing-key.pem")
key.verification_key.save("backup-public-key.pem")
Create a backup:
from statecrate import SigningKey, Source, backup
key = SigningKey.load("backup-signing-key.pem")
result = backup(
"application-backup.tar.gz",
[
Source.file("config.json"),
Source.directory("uploads"),
Source.sqlite("application.db"),
],
signing_key=key,
)
print(result.archive)
Check a backup without restoring it:
from statecrate import VerificationKey, verify
public_key = VerificationKey.load("backup-public-key.pem")
report = verify("application-backup.tar.gz", trusted_keys=public_key)
print(report.entries_checked)
Restore into a new directory:
from statecrate import restore
restore(
"application-backup.tar.gz",
"restored-state",
trusted_keys=public_key,
)
Pass replace=True only when the destination is an application-state directory
that StateCrate may replace completely. Unrelated files in that directory are
not preserved.
What it handles
- Live SQLite snapshots made through SQLite's backup API
- Ed25519 manifest signatures and trusted-key selection
- SHA-256 checks for every archived file
- SQLite integrity checks before creation and after extraction
- Safe paths, bounded extraction, and link rejection
- Required and optional sources
- File modes, empty directories, and custom JSON metadata
- Staged creation, self-verification, durable writes, and rollback on a failed replacement
Boundaries
Archives are signed, but they are not encrypted. Anyone who can read an archive can read its contents. Encrypt the archive separately when confidentiality is required.
StateCrate creates and restores local archive files. Scheduling, retention, remote storage, incremental backups, and application-specific consistency are outside its scope.
Replacing an existing destination is rollback-safe when the process reports an error. POSIX does not provide a portable atomic exchange for non-empty directories, so a system failure between the two directory renames can require operator recovery from the hidden staging directory.
See the archive format for the compatibility and security contract.
Development
make install
make check
StateCrate is licensed under Apache License 2.0. Contributions are welcome; see CONTRIBUTING.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file statecrate-0.1.0.tar.gz.
File metadata
- Download URL: statecrate-0.1.0.tar.gz
- Upload date:
- Size: 30.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bab7db66757cbc678f9af8ede7643c3d761de34d753f180d31e66505995d4564
|
|
| MD5 |
da97118e6afa4f836d84d2cca33bab1c
|
|
| BLAKE2b-256 |
0432951bee3b7cb8fc972e3f99995e989dc8ce8a9360f07e3a25858b74a37715
|
Provenance
The following attestation bundles were made for statecrate-0.1.0.tar.gz:
Publisher:
publish.yml on latheiere/statecrate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
statecrate-0.1.0.tar.gz -
Subject digest:
bab7db66757cbc678f9af8ede7643c3d761de34d753f180d31e66505995d4564 - Sigstore transparency entry: 2306881952
- Sigstore integration time:
-
Permalink:
latheiere/statecrate@51a9be936b64870e336385ba9ccbe177068fbaf4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/latheiere
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@51a9be936b64870e336385ba9ccbe177068fbaf4 -
Trigger Event:
release
-
Statement type:
File details
Details for the file statecrate-0.1.0-py3-none-any.whl.
File metadata
- Download URL: statecrate-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a94287fb394ba64d300689707f4c2eb8c62b29659a586152ccd236c2be8c8b23
|
|
| MD5 |
0433a17096775b483342b171c956905b
|
|
| BLAKE2b-256 |
2edefb43adc1220066e16231e20324655b7f671194328905ab716654695b4597
|
Provenance
The following attestation bundles were made for statecrate-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on latheiere/statecrate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
statecrate-0.1.0-py3-none-any.whl -
Subject digest:
a94287fb394ba64d300689707f4c2eb8c62b29659a586152ccd236c2be8c8b23 - Sigstore transparency entry: 2306881987
- Sigstore integration time:
-
Permalink:
latheiere/statecrate@51a9be936b64870e336385ba9ccbe177068fbaf4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/latheiere
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@51a9be936b64870e336385ba9ccbe177068fbaf4 -
Trigger Event:
release
-
Statement type: