Import now supports three sources: server-side path (USB/NFS volumes), backend URL download, and browser file upload. Export/import workflows refactored from routed pages to overlay dialogs. Docs updated with volume mount instructions and source comparison table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.3 KiB
Concelier Air-Gap Bundle Deploy Runbook (CONCELIER-AIRGAP-56-003)
Status: draft · 2025-11-24 Scope: deploy sealed-mode Concelier evidence bundles using deterministic NDJSON + manifest/entry-trace outputs.
Inputs
- Bundle:
concelier-airgap.ndjson - Manifest:
bundle.manifest.json - Entry trace:
bundle.entry-trace.json - Hashes: SHA256 recorded in manifest and entry-trace; verify before import.
Preconditions
- Concelier WebService running with
concelier:features:airgapenabled. - No external egress; only local file system allowed for bundle path.
- PostgreSQL indexes applied (
advisory_observations,advisory_linksetstables). - Import volume mounted: The Concelier container must have the import staging directory mounted. In Docker Compose this is configured via
STELLAOPS_AIRGAP_IMPORT_DIR(defaults to./airgap-importon the host, mounted read-only at/var/lib/concelier/importinside the container).
Import Volume Setup (Docker Compose)
The Concelier service mounts an import staging volume for air-gapped bundle ingestion.
Bundles placed on the host at $STELLAOPS_AIRGAP_IMPORT_DIR are visible inside the container at /var/lib/concelier/import/.
# Default: ./airgap-import relative to the compose directory
mkdir -p devops/compose/airgap-import
# Override: point to USB, NFS mount, or any host directory
export STELLAOPS_AIRGAP_IMPORT_DIR=/media/usb/stellaops-bundles
docker compose -f docker-compose.stella-ops.yml up -d concelier
The volume is mounted read-only — the Concelier service reads and validates bundles but never modifies the staging directory. The environment variable CONCELIER_IMPORT__STAGINGROOT tells the service where to find staged bundles inside the container.
UI Console Import
The Feeds & Airgap console (Ops → Operations → Feeds & Airgap → Airgap Bundles → Import) supports three import sources:
| Source | Description | Volume needed? |
|---|---|---|
| Server Path | Path inside the container (e.g. /var/lib/concelier/import/bundle.tar.gz). Zero browser transfer. |
Yes |
| URL | Internal URL the backend downloads directly. | No |
| File Upload | Browser drag-and-drop for small bundles. | No |
For large bundles (GB+), use Server Path or URL — never browser upload.
Steps
- Stage the bundle onto the import volume (or transfer to the offline controller host).
- Verify hashes:
sha256sum concelier-airgap.ndjson | diff - <(jq -r .bundleSha256 bundle.manifest.json) jq -r '.[].sha256' bundle.entry-trace.json | nl | sed 's/\t/:/' > entry.hashes paste -d' ' <(cut -d: -f1 entry.hashes) <(cut -d: -f2 entry.hashes) - Import:
curl -sSf -X POST \ -H 'Content-Type: application/x-ndjson' \ --data-binary @concelier-airgap.ndjson \ http://localhost:5000/internal/airgap/import - Validate import:
curl -sSf http://localhost:5000/internal/airgap/status | jq - Record evidence:
- Store manifest + entry-trace alongside TRX/logs in
artifacts/airgap/<date>/.
- Store manifest + entry-trace alongside TRX/logs in
Determinism notes
- NDJSON ordering is lexicographic; do not re-sort downstream.
- Entry-trace hashes must match post-transfer; any mismatch aborts import.
Rollback
- Delete imported batch by
bundleIdfromadvisory_observationsandadvisory_linksets(requires DBA approval); rerun import after fixing hash.