feat(stacks): Add Planka kanban board + project-management category#631
Merged
Conversation
Planka is an open-source kanban board (Trello alternative) with real-time multi-user collaboration — boards, lists, cards, labels, due dates, attachments, Markdown descriptions. New `project-management` category (categories.ts + services.yaml header) since no existing category fit; future PM tools (e.g. Plane, #630) share it. Stack wiring (per CLAUDE.md "Adding New Stacks"): - stacks/planka/docker-compose.yml — Planka 2.1.1 (multi-arch amd64+arm64 verified) + dedicated postgres:16-alpine. Container port 1337 (free). Planka 2.x stores all uploads under a single /app/data dir, bind-mounted to /mnt/nexus-data/planka/data. - services.yaml — subdomain `planka`, port 1337, pinned image. - config.py / infisical.py / tofu — random_password.planka_secret_key (64) + planka_db_password (24) + planka_admin (24), pushed to Infisical /planka. - service_env._render_planka — composes BASE_URL via service_host, pipes SECRET_KEY/DB/admin creds, fail-fast guard on empty secrets (same pattern as HedgeDoc). Admin username falls back to "nexus" (not the predictable "admin") per issue #626. Auth: CF Access at the edge + Planka seeds its single admin from DEFAULT_ADMIN_* on first boot (no services.py hook needed — Planka self-seeds, unlike HedgeDoc's CLI dance). Persistence (RFC 0001 R2 snapshot/restore): - planka-db → pg_dump (PostgresDumpTarget) for boards/cards/users. - /mnt/nexus-data/planka/data → rsync (RsyncTarget) for uploads. - Added to _STANDARD_STOP_COMPOSE_FILES so the snapshot quiesces the container first (the symmetry test enforces this). - compose_runner planka_data_prep block mkdir+chowns the bind-mount to 1000:1000 (the node user) before compose-up. Docs: README badge/table + count 73→74, docs/stacks/planka.md, docs/stacks/README.md image-versions + stack-doc index. Tests: _render_planka fail-fast + base-URL + admin-seed + username fallback; compose_runner planka_data_prep render + default-inference; config field count 96→99; regenerated config/infisical snapshots. Closes #629
Contributor
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds Planka (open-source kanban board) as a new stack and introduces a project-management category to host it (and future PM tools like Plane in #630). Follows the established HedgeDoc pattern: dedicated Postgres sidecar, fail-fast env renderer, R2 snapshot/restore for both DB and uploads, guarded chown for the bind-mount.
Changes:
- New
stacks/planka/docker-compose.yml(Planka + dedicated Postgres 16), with image pinned to2.1.1andnexus-plankaDB user - New
project-managementcategory inservices.yaml+control-plane/src/lib/categories.ts(CATEGORIES + CATEGORY_ORDER) - Wiring across
config.py,service_env._render_planka,infisical.compute_folders,compose_runner.planka_data_prep,s3_restore.standard_targets+_STANDARD_STOP_COMPOSE_FILES, plus tofurandom_passwordresources andsecretsoutput; full unit-test coverage and updated snapshots; docs + README
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| stacks/planka/docker-compose.yml | New Planka + Postgres compose with bind-mounted /app/data, healthchecks, internal network |
| services.yaml | Registers planka service under project-management with pinned image 2.1.1 |
| control-plane/src/lib/categories.ts | Adds project-management to CATEGORIES + CATEGORY_ORDER so it renders on /stacks |
| src/nexus_deploy/config.py | Adds 3 Planka secret fields to _FIELDS + NexusConfig |
| src/nexus_deploy/service_env.py | New _render_planka with fail-fast guard, BASE_URL via service_host, admin seeding, nexus fallback |
| src/nexus_deploy/infisical.py | Adds /planka folder with USERNAME/PASSWORD/SECRET_KEY/DB_PASSWORD |
| src/nexus_deploy/compose_runner.py | Adds planka_data_prep block with guarded chown to 1000:1000 |
| src/nexus_deploy/s3_restore.py | Adds planka-db pg_dump target, planka-data rsync target, and stop-compose entry |
| tofu/stack/main.tf | Adds 3 random_password resources (secret_key/db/admin) |
| tofu/stack/outputs.tf | Exposes the 3 new secrets to Infisical push |
| tests/unit/test_service_env.py | New Planka renderer tests (per-secret guards, all-at-once, URL, separator, fallback) |
| tests/unit/test_compose_runner.py | Tests for planka_data_prep render + owner-guard + default inference |
| tests/unit/test_config.py | Pins _FIELDS count to 99 |
| tests/unit/snapshots/*.ambr | Regenerated config + infisical snapshots |
| docs/stacks/planka.md, docs/stacks/README.md, README.md | New stack doc, index entry, badge, count bump to 74 |
stefanko-ch
pushed a commit
that referenced
this pull request
May 28, 2026
🤖 I have created a release *beep* *boop* --- ## [0.69.0](v0.68.0...v0.69.0) (2026-05-28) ### 🚀 Features * **stacks:** Add Planka kanban board + project-management category ([#631](#631)) ([0cc2754](0cc2754)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Planka — an open-source kanban board (Trello alternative) with real-time multi-user collaboration — and a new
project-managementcategory to house it.Closes #629.
New category
project-managementadded tocontrol-plane/src/lib/categories.ts(CATEGORIES + CATEGORY_ORDER) and theservices.yamlheader. No existing category fit kanban/issue-tracking tools; future PM tools (e.g. Plane, #630) share it.Stack
ghcr.io/plankanban/planka:2.1.1— multi-arch verified (amd64 + arm64)project-managementpostgres:16-alpine(planka-db)Planka 2.x consolidates all uploads (attachments, avatars, backgrounds, favicons) under a single
/app/datadir — bind-mounted to/mnt/nexus-data/planka/data.Auth
CF Access at the edge gates who reaches the login page; Planka seeds its single admin from
DEFAULT_ADMIN_*on first boot. Unlike HedgeDoc (post-boot CLI hook), Planka self-seeds — noservices.pyhook needed. Admin username falls back tonexus(not the predictableadmin) per #626.Secrets
random_password.planka_secret_key(64) +planka_db_password(24) +planka_admin(24) → Infisical/planka.service_env._render_plankacomposesBASE_URLviaservice_hostand fail-fast-guards empty secrets (same pattern as HedgeDoc).Persistence (RFC 0001 R2 snapshot/restore)
planka-db→pg_dump(PostgresDumpTarget) — boards/cards/users/mnt/nexus-data/planka/data→rsync(RsyncTarget) — uploads_STANDARD_STOP_COMPOSE_FILESso the snapshot quiesces the container first (the symmetry regression-test enforces this).compose_runnerplanka_data_prepblock mkdir+chowns the bind-mount to1000:1000(the node user) before compose-up.Tests
_render_planka: fail-fast on each empty secret + all-at-once, BASE_URL composition, subdomain-separator override, admin-seed values,nexususername fallbackcompose_runner:planka_data_preprender + owner-guard + default-inference (present iffplankaenabled)configfield count 96 → 99; regeneratedconfig+infisicalsnapshotsAll unit tests pass except 3 pre-existing
test_dump_shell_*snapshot failures that fail identically onmain(a macOS-local syrupy trailing-whitespace artifact vs thetrim trailing whitespacepre-commit hook — they pass on Linux CI). Not introduced by this PR.Test plan
gh workflow run spin-up.yml --ref feat/stacks/planka(needsinitial-setupfirst if the Tofu secrets aren't yet generated — three newrandom_passwordresources)https://planka.<domain>→ CF Access OTP → Planka login withADMIN_EMAIL+infisical secrets get PLANKA_PASSWORD --path=/planka --plainteardownthenspin-up, confirm the board and attachment survive (pg_dump + rsync restore)ssh nexus "docker port planka"shows1337/tcp → 0.0.0.0:1337