Kanboard 1.2.57 on AWS User Guide
Overview
This guide covers launching and using the Kanboard 1.2.57 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg help desk, IT service and project management listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Kanboard is open source project management built around the Kanban board. Each project is a board of columns (Backlog, Ready, Work in progress and Done to start with, and you can change them) holding cards for tasks, with swimlanes, subtasks, comments, attachments, due dates, time tracking, automatic actions, a calendar and Gantt view, analytics, per project permissions and a JSON-RPC API.
What the cloudimg image adds:
- No default login. Upstream Kanboard starts with the administrator
adminand the passwordadmin. On this image first boot replaces that password with one unique to your instance before the web server starts, soadmin/adminnever works. - Nothing baked into the image. The image ships no database. Every instance creates its own SQLite database on first boot through Kanboard's own schema migrations, which also mint its own API token and webhook token.
- HTTPS from the first boot. nginx serves Kanboard on port 443 with a certificate generated on your instance, port 80 redirects to HTTPS, and requests for a host name the instance does not serve get no answer. The session cookie
KB_SIDisSecure,HttpOnlyandSameSite=Lax. - Only Kanboard's two entry points run PHP. nginx runs PHP for
/index.php(every page) and/jsonrpc.php(the API) and nothing else. The configuration, the database, the command line tool, the application and library code, Kanboard's diagnostichealthcheck.phpand trick addresses (/index.php/x, doubled or encoded slashes) answer 404. Static files under/assets/and/plugins/are served by file type only. - Read only code. The Kanboard code is owned by root and read only to PHP,
config.phpis owned by root and only readable by Kanboard, and the plugin installer is off, so nothing on the web can change the application, its settings or its plugins. - Abuse limits and cross site protection. On top of Kanboard's own captcha (after 3 failed sign ins) and 15 minute account lockout (after 6), nginx rate limits sign in requests per client address. Sign out and every state changing link refuse requests opened from other sites. Kanboard sees the real client address and the configured host name, never values a client sends in headers.
- Metadata access blocked. nginx, PHP-FPM, Kanboard's cron and first boot are blocked from the instance metadata service, so a webhook, mail server or link preview pointed at it gets nothing back. Webhooks and external links also refuse private network addresses, and the AMI requires IMDSv2.
- Cron as a timer. Kanboard's daily job (project statistics, overdue task notifications and scheduled task triggers) runs from
kanboard-cron.timeras thekanboarduser, with no crontab. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Kanboard 1.2.57 (the upstream source archive of tag v1.2.57, commit 2ddb31bf72d3, checksum verified), nginx 1.24, PHP 8.3 FPM, SQLite, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH) from your admin network, and TCP 443 (Kanboard) and TCP 80 (redirects to HTTPS) from the networks your team works from.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Kanboard 1.2.57 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large (or larger for a big team), your key pair and a security group as above.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=kanboard}]'
First boot creates the database and the certificate and takes about a minute after the instance is running.
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Kanboard 1.2.57 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot creates the database, sets the administrator password and mints the certificate; nginx and Kanboard's cron start only after it has finished:
systemctl is-active nginx php8.3-fpm kanboard-cron.timer
sudo test -f /var/lib/cloudimg/kanboard-firstboot.done && echo FIRSTBOOT_DONE
All three are active and the first boot marker is present:
active
active
active
FIRSTBOOT_DONE
Only SSH and nginx listen on network ports. Kanboard's database is a file, so there is no database listener, and PHP-FPM uses a local socket:
sudo ss -lntp | awk 'NR>1 && $4 !~ /^127\./ {split($6, p, "\""); print $4, p[2]}' | sort
0.0.0.0:22 sshd
0.0.0.0:443 nginx
0.0.0.0:80 nginx
[::]:22 sshd
[::]:443 nginx
[::]:80 nginx
Step 4: Get your URL and password
sudo cat /root/kanboard-credentials.txt
The file is readable by root only:
# Kanboard 1.2.57 - generated on first boot by kanboard-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.
KANBOARD_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
KANBOARD_ADMIN_USER=admin
KANBOARD_ADMIN_PASSWORD=<KANBOARD_ADMIN_PASSWORD>
#
# Open KANBOARD_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to
# https) and sign in with the user name and password above. Then change the password (admin > My profile > Change
# password) and set your e-mail address. The upstream default password (admin) does not work on this instance.
# API: Settings > API shows this instance's own API token (user jsonrpc) and endpoint https://<host>/jsonrpc.php
# Data: /var/lib/kanboard/data (SQLite database db.sqlite, attachments). Configuration: /etc/kanboard/config.php
# Cron: systemctl list-timers kanboard-cron.timer (runs php cli cronjob daily as kanboard)
# Change the name it serves as: sudo kanboard-set-hostname <your-dns-name>
# User guide: https://www.cloudimg.co.uk/guides/kanboard-1-2-57-on-ubuntu-24-04-aws/
The URL uses the instance's public DNS name from the EC2 instance metadata, and the certificate also names the public and private IP addresses. nginx answers only to the names in the certificate. The name is fixed at first boot, so if you stop and start the instance without an Elastic IP and its public address changes, run sudo kanboard-set-hostname with the new name (Step 8), or better, give the instance an Elastic IP or your own DNS name.
Step 5: Sign in and make the account yours
Open the KANBOARD_URL in your browser. The certificate is self signed, so your browser asks you to confirm it the first time (or install your own, Step 8). Sign in with the user name admin and the password from Step 4.

Kanboard opens your dashboard: the projects you belong to, with a count of tasks in each column, and the tasks and subtasks assigned to you. A new instance has no projects; choose New project to create the first one.

Each project is a board. Drag cards between columns as work moves on, and use the menu at the top left of the board to edit the columns, swimlanes, categories, permissions and automatic actions.

Then open your account (the avatar at the top right, then My profile) and:
- Under Edit profile, set your own e-mail address. Kanboard sends notifications and password reset links to it.
- Under Change password, change the password.
- Under Two factor authentication, turn on two factor sign in.

Add a separate Kanboard user for each person (the avatar menu at the top right, Users management, New user) instead of sharing the administrator account, and give them access per project.
Step 6: Mail, cron, API and outbound connections
Kanboard e-mails notifications (new and changed tasks, comments, overdue tasks) to users who turn them on. Set your mail server under Settings (in the avatar menu at the top right), Email settings. Until you do, Kanboard sends no e-mail.
The daily job runs from kanboard-cron.timer at about 08:00 UTC as the kanboard user. To see when it next runs:
systemctl list-timers kanboard-cron.timer --no-pager | head -3
Settings, About shows the Kanboard, PHP and database versions, with links to download, upload and optimise the database.

Settings, API shows this instance's own API token and the endpoint https://<host>/jsonrpc.php. Applications sign in to it as the user jsonrpc with that token, or as a Kanboard user with that user's password or personal API token (My profile, API). Requests without credentials are refused:
H=$(sudo grep '^KANBOARD_URL=' /root/kanboard-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
curl -sk -o /dev/null -w 'API without credentials -> %{http_code}\n' --resolve "$H:443:127.0.0.1" \
-H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","method":"getVersion","id":1}' "https://$H/jsonrpc.php"
API without credentials -> 401
Kanboard connects out only to servers you configure: your mail server, webhook receivers (Settings, Webhooks) and the pages behind external links you add to tasks. Webhooks and external links to private network addresses and to the instance metadata service are refused. The plugin installer is off and the plugin directory is read only; new Kanboard releases arrive as new versions of this listing.
Step 7: Backups
Everything Kanboard stores is under /var/lib/kanboard/data: the SQLite database db.sqlite, task attachments and avatars. The configuration is /etc/kanboard/config.php; it holds no secret, because the API and webhook tokens live in the database. Both are on the root volume, so the simplest backup is an EBS snapshot of it.
For a copy of the database alone, use Download the database on Settings, About (a gzip compressed SQLite file). For a consistent copy of the database from the command line while Kanboard is running, install the SQLite tool and let the kanboard user take the copy (do not open the database as root: a file root creates next to it would lock Kanboard out):
sudo apt-get install -y sqlite3
sudo -u kanboard sqlite3 /var/lib/kanboard/data/db.sqlite ".backup '/var/lib/kanboard/tmp/kanboard-backup.sqlite'"
sudo mv /var/lib/kanboard/tmp/kanboard-backup.sqlite <backup-dir>/kanboard-$(date +%F).sqlite
sudo tar -C / --exclude='db.sqlite*' -czf <backup-dir>/kanboard-files-$(date +%F).tar.gz var/lib/kanboard/data etc/kanboard
The database holds every password hash and the API tokens, so store the copy as carefully as the instance.
To give Kanboard more room, enlarge the root volume in the EC2 console (Volumes, Modify); Ubuntu grows the file system on the next boot.
Step 8: Your own DNS name and certificate
Point a DNS record at the instance (an Elastic IP keeps the address stable), then set the name Kanboard is served as. This mints a new self signed certificate for the name, points nginx and Kanboard's application URL (used in every e-mailed link) at it, updates the URL in /root/kanboard-credentials.txt, and keeps the name across reboots:
sudo kanboard-set-hostname <your-domain>
To use a certificate from a public or internal certificate authority instead (for example one issued by Let's Encrypt for <your-domain>), copy it over the generated pair and reload nginx (running kanboard-set-hostname again replaces it with a self signed one):
sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/kanboard.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/kanboard.key
sudo nginx -t && sudo systemctl reload nginx
Step 9: Security checks
nginx runs PHP only for Kanboard's two entry points. The configuration, the database, Kanboard's diagnostic and command line scripts, the code and libraries and trick addresses answer 404, plain HTTP redirects to HTTPS, and a request for a name the instance does not serve gets no answer at all. The sign in redirect (302) is Kanboard sending you to its sign in page, and /jsonrpc.php answers a browser's GET with a JSON error:
H=$(sudo grep '^KANBOARD_URL=' /root/kanboard-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
for p in / /index.php /jsonrpc.php /config.php /data/db.sqlite /healthcheck.php /cli /app/common.php /vendor/autoload.php /index.php/x //index.php /.git/config; do
curl -sk -o /dev/null -w "%{http_code} $p\n" --resolve "$H:443:127.0.0.1" "https://$H$p"
done
curl -s -o /dev/null -w 'http:// -> %{http_code}\n' --resolve "$H:80:127.0.0.1" "http://$H/"
curl -sk -o /dev/null -w 'unknown host name -> %{http_code}\n' --resolve "other.example:443:127.0.0.1" "https://other.example/" || true
302 /
302 /index.php
200 /jsonrpc.php
404 /config.php
404 /data/db.sqlite
404 /healthcheck.php
404 /cli
404 /app/common.php
404 /vendor/autoload.php
404 /index.php/x
404 //index.php
404 /.git/config
http:// -> 301
unknown host name -> 000
Every service runs with the instance metadata service blocked:
for u in nginx php8.3-fpm kanboard-cron kanboard-firstboot; do echo "$u $(systemctl show -p IPAddressDeny --value $u)"; done
nginx 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
php8.3-fpm 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
kanboard-cron 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
kanboard-firstboot 168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128
The code is owned by root, PHP runs as kanboard, and only kanboard can open the data directory:
stat -c '%U:%G %a %n' /var/www/kanboard /var/www/kanboard/index.php /etc/kanboard /var/lib/kanboard
sudo stat -c '%U:%G %a %n' /etc/kanboard/config.php /var/lib/kanboard/data
root:root 755 /var/www/kanboard
root:root 644 /var/www/kanboard/index.php
root:kanboard 750 /etc/kanboard
root:kanboard 750 /var/lib/kanboard
root:kanboard 640 /etc/kanboard/config.php
kanboard:kanboard 700 /var/lib/kanboard/data
Step 10: Maintenance
Operating system security updates install automatically; run sudo apt-get update && sudo apt-get upgrade to apply everything else. nginx and PHP-FPM restart cleanly and Kanboard keeps all of its data. New Kanboard releases arrive as new versions of this listing, and support can help you move your data to one.
| Component | Path |
|---|---|
| Kanboard | /var/www/kanboard (owned by root, read only to PHP) |
| Configuration | /etc/kanboard/config.php (root:kanboard, mode 0640) |
| Database, attachments and avatars | /var/lib/kanboard/data (db.sqlite; uploads under files/) |
| nginx site | /etc/nginx/sites-available/cloudimg-kanboard |
| Certificate and key | /etc/nginx/ssl/kanboard.crt, /etc/nginx/ssl/kanboard.key |
| Cron | kanboard-cron.timer and kanboard-cron.service |
| Helper | /usr/local/sbin/kanboard-set-hostname |
| Credentials | /root/kanboard-credentials.txt (mode 0600) |
| Source and changes | /usr/share/doc/kanboard/SOURCE.txt |
Step 11: Security recommendations
- Allow port 22 from your admin network only, and ports 80 and 443 only from the networks your team works from.
- Use your own DNS name and a certificate your users' browsers trust (Step 8).
- Change the administrator password and e-mail address as soon as you sign in, turn on two factor authentication, and give each person their own user (Step 5).
- Treat the API token on Settings, API as a password; anyone holding it can act on every project.
- Keep the operating system patched, and snapshot the root volume regularly.
Support and licensing
Kanboard is open source under the MIT licence, by Frédéric Guillot and its contributors; there is no per user licence fee. The image ships Kanboard exactly as released, with its bundled PHP libraries: /usr/share/doc/kanboard/SOURCE.txt names the tag and commit it came from and lists every file the image leaves out or adds, and no source file is modified. The AMI price covers cloudimg's hardening, first boot setup and support.
- Email: support@cloudimg.co.uk
- Website: https://www.cloudimg.co.uk
- Support: 24/7, with a 24 hour response SLA
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.