- Python 84.1%
- Shell 11.3%
- Dockerfile 4.6%
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| README.md | ||
| step-badger_6.5.0 | ||
| sync.py | ||
🔗 Step-CA to Bookstack
This container reads your Smallstep step-ca Badger database with step-badger and automatically updates a BookStack page with a clear certificate list.
What you get
- Two tables on your BookStack page:
- Expired (includes REVOKED)
- Active
- Sorted by End (expiry) ascending
- Row highlighting close to expiry (yellow/red; days & colors are configurable)
- Time format: dd.mm.yyyy hh:mm (local time)
The container reads your data read-only. A temporary on‑disk copy avoids Badger DB lock errors while
step-cais running.
Prerequisites
- BookStack API token (Admin → Settings → API → Create Token). Note Token ID and Token Secret.
- A BookStack page to host the tables. Note the page ID (visible in the URL, e.g.
/pages/123). - step-ca data directory mounted into the container with the Badger DB (files like
MANIFEST,KEYREGISTRY,*.sst,*.vlog). Example: host/docker/step/ca/db→ container/step/db.
Quick start (Docker Compose)
Create or open docker-compose.yml and add this service:
services:
sync:
image: onesystems/step-ca-to-bookstack:latest
environment:
# When to sync? (cron, container local time)
CRON_SCHEDULE: "5 2 * * *" # daily 02:05
TZ: "Europe/Zurich"
# BookStack API
BOOKSTACK_URL: "https://wiki.example.com"
BOOKSTACK_PAGE_ID: "123" # your page ID
BOOKSTACK_TOKEN_ID: "<token-id>"
BOOKSTACK_TOKEN_SECRET: "<token-secret>"
# Alternative to the two lines above:
# BOOKSTACK_API_KEY: "<token-id>:<token-secret>"
# step-ca DB path inside the container
STEP_DB_DIR: "/step/db"
# (Optional) internal DB copy to avoid locks
DB_SNAPSHOT: "true"
TMP_BASE: "/tmp"
# (Optional) row colors / thresholds
WARN_DAYS: "30" # yellow when ≤ 30 days left
CRIT_DAYS: "10" # red when ≤ 10 days left
WARN_BG: "#fff6bf"
CRIT_BG: "#ffd6d6"
# (Optional) title above the tables (leave empty to hide)
TABLE_TITLE: "step-ca certificates"
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/step/ca:/step:ro # must contain directory "db"
restart: unless-stopped
Start the service:
docker compose up -d
Watch logs:
docker compose logs -f sync
On first start the page is updated immediately, then according to the schedule.
What appears on the page?
- A timestamp line: Generated: …
- Expired table (expired or revoked certificates)
- Active table (currently valid certificates)
- Columns: Subject/CN, SANs, Serial, Start, End, Days Left, Provisioner, Status
- Row colors:
- Yellow when
Days Left≤ WARN_DAYS - Red when
Days Left≤ CRIT_DAYS
- Yellow when
If the target page already contains the marker block, only the content between these markers is replaced on each run:
<!-- BEGIN STEP-CA TABLE --> ... (will be replaced) ... <!-- END STEP-CA TABLE -->
Environment variables
| Variable | Default | Description |
|---|---|---|
CRON_SCHEDULE |
0 3 * * * |
Cron expression (container local time). |
BOOKSTACK_URL |
— | Base URL, e.g. https://wiki.example.com. |
BOOKSTACK_PAGE_ID |
— | Numeric ID of the page to update. |
BOOKSTACK_TOKEN_ID |
— | BookStack API token ID. |
BOOKSTACK_TOKEN_SECRET |
— | BookStack API token secret. |
BOOKSTACK_API_KEY |
— | Alternative to the two vars above: id:secret. |
STEP_DB_DIR |
/step/db |
Path to step-ca Badger DB inside the container. |
DB_SNAPSHOT |
true |
If true, copy DB to a temp folder before reading (avoids lock). |
TMP_BASE |
/tmp |
Base folder for the temporary DB copy. Ensure enough space. |
TABLE_TITLE |
step-ca certificates |
Heading above the tables (set empty to hide). |
WARN_DAYS |
30 |
Yellow when Days Left ≤ WARN_DAYS. |
CRIT_DAYS |
10 |
Red when Days Left ≤ CRIT_DAYS. |
WARN_BG |
#fff8d5 |
CSS color for “warn” rows. |
CRIT_BG |
#ffe5e5 |
CSS color for “crit” rows. |
INCLUDE_EXPIRED |
true |
Kept for compatibility; not used (both tables are rendered). |
Run once now (ad‑hoc)
# Run the sync script inside the running container
docker exec -it <container> /usr/bin/python3 /app/sync.py
# Tail cron output
docker exec -it <container> sh -c 'tail -n 200 /var/log/cron.log'
Troubleshooting
“Cannot acquire directory lock … Another process is using this Badger database.”
This is expected while step-ca is running. Keep DB_SNAPSHOT=true and ensure there is free space under TMP_BASE (default /tmp).
Empty columns / missing values
JSON field names from step-badger may vary. The script uses a tolerant, deep lookup for common keys. If values remain empty, please verify that your mount contains the Badger files and check logs with docker compose logs -f sync.
BookStack 401/403
Double-check BOOKSTACK_URL, BOOKSTACK_PAGE_ID, and the token’s permissions. The token must be allowed to update the target page.
Customize
- Schedule:
CRON_SCHEDULE(cron syntax) - Title: set
TABLE_TITLEto empty to hide - Colors / thresholds: tune
WARN_DAYS,CRIT_DAYS,WARN_BG,CRIT_BG
Update & remove
Update:
docker compose pull sync
docker compose up -d
Stop & remove:
docker compose down
Security
- Keep tokens in a safer place, e.g. a
.envfile or Docker secrets, rather than hard-coding them in compose. - The container accesses your step-ca data read-only.
Example
.env:BOOKSTACK_URL=https://wiki.example.com BOOKSTACK_PAGE_ID=123 BOOKSTACK_API_KEY=tokenid:tokensecretThen in
docker-compose.ymluseenv_file: [.env].
Author
- Michael Kleger
OneSystems GmbH
mkleger@onesystems.ch
License
MIT License – free for commercial and private use.
Credits
- step-badger by Smallstep community.
- This mailer uses the same snapshot & parsing approach as our BookStack sync for step-ca.
Build
Multi Platform Builder
docker buildx create --use --platform=linux/arm64,linux/amd64 --name multi-platform-builder
docker buildx inspect --bootstrap
Build
docker buildx build --platform linux/amd64,linux/arm64 --push --provenance=mode=max --sbom=true --tag onesystems/step-ca-to-bookstack:v1.0.0 --tag onesystems/step-ca-to-bookstack:latest --file Dockerfile .