# Findings Ledger Offline Kit This directory contains manifests and scripts for deploying Findings Ledger in air-gapped/offline environments. ## Contents ``` offline-kit/ ├── README.md # This file ├── manifest.yaml # Offline bundle manifest ├── images/ # Container image tarballs (populated at build) │ └── .gitkeep ├── migrations/ # Database migration scripts │ └── .gitkeep ├── dashboards/ # Grafana dashboard JSON exports │ └── findings-ledger.json ├── alerts/ # Prometheus alert rules │ └── findings-ledger-alerts.yaml └── scripts/ ├── import-images.sh # Load container images ├── run-migrations.sh # Apply database migrations └── verify-install.sh # Post-install verification ``` ## Building the Offline Kit Use the platform offline kit builder: ```bash # From repository root python ops/offline-kit/build_offline_kit.py \ --include ledger \ --version 2025.11.0 \ --output dist/offline-kit-ledger-2025.11.0.tar.gz ``` ## Installation Steps ### 1. Transfer and Extract ```bash # On air-gapped host tar xzf offline-kit-ledger-*.tar.gz cd offline-kit-ledger-* ``` ### 2. Load Container Images ```bash ./scripts/import-images.sh # Loads: stellaops/findings-ledger, stellaops/findings-ledger-migrations ``` ### 3. Run Database Migrations ```bash export LEDGER__DB__CONNECTIONSTRING="Host=...;Database=...;..." ./scripts/run-migrations.sh ``` ### 4. Deploy Service Choose deployment method: **Docker Compose:** ```bash cp ../compose/env/ledger.prod.env ./ledger.env # Edit ledger.env with local values docker compose -f ../compose/docker-compose.ledger.yaml up -d ``` **Helm:** ```bash helm upgrade --install findings-ledger ../helm \ -f values-offline.yaml \ --set image.pullPolicy=Never ``` ### 5. Verify Installation ```bash ./scripts/verify-install.sh ``` ## Configuration Notes ### Sealed Mode In air-gapped environments, configure: ```yaml # Disable outbound attachment egress LEDGER__ATTACHMENTS__ALLOWEGRESS: "false" # Set appropriate staleness thresholds LEDGER__AIRGAP__ADVISORYSTALETHRESHOLD: "604800" # 7 days LEDGER__AIRGAP__VEXSTALETHRESHOLD: "604800" LEDGER__AIRGAP__POLICYSTALETHRESHOLD: "86400" # 1 day ``` ### Merkle Anchoring For offline environments without external anchoring: ```yaml LEDGER__MERKLE__EXTERNALIZE: "false" ``` Keep local Merkle roots and export periodically for audit. ## Backup & Restore See `docs/modules/findings-ledger/deployment.md` for full backup/restore procedures. Quick reference: ```bash # Backup pg_dump -Fc --dbname="$LEDGER_DB" --file ledger-$(date -u +%Y%m%d).dump # Restore pg_restore -C -d postgres ledger-YYYYMMDD.dump # Replay projections dotnet run --project tools/LedgerReplayHarness -- \ --connection "$LEDGER_DB" --tenant all ``` ## Observability Import the provided dashboards into your local Grafana instance: ```bash # Import via Grafana API or UI curl -X POST http://grafana:3000/api/dashboards/db \ -H "Content-Type: application/json" \ -d @dashboards/findings-ledger.json ``` Apply alert rules to Prometheus: ```bash cp alerts/findings-ledger-alerts.yaml /etc/prometheus/rules.d/ # Reload Prometheus ``` ## Troubleshooting | Issue | Resolution | | --- | --- | | Migration fails | Check DB connectivity; verify user has CREATE/ALTER privileges | | Health check fails | Check logs: `docker logs findings-ledger` or `kubectl logs -l app.kubernetes.io/name=findings-ledger` | | Metrics not visible | Verify OTLP endpoint is reachable or use Prometheus scrape | | Staleness warnings | Import fresh advisory/VEX bundles via Mirror | ## Support - Platform docs: `docs/modules/findings-ledger/` - Offline operation: `docs/24_OFFLINE_KIT.md` - Air-gap mode: `docs/airgap/`