Getting started
Try it locally in thirty seconds, then point it at a GitHub repo when you're ready.
Try it locally
No GitHub needed. Local mode serves and edits a plain directory.
git clone https://github.com/nullism/trunkcms
cd trunkcms
TRUNKCMS_CONTENT_DIR=./testdata/site go run ./cmd/trunkcms
Open http://localhost:8080 for the site and http://localhost:8080/admin to edit. Local mode offers three dev logins, dev-admin, dev-editor and dev-author, so you can try each role. Saves are written straight into the content directory, and edits you make to those files by hand show up within about two seconds.
Note This writes to testdata/site. Copy it somewhere first if you want to keep the fixture clean.
You can also render a content directory to static files:
go run ./cmd/trunkcms build -dir ./testdata/site -out ./public
Run against GitHub
1. Create the content repo
For example nullism/myblog. Keep it private so drafts stay hidden. It can be empty: trunkcms serves a placeholder and the dashboard offers to initialize it.
2. Create a GitHub App
In GitHub, go to Settings → Developer settings → GitHub Apps:
- Callback URL:
https://myblog.com/admin/callback - Webhook URL:
https://myblog.com/admin/webhook, with a random secret - Repository permissions: Contents, read & write. Subscribe to Push events.
- Generate a private key and a client secret, then install the App on the content repo only.
- Under Advanced, make the App public. Otherwise GitHub shows a 404 to anyone but the App’s owner when they try to sign in. Public only means other accounts can sign in through it. Access is still decided by repo permission and
users.yaml.
3. Run the image
The image is on Docker Hub as nullism/trunkcms. There’s no Dockerfile per blog: one image, configured with environment variables.
docker run -p 8080:8080 \
-e TRUNKCMS_REPO=nullism/myblog \
-e TRUNKCMS_SITE_URL=https://myblog.com \
-e TRUNKCMS_GITHUB_APP_ID=123456 \
-e TRUNKCMS_GITHUB_PRIVATE_KEY_FILE=/secrets/app.pem \
-e TRUNKCMS_GITHUB_CLIENT_ID=Iv1.abc \
-e TRUNKCMS_GITHUB_CLIENT_SECRET=... \
-e TRUNKCMS_WEBHOOK_SECRET=... \
-e TRUNKCMS_SESSION_KEY="$(openssl rand -base64 32)" \
-v "$PWD/secrets:/secrets:ro" \
nullism/trunkcms
On Kubernetes, Cloud Run, ECS or Lambda, the same values go in the platform’s env and secret config. There’s a Kubernetes example in the repo.
4. Sign in
Visit /admin and sign in with GitHub. Anyone with push access to the repo is an admin. If the repo is empty, click Initialize site.
From then on, editing outside the UI works the same way. A git push from a laptop, a merged PR, or GitHub’s web editor all fire the push webhook, and the site rebuilds.