Kanboard is a self-hosted, lightweight alternative to Trello featuring native WIP limits, automated workflow actions, and zero per-seat subscription fees.
Frédéric Guillot created Kanboard in 2014 to give teams a minimalist visual task tracker anchored strictly in the Kanban methodology. Rather than adopting the heavy client-side frameworks common in modern project management software, the application relies on standard server-rendered PHP backed by SQLite, MySQL, or PostgreSQL. That architectural restraint means an instance deploys with negligible server resource demands, boots almost instantly, and keeps day-to-day card workflows free of interface clutter.
Trello relies on Power-Ups and automation quotas to connect outside tools, routing operational metadata through cloud brokers and adding per-seat fees. Kanboard takes a local-first approach to connectivity: the software runs behind your firewall, offering a JSON-RPC API and two-way webhooks that link directly to internal repositories, chat servers, and deployment pipelines. Teams hosting their own infrastructure avoid sending card titles, client deliverables, or server alerts to external SaaS platforms.
The platform includes native integrations and plugins for GitLab, GitHub, Gogs, Mattermost, Rocket.Chat, Slack, and Matrix, alongside directory authentication through LDAP or Active Directory. Where Trello focuses on consumer-facing polish and commercial SaaS marketplaces, Kanboard provides systems administrators with direct database access, scriptable automation rules, and incoming webhook triggers that create or transition tasks without third-party integration tiers or per-seat billing.
How does Kanboard compare to Trello? Kanboard is self-hosted and includes native WIP limits, swimlanes, and automated actions without paid tiers, whereas Trello is a hosted SaaS product offering polished mobile apps and a commercial plugin marketplace.
Can Kanboard run inside a Docker container? Yes. The maintainers provide official Docker container images that run with SQLite by default or connect to external PostgreSQL or MySQL database containers.
Is Kanboard still actively developed? The software is in maintenance mode, meaning new architectural features are rare, but the project receives ongoing security patches, bug fixes, and PHP version updates from community contributors.
Kanboard is a practical match for small teams and operations leads who prioritize self-hosted simplicity, direct API automation, and predictable server footprints over modern UI flair. While its maintenance-mode status and absence of native mobile apps make it less suited for organizations that demand frequent feature redesigns, active community maintenance and a permissive MIT license guarantee complete autonomy and data privacy on internal hardware.
We started this exact setup from scratch in a clean Linux machine on Nov 2, 2026 and checked it through Kanboard's own API: every check passed. Recipes are re-checked regularly and removed if they stop working.
mkdir -p kanboard && cd kanboard
curl -fsSL https://open-source.store/tools/kanboard/compose.yml -o compose.ymltouch .envdocker compose up -dservices:
app:
image: kanboard/kanboard:v1.2.57
restart: always
ports:
- "80:80"
environment:
- SESSION_HANDLER=php
- DB_TIMEOUT=30
volumes:
- kanboard-data:/var/www/app/data
- kanboard-plugins:/var/www/app/plugins
- kanboard-ssl:/etc/nginx/ssl
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost/healthcheck.php || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
volumes:
kanboard-data:
kanboard-plugins:
kanboard-ssl:
Free IDE for Java, Kotlin, Go, TypeScript and Python. Built on IntelliJ Community, fully open source, 300+ plugins.
Show that Kanboard is listed as an open-source alternative. Paste into your README:
Ubuntu 24.04 · Apple container, Docker 29.1.3, Compose 2.40.3+ds1-0ubuntu1~24.04.1. Images pulled in 8 s: kanboard/kanboard:v1.2.57.
Based on the upstream setup. Official SQLite docker-compose. Image pinned to v1.2.57, published only HTTP port 80, configured PHP file sessions and DB timeout to prevent SQLite lock contention, and added healthcheck on /healthcheck.php.
app-1 | 2026-11-02T06:52:57.790798381Z PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353"
app-1 | 2026-11-02T06:52:57.790804464Z Stack trace:"
app-1 | 2026-11-02T06:52:57.790805131Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()"
app-1 | 2026-11-02T06:52:57.790806089Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()"
app-1 | 2026-11-02T06:52:57.790806673Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()"
app-1 | 2026-11-02T06:52:57.790807214Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()"
app-1 | 2026-11-02T06:52:57.790807798Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()"
app-1 | 2026-11-02T06:52:57.790808339Z #5 [internal function]: session_write_close()"
app-1 | 2026-11-02T06:52:57.790810589Z #6 {main}"
app-1 | 2026-11-02T06:52:57.790811131Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353"
app-1 | 2026-11-02T06:52:57.790811714Z 2026/11/02 06:52:57 [error] 16#16: *24268 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353
app-1 | 2026-11-02T06:52:57.790812423Z Stack trace:
app-1 | 2026-11-02T06:52:57.790812923Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()
app-1 | 2026-11-02T06:52:57.790813464Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()
app-1 | 2026-11-02T06:52:57.790814006Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()
app-1 | 2026-11-02T06:52:57.790814548Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()
app-1 | 2026-11-02T06:52:57.790815089Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()
app-1 | 2026-11-02T06:52:57.790815631Z #5 [internal function]: session_write_close()
app-1 | 2026-11-02T06:52:57.790816173Z #6 {main}
app-1 | 2026-11-02T06:52:57.790816631Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353" while reading response header from upstream, client: 192.168.65.118, server: localhost, request: "GET /auth/auth.json HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "oss-verify.example"
app-1 | 2026-11-02T06:52:57.791571256Z PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353"
app-1 | 2026-11-02T06:52:57.791584131Z Stack trace:"
app-1 | 2026-11-02T06:52:57.791591548Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()"
app-1 | 2026-11-02T06:52:57.791598089Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()"
app-1 | 2026-11-02T06:52:57.791604089Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()"
app-1 | 2026-11-02T06:52:57.791610089Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()"
app-1 | 2026-11-02T06:52:57.791615756Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()"
app-1 | 2026-11-02T06:52:57.791621089Z 2026/11/02 06:52:57 [error] 16#16: *24268 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353
app-1 | 2026-11-02T06:52:57.791626964Z Stack trace:
app-1 | 2026-11-02T06:52:57.791627673Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()
app-1 | 2026-11-02T06:52:57.791628423Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()
app-1 | 2026-11-02T06:52:57.791629048Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()
app-1 | 2026-11-02T06:52:57.791631256Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()
app-1 | 2026-11-02T06:52:57.791631881Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()
app-1 | 2026-11-02T06:52:57.791632464Z #5 [internal function]: session_write_close()
app-1 | 2026-11-02T06:52:57.791633006Z #6 {main}
app-1 | 2026-11-02T06:52:57.791633548Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353" while reading response header from upstream, client: 192.168.65.118, server: localhost, request: "GET /authentication/auth.json HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "oss-verify.example"
app-1 | 2026-11-02T06:52:57.791642714Z #5 [internal function]: session_write_close()"
app-1 | 2026-11-02T06:52:57.791651256Z #6 {main}"
app-1 | 2026-11-02T06:52:57.791657839Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353"
app-1 | 2026-11-02T06:52:57.793785714Z PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353"
app-1 | 2026-11-02T06:52:57.793790548Z Stack trace:"
app-1 | 2026-11-02T06:52:57.793791131Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()"
app-1 | 2026-11-02T06:52:57.793791798Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()"
app-1 | 2026-11-02T06:52:57.793792381Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()"
app-1 | 2026-11-02T06:52:57.793792964Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()"
app-1 | 2026-11-02T06:52:57.793793589Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()"
app-1 | 2026-11-02T06:52:57.793794173Z #5 [internal function]: session_write_close()"
app-1 | 2026-11-02T06:52:57.793794673Z #6 {main}"
app-1 | 2026-11-02T06:52:57.793795173Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353"
app-1 | 2026-11-02T06:52:57.793951298Z 2026/11/02 06:52:57 [error] 16#16: *24268 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353
app-1 | 2026-11-02T06:52:57.793953381Z Stack trace:
app-1 | 2026-11-02T06:52:57.793954006Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()
app-1 | 2026-11-02T06:52:57.793954756Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()
app-1 | 2026-11-02T06:52:57.793955339Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()
app-1 | 2026-11-02T06:52:57.793955923Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()
app-1 | 2026-11-02T06:52:57.793956464Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()
app-1 | 2026-11-02T06:52:57.793957006Z #5 [internal function]: session_write_close()
app-1 | 2026-11-02T06:52:57.793959006Z #6 {main}
app-1 | 2026-11-02T06:52:57.793959506Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353" while reading response header from upstream, client: 192.168.65.118, server: localhost, request: "GET /oauth/auth.json HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "oss-verify.example"
app-1 | 2026-11-02T06:52:57.794916548Z PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353"
app-1 | 2026-11-02T06:52:57.794920048Z Stack trace:"
app-1 | 2026-11-02T06:52:57.794920756Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()"
app-1 | 2026-11-02T06:52:57.794934631Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()"
app-1 | 2026-11-02T06:52:57.794935798Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()"
app-1 | 2026-11-02T06:52:57.794936464Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()"
app-1 | 2026-11-02T06:52:57.794937089Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()"
app-1 | 2026-11-02T06:52:57.794937714Z #5 [internal function]: session_write_close()"
app-1 | 2026-11-02T06:52:57.794938339Z #6 {main}"
app-1 | 2026-11-02T06:52:57.794938839Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353"
app-1 | 2026-11-02T06:52:57.794940423Z 2026/11/02 06:52:57 [error] 16#16: *24268 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353
app-1 | 2026-11-02T06:52:57.794941214Z Stack trace:
app-1 | 2026-11-02T06:52:57.794941756Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()
app-1 | 2026-11-02T06:52:57.794942381Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()
app-1 | 2026-11-02T06:52:57.794943006Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()
app-1 | 2026-11-02T06:52:57.794943548Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()
app-1 | 2026-11-02T06:52:57.794944131Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()
app-1 | 2026-11-02T06:52:57.794944714Z #5 [internal function]: session_write_close()
app-1 | 2026-11-02T06:52:57.794945214Z #6 {main}
app-1 | 2026-11-02T06:52:57.794945714Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353" while reading response header from upstream, client: 192.168.65.118, server: localhost, request: "GET /keys/auth.json HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "oss-verify.example"
app-1 | 2026-11-02T06:52:57.797062423Z PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353"
app-1 | 2026-11-02T06:52:57.797068923Z Stack trace:"
app-1 | 2026-11-02T06:52:57.797072464Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()"
app-1 | 2026-11-02T06:52:57.797073298Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()"
app-1 | 2026-11-02T06:52:57.797074048Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()"
app-1 | 2026-11-02T06:52:57.797074673Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()"
app-1 | 2026-11-02T06:52:57.797076631Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()"
app-1 | 2026-11-02T06:52:57.797077298Z #5 [internal function]: session_write_close()"
app-1 | 2026-11-02T06:52:57.797077839Z #6 {main}"
app-1 | 2026-11-02T06:52:57.797078339Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353"
app-1 | 2026-11-02T06:52:57.797464506Z 2026/11/02 06:52:57 [error] 16#16: *24268 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353
app-1 | 2026-11-02T06:52:57.797467673Z Stack trace:
app-1 | 2026-11-02T06:52:57.797468256Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()
app-1 | 2026-11-02T06:52:57.797469006Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()
app-1 | 2026-11-02T06:52:57.797469589Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()
app-1 | 2026-11-02T06:52:57.797470214Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()
app-1 | 2026-11-02T06:52:57.797470798Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()
app-1 | 2026-11-02T06:52:57.797471381Z #5 [internal function]: session_write_close()
app-1 | 2026-11-02T06:52:57.797471881Z #6 {main}
app-1 | 2026-11-02T06:52:57.797472381Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353" while reading response header from upstream, client: 192.168.65.118, server: localhost, request: "GET /credentials/auth.json HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "oss-verify.example"
app-1 | 2026-11-02T06:52:57.798149798Z PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353"
app-1 | 2026-11-02T06:52:57.798152839Z Stack trace:"
app-1 | 2026-11-02T06:52:57.798153381Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()"
app-1 | 2026-11-02T06:52:57.798154089Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()"
app-1 | 2026-11-02T06:52:57.798154631Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()"
app-1 | 2026-11-02T06:52:57.798155214Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()"
app-1 | 2026-11-02T06:52:57.798157548Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()"
app-1 | 2026-11-02T06:52:57.798158131Z #5 [internal function]: session_write_close()"
app-1 | 2026-11-02T06:52:57.798158714Z #6 {main}"
app-1 | 2026-11-02T06:52:57.798159214Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353"
app-1 | 2026-11-02T06:52:57.798260339Z 2026/11/02 06:52:57 [error] 16#16: *24268 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught PicoDb\SQLException: SQL Error[HY000]: SQLSTATE[HY000]: General error: 5 database is locked in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php:353
app-1 | 2026-11-02T06:52:57.798262631Z Stack trace:
app-1 | 2026-11-02T06:52:57.798263256Z #0 /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php(245): PicoDb\StatementHandler->handleSqlError()
app-1 | 2026-11-02T06:52:57.798263964Z #1 /var/www/app/libs/picodb/lib/PicoDb/Database.php(279): PicoDb\StatementHandler->execute()
app-1 | 2026-11-02T06:52:57.798264506Z #2 /var/www/app/libs/picodb/lib/PicoDb/Table.php(234): PicoDb\Database->execute()
app-1 | 2026-11-02T06:52:57.798265089Z #3 /var/www/app/app/Core/Session/SessionHandler.php(91): PicoDb\Table->update()
app-1 | 2026-11-02T06:52:57.798265631Z #4 [internal function]: Kanboard\Core\Session\SessionHandler->write()
app-1 | 2026-11-02T06:52:57.798266173Z #5 [internal function]: session_write_close()
app-1 | 2026-11-02T06:52:57.798266714Z #6 {main}
app-1 | 2026-11-02T06:52:57.798267214Z thrown in /var/www/app/libs/picodb/lib/PicoDb/StatementHandler.php on line 353" while reading response header from upstream, client: 192.168.65.118, server: localhost, request: "GET /creds/auth.json HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: "oss-verify.example"