Deployment automation for the Keylime Monitoring Dashboard. Containerfiles, Podman Compose, and scripts for plug-and-play provisioning of the frontend, backend, and supporting services.
Browser ──TLS 1.3──▶ Reverse Proxy (:8443)
├── / → Frontend (static files)
└── /api/*, /ws → Backend (:8080)
├── mTLS → Keylime Verifier (:8881)
├── mTLS → Keylime Registrar (:8891)
├── TCP → TimescaleDB (:5432)
└── TCP → Redis (:6379)
| Service | Image | Role |
|---|---|---|
| frontend | keylime-webtool-frontend |
nginx reverse proxy + React SPA |
| backend | keylime-webtool-backend |
Rust/Axum REST + WebSocket API |
| timescaledb | timescale/timescaledb |
Attestation event time-series store |
| redis | redis:7-alpine |
Response cache with tiered TTLs |
| Tool | Minimum Version | Install (Fedora/RHEL) |
|---|---|---|
| Podman | 4.0+ | sudo dnf install podman |
| podman-compose | 1.0+ | pip install podman-compose |
| OpenSSL | 3.0+ | Installed by default on RHEL 9 / Fedora 40+ |
| Make | any | sudo dnf install make |
git clone https://github.com/keylime-webtool/keylime-webtool-deploy.git
cd keylime-webtool-deploy
make setupThat single command will:
- Verify
podmanandpodman-composeare installed - Copy
.env.exampleto.env(if missing) - Generate self-signed TLS certificates (if missing)
- Build OCI images for the frontend and backend
- Start all services
The dashboard is then available at https://localhost:8443.
All configuration is managed through environment variables in .env. See .env.example for the full list with documentation.
| Variable | Default | Description |
|---|---|---|
HOST_HTTPS_PORT |
8443 |
Host port for the HTTPS frontend |
KEYLIME_VERIFIER_URL |
https://localhost:8881 |
Keylime Verifier API endpoint |
KEYLIME_REGISTRAR_URL |
https://localhost:8891 |
Keylime Registrar API endpoint |
TLS_CERT_PATH |
./certs/tls.crt |
Path to TLS certificate |
TLS_KEY_PATH |
./certs/tls.key |
Path to TLS private key |
KEYLIME_CA_CERT |
./certs/keylime-ca.crt |
Keylime CA certificate |
KEYLIME_CLIENT_CERT |
./certs/keylime-client.crt |
Keylime client certificate |
KEYLIME_CLIENT_KEY |
./certs/keylime-client.key |
Keylime client key |
POSTGRES_DB |
keylime_dashboard |
TimescaleDB database name |
POSTGRES_USER |
keylime |
TimescaleDB user |
POSTGRES_PASSWORD |
changeme |
TimescaleDB password |
DATABASE_URL |
postgresql://keylime:... |
Full connection string for the backend |
REDIS_URL |
redis://redis:6379 |
Redis connection string |
RUST_LOG |
info |
Backend log level |
make help # Show all targets
make setup # One-command bootstrap
make build # Build/rebuild OCI images
make up # Start services
make down # Stop services (keep data)
make logs # View logs (ARGS="-f" to follow, ARGS="backend" for one service)
make health # Check service health
make certs # Generate self-signed TLS certificates
make clean # Full reset: stop, remove volumes, images, and certs
Replace the self-signed certificates with real ones:
# Edit .env to point to your real certificates
TLS_CERT_PATH=/path/to/production.crt
TLS_KEY_PATH=/path/to/production.keyMount the mTLS certificates issued by your Keylime CA:
KEYLIME_CA_CERT=/path/to/keylime/cacert.crt
KEYLIME_CLIENT_CERT=/path/to/keylime/client.crt
KEYLIME_CLIENT_KEY=/path/to/keylime/client.keySet a strong password and update the DATABASE_URL to match:
POSTGRES_PASSWORD=<strong-random-password>
DATABASE_URL=postgresql://keylime:<strong-random-password>@timescaledb:5432/keylime_dashboardAdd resource limits in a compose.override.yaml:
services:
backend:
deploy:
resources:
limits:
cpus: "2.0"
memory: 512M
timescaledb:
deploy:
resources:
limits:
cpus: "2.0"
memory: 1GFor environments without internet access, pre-build and transfer images as OCI archives.
On a connected machine:
make build
podman save -o keylime-frontend.tar keylime-webtool-frontend:latest
podman save -o keylime-backend.tar keylime-webtool-backend:latest
podman save -o timescaledb.tar docker.io/timescale/timescaledb:latest-pg16
podman save -o redis.tar docker.io/library/redis:7-alpineTransfer the .tar files to the air-gapped host, then:
podman load -i keylime-frontend.tar
podman load -i keylime-backend.tar
podman load -i timescaledb.tar
podman load -i redis.tar
cp .env.example .env
# Edit .env with production values
podman-compose up -dServices won't start:
make health # Check which service is unhealthy
make logs ARGS="backend" # Check specific service logs
podman ps -a # Check container states"Permission denied" on certificate files:
SELinux may block volume mounts. The compose file uses the :Z label, but if issues persist:
sudo setsebool -P container_manage_cgroup onTimescaleDB init.sql not applied:
The init script only runs on first container start. To re-initialize:
make clean # Removes volumes
make up # Fresh start with init.sqlPort 8443 already in use:
Change HOST_HTTPS_PORT in .env:
HOST_HTTPS_PORT=9443
make upFrontend shows "502 Bad Gateway":
The backend hasn't finished starting. Check its health:
make health
make logs ARGS="backend"Apache-2.0 — see LICENSE.