Archive and State Bundle
The hub cluster holds the complete DR configuration: protection plans, paths, and applications. To survive the loss of the hub itself, dr-hub writes this state as a signed DR state bundle to an
S3 archive. The same archive stores the report of every finished recovery action and test.
The archive is configured in DRConfig.spec.archive. Without an archive, no bundles and no reports are written, and
finished runs are never pruned from the hub.
The archive bucket is separate from the DR metadata buckets of the sites, which hold the Kubernetes objects of the protected applications, and from the simplyblock backup buckets of the storage clusters, which hold volume data. See S3 Buckets.
What the Archive Contains
All keys are written below the configured prefix (default dr/):
| Key | Content |
|---|---|
<prefix>bundle/<generation>.tar |
One DR state bundle per state generation. |
<prefix>bundle/<generation>.sig |
The ed25519 signature of the bundle. |
<prefix>reports/<namespace>/<kind>/<yyyy>/<mm>/<completed>-<name>-<uid>.pdf |
The report of a finished recovery action or test, as PDF. |
<prefix>reports/<namespace>/<kind>/<yyyy>/<mm>/<completed>-<name>-<uid>.json |
The same report as JSON (schema: dr.simplyblock.io/report/v1). |
A DR state bundle contains:
- DR configuration: The
DRConfigand all DR objects (protection plans, DR paths, protected applications, recovery plans, and test schedules). - Sites: The managed clusters the hub expects.
- Generated Recipes: The Recipes generated for protected applications.
A bundle never contains Secrets and no finished runs. The S3 credentials, the archive credential, and the signing key must be kept in a separate, safe location and restored manually after a hub loss (see Recovering the Hub).
The hub checks every 5 minutes (bundle.interval) whether its DR state has changed and writes a new bundle only when
it has.
Preparing the Signing Key
Every bundle is signed with an ed25519 key. When the hub is rebuilt, dr-restore refuses any bundle that does not
verify against the public key. The key pair is generated with dr-restore keygen. The dr-restore binary is part of
the dr-hub image:
mkdir -p keys
docker run --rm --entrypoint dr-restore -v "$PWD/keys:/keys" \
quay.io/simplyblock-io/dr-hub:<version> keygen -out /keys
The command writes bundle-signing.key (the private key, PKCS#8 PEM) and bundle-signing.pub (the public key) and
prints the key fingerprint.
Creating the Secrets
The archive needs two Secrets in the dr-simplyblock namespace: the S3 credential the hub writes with, and the
private signing key.
kubectl -n dr-simplyblock create secret generic dr-archive \
--from-literal=AWS_ACCESS_KEY_ID=<access key id> \
--from-literal=AWS_SECRET_ACCESS_KEY=<secret access key>
kubectl -n dr-simplyblock create secret generic dr-bundle-key \
--from-file=ed25519.key=keys/bundle-signing.key
The signing key must be stored under the key ed25519.key.
Configuring the Archive
The archive is set in the hub chart values (drConfig.spec.archive) or directly in the DRConfig:
apiVersion: dr.simplyblock.io/v1alpha1
kind: DRConfig
metadata:
name: default
spec:
archive:
endpoint: s3.eu-central-1.amazonaws.com
bucket: dr-archive
region: eu-central-1
prefix: dr/
credentialsSecretRef:
name: dr-archive
reportRetainDays: 0
bundle:
interval: 5m
retainDays: 30
signingKeySecretRef:
name: dr-bundle-key
retention:
days: 90
keepPerApplication: 10
| Field | Default | Description |
|---|---|---|
archive.endpoint |
Required | S3 endpoint as host[:port], without a scheme. Any S3-compatible object store is supported. |
archive.bucket |
Required | Archive bucket. |
archive.region |
Empty | Bucket region. |
archive.prefix |
dr/ |
Prefix of every key. |
archive.insecure |
false |
Uses plain HTTP instead of HTTPS. |
archive.credentialsSecretRef.name |
Required | Secret in the dr-simplyblock namespace with AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. |
archive.reportRetainDays |
0 |
Object lock retention of each report in days. 0 writes reports without an object lock. |
archive.bundle.disabled |
false |
Stops writing bundles. Reports are still written. |
archive.bundle.interval |
5m |
How often the hub checks its DR state for changes. |
archive.bundle.retainDays |
30 |
Object lock retention of each bundle in days. Requires a bucket with object lock enabled. |
archive.bundle.signingKeySecretRef.name |
Required | Secret in the dr-simplyblock namespace with the private key under ed25519.key. |
The DRConfig status shows the last bundle written:
kubectl get drconfig default -o jsonpath='{.status.lastBundle}'
Object Lock
Object lock makes bundles and reports immutable for their retention period, so that neither an operator error nor
an attacker with the hub's credentials can delete them. Bundles are written with compliance-mode object lock for
bundle.retainDays days, reports with reportRetainDays days.
- Bucket setting: Object lock must be enabled when the bucket is created. It cannot be added to most existing buckets. Versioning is required for object lock.
- Without object lock: Disaster recovery works without object lock, but recovering the hub after a ransomware attack relies on bundles the attacker could not delete.
- Compliance mode: Objects under compliance-mode lock cannot be deleted before their retention expires, not even by the bucket owner. The retention periods should be chosen accordingly.
Note
dr-hub does not check the bucket settings. A bucket without object lock accepts the bundles, but the retention
is not enforced.
Retention of Finished Runs
Finished recovery actions and tests stay on the hub as Kubernetes objects so that their status and reports remain
visible. DRConfig.spec.retention bounds how many are kept:
- Keep per application: The newest
keepPerApplicationruns (default 10) of each application or recovery plan are always kept, whatever their age. - Age: Older runs are deleted after
daysdays (default 90), but only after their report is in the archive. - Without archive: Without an archive, finished runs are never pruned.
Safekeeping the Restore Material
The hub writes to the archive with its own credential. A hub rebuild reads from the archive with a separate credential. The following material must be kept offline, outside the hub and outside the sites:
- Public key:
bundle-signing.pub, used bydr-restoreto verify a bundle. - Read credential: An S3 credential that can read the archive bucket. Ideally, the hub's own credential is write-only and cannot read or delete bundles.
- Secrets: The archive credential, the signing key, and the DR metadata credential, which are not part of the bundle.
The private signing key bundle-signing.key is only needed again when the hub is rebuilt. It should be stored with
the same care as the other Secrets.