Skip to content

markrai/scrumboy

scrumboy logo
version license

Self-hosted project management & issue-tracking solution + instant shareable & customizable boards + realtime collaboration, automation, API access and MCP-compatible client support

image

Table of contents

Quick Start

Runs in seconds. No setup required.

No .env file, TLS certificates, or encryption key are required to start the app.

Run with Docker

docker compose up --build

Open http://localhost:8080.

Run from source

go run ./cmd/scrumboy

Open http://localhost:8080.

Optional Configuration

Environment variables

  • The app does not automatically load .env files.
  • On Linux/macOS, export variables manually (for example: export SCRUMBOY_ENCRYPTION_KEY=...).
  • On Windows, win_run_full.bat and win_run_anonymous.bat manage data/scrumboy.env automatically for local convenience.
  • Precedence on Windows is: existing process env var SCRUMBOY_ENCRYPTION_KEY, then data/scrumboy.env, then legacy root scrumboy.env.
  • The canonical Windows-managed local file format is SCRUMBOY_ENCRYPTION_KEY=<base64-32-byte-key>.
  • Windows helper scripts still accept legacy raw single-line key files for backward compatibility.

Encryption key for 2FA/password reset

  • SCRUMBOY_ENCRYPTION_KEY is not required for basic startup.
  • It becomes required for encrypted auth/security features, including:
    • 2FA
    • Password reset flows
  • If an existing database already has 2FA-enabled users, startup fails without this key.
  • The key is part of the same backup/restore unit as data/app.db. Back them up together.
  • Do not regenerate or replace the key casually after encrypted auth/security data exists, or you can break access to 2FA/password-reset data.

Generate a key with: openssl rand -base64 32

Example for Docker Compose secret injection:

services:
  scrumboy:
    environment:
      - SCRUMBOY_ENCRYPTION_KEY=${SCRUMBOY_ENCRYPTION_KEY}

Example for systemd secret injection:

[Service]
Environment="SCRUMBOY_ENCRYPTION_KEY=REPLACE_WITH_BASE64_32_BYTE_KEY"

In both cases, the deployment manager is injecting the environment variable. Scrumboy itself does not auto-load these files.

OIDC / SSO login (optional)

Scrumboy supports OpenID Connect for single sign-on with any standards-compliant provider (Keycloak, Authentik, Auth0, Entra ID, etc.). OIDC is enabled by setting all four required environment variables:

Variable Description
SCRUMBOY_OIDC_ISSUER Issuer URL (e.g. https://auth.example.com/realms/main)
SCRUMBOY_OIDC_CLIENT_ID OAuth client ID
SCRUMBOY_OIDC_CLIENT_SECRET Confidential client secret
SCRUMBOY_OIDC_REDIRECT_URL Full callback URL registered at IdP (e.g. https://scrumboy.example.com/api/auth/oidc/callback)

Optional:

Variable Description
SCRUMBOY_OIDC_LOCAL_AUTH_DISABLED Set to true to disable local password login when OIDC is configured (SSO-only mode)

Local password authentication remains available by default alongside OIDC. After successful OIDC login, the user receives a standard Scrumboy session cookie. The IdP must return a verified email (email_verified: true). HTTPS is recommended when using OIDC to ensure session cookies are Secure.

See docs/oidc.md for full setup details, constraints, and troubleshooting.

TLS / HTTPS (optional)

  • TLS is optional.
  • HTTPS is enabled only when both SCRUMBOY_TLS_CERT and SCRUMBOY_TLS_KEY files exist.
  • Otherwise, the server runs on HTTP by default.

PWA / Web Push (optional)

Install the app from the browser for a standalone window and better mobile UX. Background assignment alerts use the Web Push API with VAPID keys on the server. When both keys are set, signed-in clients attempt to subscribe automatically (browser permission may be prompted). Docker users must pass the VAPID variables into the container environment and recreate the container after changes. Details, Docker verification steps, and subscriber contact semantics: docs/pwa.md.

Frontend build note

The Docker image and go run embed prebuilt assets under internal/httpapi/web/dist. If they are missing, build them:

cd internal/httpapi/web
npm install
npm run build

Then run docker compose up --build or go run ./cmd/scrumboy again from the repository root.

Why Scrumboy?

Simplicity of a light Kanban, with the power of structured systems: Roles, sprints, audit trails & customizable workflows - without being locked into SaaS tools.

Who is this for?

  • self-hosted & privacy-focused community
  • small to medium-sized teams & solo builders

Modes

  • Full (SCRUMBOY_MODE=full, default): Auth can be enabled. First user via bootstrap; then login/session. Backup/export, tags, multi-project. Projects can be user-owned (project_members) or anonymous (shareable by URL): /anon (or /temp) creates a throwaway board and redirects to /{slug}.

  • Anonymous (SCRUMBOY_MODE=anonymous): No auth. Landing at /; live deployment at: https://scrumboy.com/

Features

  • Custom Workflows: You can create any combination of workflow you want, per project, with user-defined "Done" lane.

  • Realtime SSE enabled boards for instant multi-user actions.

  • Webhooks (API-only, full mode): Register URLs per project so Scrumboy can POST JSON when subscribed domain events fire (e.g. todo.assigned). For your own automations, not in-app or browser notifications. See Integrations.

  • Customizable Tags: Users can inherit and customize tag colors.

  • Advanced filtering: Search todos based on text or tags.

  • Sprints: create, activate, close; sprint filter on board; default sprint weeks (1 or 2) per project.

  • Authentication & 2FA: TOTP supported when SCRUMBOY_ENCRYPTION_KEY is set.

  • Audit trail: append-only audit_events table; todo/member/project/link actions logged (see docs/AUDIT_TRAIL.md).

  • Backup: export/import JSON; merge or replace; scope full or single project (see store backup logic).

  • PWA: Excellent UX for mobile users.

  • Anonymous shareable boards can be created in both Full & Anonymous deployments.

  • VoiceFlow - deterministic voice commands (see docs/VOICEFLOW.md).

  • Sticky-Note Wall - per-project scratchpad of draggable sticky notes on the board (see docs/WALL.md).

  • Todo notes Markdown preview (optional) - markdown / preview tabs in the todo Notes field; optional Mermaid diagrams in fenced ```mermaid blocks in preview only (see FAQ.md, docs/markdown&mermaid.md).


Integrations & API Access

Scrumboy supports API access tokens for automation, integrations, and programmatic MCP access (legacy HTTP and JSON-RPC - see below). Full MCP guide for developers and agents: docs/mcp.md.

You can create a token from the API and use it to call MCP endpoints directly - no browser session or cookies required.

Create a token (requires login session):

curl -b cookies.txt -X POST http://localhost:8080/api/me/tokens \
  -H "Content-Type: application/json" \
  -H "X-Scrumboy: 1" \
  -d '{"name":"cli"}'

Response includes a one-time token (starts with sb_).

Use it with MCP:

curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sb_your_token_here" \
  -d '{"tool":"projects.list","input":{}}'

MCP (JSON-RPC) for AI agents

Scrumboy exposes a Model Context Protocol (MCP) compatible JSON-RPC endpoint for AI agents (Claude, etc.) and MCP-compatible clients.

Endpoint: POST /mcp/rpc

This is separate from the /mcp HTTP endpoint above and follows JSON-RPC 2.0 (initialize, tools/list, tools/call, etc.). See docs/mcp.md for tools, auth, response shapes, and examples; API.md for the full HTTP/MCP behavior reference.

Example: initialize

curl -X POST http://localhost:8080/mcp/rpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'

Example: list tools

curl -X POST http://localhost:8080/mcp/rpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

Example: call a tool

curl -X POST http://localhost:8080/mcp/rpc \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sb_your_token_here" \
  -d '{
    "jsonrpc":"2.0",
    "id":3,
    "method":"tools/call",
    "params":{
      "name":"todos.create",
      "arguments":{
        "projectSlug":"my-project",
        "title":"Created via MCP"
      }
    }
  }'

Notes

  • Compatible with MCP clients that support HTTP JSON-RPC to this URL.
  • Some MCP clients expect stdio-based servers - those are not supported here.
  • Authentication works via session cookie or Bearer token (same rules as /mcp).

This enables:

  • CLI usage
  • CI/CD automation
  • AI agents and MCP clients (use POST /mcp/rpc for JSON-RPC; POST /mcp remains available for the legacy { "tool", "input" } envelope)
  • Scripting/integrations without login flows

Webhooks (outbound HTTP)

Scrumboy can POST JSON to URLs you register when certain events occur. This is for server-side integrations (your script, gateway, queue worker, etc.). It does not add notifications inside the Scrumboy UI; live boards still update via SSE as before.

  • Availability: Full mode only (endpoints are disabled in anonymous mode).
  • Who can configure: Project maintainers, via the HTTP API only - there is no settings screen for webhooks yet.
  • API: POST /api/webhooks (create), GET /api/webhooks (list yours), DELETE /api/webhooks/{id} - same session cookie / CSRF header rules as other mutating /api/* calls.
  • Events: Subscribe to specific types (e.g. todo.assigned) or * for all delivered types. The set may grow over time; unused types in your list are harmless.
  • Security: Optional per-webhook secret; when set, requests include an X-Scrumboy-Signature header (sha256= HMAC of the raw JSON body).
  • Semantics: Best-effort delivery with retries on failure; not a durable external queue - design for idempotent receivers using the event id in the JSON body.

Example create (replace cookie / project id / URL):

curl -b cookies.txt -X POST http://localhost:8080/api/webhooks \
  -H "Content-Type: application/json" \
  -H "X-Scrumboy: 1" \
  -d '{"projectId":1,"url":"https://example.com/scrumboy-hook","events":["todo.assigned"],"secret":"optional-shared-secret"}'

Config

Env vars and defaults are defined in internal/config/config.go. ResolveDataDir uses DATA_DIR and SQLITE_PATH as documented there. None of these are required for basic startup.

Variable Default (from code)
BIND_ADDR :8080
DATA_DIR ./data
SQLITE_PATH (empty; then $DATA_DIR/app.db)
SQLITE_BUSY_TIMEOUT_MS 30000
SQLITE_JOURNAL_MODE WAL
SQLITE_SYNCHRONOUS FULL
MAX_REQUEST_BODY_BYTES 1048576 (1 MiB)
SCRUMBOY_MODE full (or anonymous)
SCRUMBOY_ENCRYPTION_KEY (empty) - Required for 2FA. Base64-encoded 32-byte key. Generate with openssl rand -base64 32. Without it, 2FA setup returns 503. Back this key up with data/app.db; do not replace it casually once encrypted auth/security data exists.
SCRUMBOY_TLS_CERT ./cert.pem - TLS cert for HTTPS
SCRUMBOY_TLS_KEY ./key.pem - TLS key for HTTPS
SCRUMBOY_INTRANET_IP 192.168.1.250 - LAN IP to log for intranet access
SCRUMBOY_VAPID_PUBLIC_KEY (empty) - Web Push. VAPID public key (URL-safe base64). Required together with private key for PWA background assignment notifications and for post-login auto-subscribe in the SPA.
SCRUMBOY_VAPID_PRIVATE_KEY (empty) - VAPID private key (URL-safe base64).
SCRUMBOY_VAPID_SUBSCRIBER (empty) - Contact for VAPID JWT sub (not tied to IdP). Use a plain email (e.g. ops@example.com); the server adds mailto:. Or set a full mailto:... or https://... URL explicitly. If unset, a built-in default is used.
SCRUMBOY_DEBUG_PUSH (empty) - Set to 1 to log push send/prune on the server.

docker-compose.yml overrides some of these (e.g. SQLITE_BUSY_TIMEOUT_MS=5000).


Roles

In full mode, access is governed by two separate role systems. System roles do not grant project access; project access comes only from project membership.

System roles (instance-wide)

Role Who has it Allowed actions
Owner Bootstrap (first) user; can be assigned by another owner List all users; create users (admin-only API); update any user’s system role (owner/admin/user); delete users (except cannot delete the last owner).
Admin Assigned by an owner List all users; create users. Cannot change system roles or delete users.
User Default for new users; assigned by owner No system-level user management. Access to projects only via project membership.

Project roles (per project)

A user must be a member of a project to access it; system role alone does not grant access.

Role View board & todos Create/edit/move/delete todos Edit body when assigned Manage members Delete project Tag delete/color (project-scoped)
Maintainer ✓ (maintainer)
Contributor - ✓ (body only) - - -
Viewer - - - - -
  • View (board, backlog, burndown, charts, etc.): Any project role (Viewer or above).
  • Create/edit/move/delete todos, assign, sprints: Maintainer only. Contributor cannot create, delete, move, or assign; cannot edit title, tags, sprint, or estimation.
  • Edit body when assigned: Contributor can edit the body field only when the todo is assigned to them. Maintainer has full edit.
  • Manage members (add/remove members, change role): Maintainer only.
  • Delete project: Maintainer only.
  • Delete/update tag (project-scoped tags): Maintainer only. User-owned tags: owner of the tag or maintainer in all projects where the tag is used.
  • Create tags: Contributor or Maintainer.

Temporary/anonymous boards (shareable by URL, no auth) do not use project roles; anyone with the link can view and edit. New Todo and drag-and-drop are enabled for anonymous boards.


Export scope

  • Full: All projects the user can access (full mode: projects where the user is a member, or temporary boards they created; anonymous mode: not applicable for full export).
  • Single project: One board/project only (e.g. current board in anonymous mode).

Import modes

When importing a backup JSON, you choose how it is applied:

Mode Description
Replace Replace all: delete every project in your current export scope, then create projects from the backup. Effect is “nuke and restore” so the instance matches the backup. Not available in anonymous mode.
Merge Merge/update: for each project in the backup, match by slug. If a project with that slug exists (and you have access), update its todos, tags, and links to match the backup; otherwise create a new project. In anonymous mode, merge behaves like Create Copy (all projects are created as new).
Create copy Create copy: create new projects for every project in the backup. Slugs are made unique (e.g. name-imported-2), so nothing is overwritten; you get duplicates.

In anonymous mode, full-scope import is not allowed; you can only import into the current board (todos and tags are added to that board).


Code layout (reference)

  • cmd/scrumboy: main server entrypoint. Other cmd/* are utilities (tagcheck, tagrecover, dbquery, slugfix).
  • internal/config: env-based config.
  • internal/version: app and export format version.
  • internal/db: SQLite open/options (PRAGMAs from config).
  • internal/migrate: DB migrations.
  • internal/store: data model and persistence (projects, todos, tags, auth, backup, ordering, memberships, audit, links, sprints, workflows, etc.).
  • internal/httpapi: HTTP server, routing, auth cookies, SPA serve, embedded web FS.
  • internal/httpapi/web: frontend (TS, CSS, HTML); built with npm run build in internal/httpapi/web; output under web/dist and embedded by server.

Invariants (e.g. canonical URL /{slug}, no UI links to /p/{id}) are enforced in code and tests; see internal/httpapi and internal/store for the authoritative behavior.


Documentation

  • MCP (HTTP tools + JSON-RPC): docs/mcp.md - tool catalog, auth, legacy vs /mcp/rpc, examples (agents & automation). See also API.md for exhaustive MCP HTTP detail.
  • PWA / Web Push (VAPID): docs/pwa.md - keys, subscriber contact, post-login auto-subscribe when VAPID is configured, Settings opt-out, tradeoffs.
  • Roles and permissions: docs/ROLES_AND_PERMISSIONS.md - project roles, backend authorization, anonymous boards.
  • Audit trail: docs/AUDIT_TRAIL.md - action vocabulary, event model, integration points.

License and Contributions

Scrumboy is licensed under the GNU Affero General Public License v3 (AGPL v3). See LICENSE for the full text.

Contributing: Contributors must sign the Contributor License Agreement (CLA) before contributions are accepted. See CONTRIBUTING.md for setup, build, and pull request guidelines.

Scrumboy is an independent open-source project and is not affiliated with, sponsored by, or endorsed by Scrum.org, Scrum Alliance, Inc., or any other organization associated with Scrum training or certification. Any reference to "scrum" is made solely to describe the project management methodology that the software is intended to support. We hope you will ❤️ it as much as we do!

About

Self-hosted kanban & project management with shareable boards, voice commands, sticky-notes and MCP support

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors