Skip to content

feat(stacks): Add Planka kanban board + project-management category#631

Merged
stefanko-ch merged 1 commit into
mainfrom
feat/stacks/planka
May 28, 2026
Merged

feat(stacks): Add Planka kanban board + project-management category#631
stefanko-ch merged 1 commit into
mainfrom
feat/stacks/planka

Conversation

@stefanko-ch

Copy link
Copy Markdown
Owner

Summary

Adds Planka — an open-source kanban board (Trello alternative) with real-time multi-user collaboration — and a new project-management category to house it.

Closes #629.

New category

project-management added to control-plane/src/lib/categories.ts (CATEGORIES + CATEGORY_ORDER) and the services.yaml header. No existing category fit kanban/issue-tracking tools; future PM tools (e.g. Plane, #630) share it.

Stack

Field Value
Image ghcr.io/plankanban/planka:2.1.1 — multi-arch verified (amd64 + arm64)
Port host 1337 → container 1337 (1337 was free)
Category project-management
Backing DB dedicated postgres:16-alpine (planka-db)

Planka 2.x consolidates all uploads (attachments, avatars, backgrounds, favicons) under a single /app/data dir — 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 — no services.py hook needed. Admin username falls back to nexus (not the predictable admin) per #626.

Secrets

random_password.planka_secret_key (64) + planka_db_password (24) + planka_admin (24) → Infisical /planka. service_env._render_planka composes BASE_URL via service_host and fail-fast-guards empty secrets (same pattern as HedgeDoc).

Persistence (RFC 0001 R2 snapshot/restore)

  • planka-dbpg_dump (PostgresDumpTarget) — boards/cards/users
  • /mnt/nexus-data/planka/datarsync (RsyncTarget) — uploads
  • Added to _STANDARD_STOP_COMPOSE_FILES so the snapshot quiesces the container first (the symmetry regression-test enforces this).
  • compose_runner planka_data_prep block mkdir+chowns the bind-mount to 1000: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, nexus username fallback
  • compose_runner: planka_data_prep render + owner-guard + default-inference (present iff planka enabled)
  • config field count 96 → 99; regenerated config + infisical snapshots

All unit tests pass except 3 pre-existing test_dump_shell_* snapshot failures that fail identically on main (a macOS-local syrupy trailing-whitespace artifact vs the trim trailing whitespace pre-commit hook — they pass on Linux CI). Not introduced by this PR.

Test plan

  • gh workflow run spin-up.yml --ref feat/stacks/planka (needs initial-setup first if the Tofu secrets aren't yet generated — three new random_password resources)
  • Enable Planka in the Control Plane → it appears under the new Project Management category
  • https://planka.<domain> → CF Access OTP → Planka login with ADMIN_EMAIL + infisical secrets get PLANKA_PASSWORD --path=/planka --plain
  • Create a board + card with an attachment, run teardown then spin-up, confirm the board and attachment survive (pg_dump + rsync restore)
  • ssh nexus "docker port planka" shows 1337/tcp → 0.0.0.0:1337

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
Copilot AI review requested due to automatic review settings May 28, 2026 18:27
@github-actions

Copy link
Copy Markdown
Contributor

coverage

Coverage report — nexus_deploy
FileStmtsMissCoverMissing
__init__.py50100% 
_remote.py150100% 
cli.py40100% 
compose_restart.py400100% 
compose_runner.py880100% 
config.py1400100% 
firewall.py2060100% 
gitea.py5875590%691–692, 697, 720–721, 733–734, 770–771, 783–784, 802–803, 828–829, 851–852, 863–864, 919–920, 928–929, 934, 940–941, 965–966, 999–1000, 1003, 1034–1035, 1076–1077, 1082–1083, 1123–1124, 1155–1156, 1179–1180, 1185–1186, 1285–1286, 1291–1292, 1766, 1770, 1791, 1819–1820, 1907
hetzner_capacity.py1260100% 
infisical.py2040100% 
kestra.py176398%223, 427, 768
orchestrator.py6207388%456, 616, 628, 798–799, 804–805, 837–839, 848, 853–855, 866, 903–904, 909–910, 930, 965–966, 971–972, 980, 1005–1006, 1014, 1036–1037, 1042–1043, 1095–1096, 1101–1102, 1335, 1338, 1408, 1414–1415, 1420–1421, 1455, 1562–1563, 1568–1569, 1618–1619, 1624–1625, 1684, 1699, 1756, 1761–1762, 1767–1768, 1775, 1781, 1948, 1955, 1967–1968, 1973–1974, 1980, 1986, 2059–2060, 2081–2082
pipeline.py2071393%165–166, 350, 388, 468, 485, 580–581, 626–627, 717–718, 765
r2_tokens.py113298%87, 150
s3_persistence.py199199%315
s3_restore.py1030100% 
secret_sync.py990100% 
seeder.py980100% 
service_env.py3973391%1142, 1144–1146, 1154–1155, 1484–1487, 1492–1498, 1527–1531, 1547–1551, 1573, 1575, 1597–1598, 1605, 1714
services.py319199%2018
setup.py1651392%238, 308–311, 319, 323–328, 344
ssh.py560100% 
stack_sync.py960100% 
tfvars.py440100% 
tofu.py860100% 
workspace_coords.py1010100% 
TOTAL429419495% 

@codecov

codecov Bot commented May 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 to 2.1.1 and nexus-planka DB user
  • New project-management category in services.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 tofu random_password resources and secrets output; 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 stefanko-ch merged commit 0cc2754 into main May 28, 2026
9 checks passed
@stefanko-ch stefanko-ch deleted the feat/stacks/planka branch May 28, 2026 19:14
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stacks): Add Planka kanban board

2 participants