This container reads your Smallstep step-ca Badger database with step-badger and automatically updates a BookStack page with a clear certificate list.
  • Python 84.1%
  • Shell 11.3%
  • Dockerfile 4.6%
Find a file
2025-09-05 14:53:19 +02:00
docker-compose.yml Version 1.0.0 2025-09-05 12:01:47 +02:00
Dockerfile Version 1.0.0 2025-09-05 12:01:47 +02:00
entrypoint.sh Version 1.0.0 2025-09-05 14:53:19 +02:00
README.md Version 1.0.0 2025-09-05 14:53:19 +02:00
step-badger_6.5.0 Version 1.0.0 2025-09-05 12:01:47 +02:00
sync.py Version 1.0.0 2025-09-05 14:53:19 +02:00

🔗 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 ondisk copy avoids Badger DB lock errors while step-ca is running.


Prerequisites

  1. BookStack API token (Admin → SettingsAPICreate Token). Note Token ID and Token Secret.
  2. A BookStack page to host the tables. Note the page ID (visible in the URL, e.g. /pages/123).
  3. 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 LeftWARN_DAYS
    • Red when Days LeftCRIT_DAYS

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 LeftWARN_DAYS.
CRIT_DAYS 10 Red when Days LeftCRIT_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 (adhoc)

# 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 tokens permissions. The token must be allowed to update the target page.


Customize

  • Schedule: CRON_SCHEDULE (cron syntax)
  • Title: set TABLE_TITLE to 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 .env file 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:tokensecret

Then in docker-compose.yml use env_file: [.env].


Author


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 .