Kiwi TCMS is a powerful open-source test management system built on Django and MariaDB. In this guide, we’ll install Kiwi TCMS using Docker on Ubuntu 24.04, enable HTTPS, and configure it to auto-start using systemd
.
Prerequisites
- Ubuntu 24.04 server
- DNS:
kiwi.maksonlee.com
managed by Cloudflare - Docker + Compose plugin: Install Docker on Ubuntu 24.04
- Port 443 open (port 80 is not required)
Install required packages:
sudo apt update
sudo apt install -y certbot python3-certbot-dns-cloudflare
sudo add-apt-repository ppa:vbernat/haproxy-3.2 -y
sudo apt-get install haproxy=3.2.\*
sudo systemctl enable --now haproxy
- Clone Kiwi TCMS OSS Repository
git clone https://github.com/kiwitcms/Kiwi.git
sudo mv Kiwi /opt/kiwi
cd /opt/kiwi
This gives you the official docker-compose.yml
file. Kiwi listens on ports 8080
and 8443
internally and maps them to 80
and 443
by default.
- Run Kiwi Initial Setup
Start the container stack:
docker compose up -d
Then run the initialization:
docker exec -it kiwi_web /Kiwi/manage.py initial_setup
You’ll be prompted to:
- Create the admin user
- Set the domain (e.g.
kiwi.maksonlee.com
) - Assign default roles
- Cloudflare Token & Certbot Credentials
- Generate Cloudflare Token
- Go to: Cloudflare API Tokens → Create Token
- Use the “Edit zone DNS” template:
- Permissions:
- Zone → DNS → Edit
- Zone Resources:
- Include →
maksonlee.com
- Include →
- Permissions:
- Click Create Token, copy the value.
- Create
cloudflare.ini
vi ~/.secrets/certbot/cloudflare.ini
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
Set strict permissions:
chmod 600 ~/.secrets/certbot/cloudflare.ini
- Issue Let’s Encrypt Cert via DNS-01
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \
-d kiwi.maksonlee.com
- Apply HTTPS Certificate
You can secure Kiwi TCMS via HTTPS using either of the following options:
Option 1 – Use HAProxy for SSL Termination
In this setup, Kiwi listens on 127.0.0.1:8443
, and HAProxy terminates HTTPS at the host level.
- Limit Kiwi to localhost
Create docker-compose.override.yml
:
services:
web:
ports: !override
- "127.0.0.1:8443:8443"
Restart Docker Compose:
docker compose down
docker compose up -d
- Combine your TLS cert
sudo mkdir -p /etc/haproxy/certs/
sudo bash -c "cat /etc/letsencrypt/live/kiwi.maksonlee.com/fullchain.pem /etc/letsencrypt/live/kiwi.maksonlee.com/privkey.pem > /etc/haproxy/certs/kiwi.maksonlee.com.pem"
sudo chmod 600 /etc/haproxy/certs/kiwi.maksonlee.com.pem
- Configure HAProxy
Edit /etc/haproxy/haproxy.cfg
:
frontend https-in
bind *:443 ssl crt /etc/haproxy/certs/kiwi.maksonlee.com.pem
mode http
default_backend kiwi_backend_https
backend kiwi_backend_https
mode http
server kiwi 127.0.0.1:8443 ssl verify none
Reload HAProxy:
sudo systemctl restart haproxy
Option 2 – Mount Certs into the Kiwi Container
This lets Kiwi’s internal NGINX handle HTTPS.
- Copy and secure your certs
sudo mkdir -p /opt/kiwi/ssl
sudo cp /etc/letsencrypt/live/kiwi.maksonlee.com/fullchain.pem /opt/kiwi/ssl/localhost.crt
sudo cp /etc/letsencrypt/live/kiwi.maksonlee.com/privkey.pem /opt/kiwi/ssl/localhost.key
sudo chmod 644 /opt/kiwi/ssl/localhost.crt
sudo chmod 600 /opt/kiwi/ssl/localhost.key
sudo chown -R $USER:$USER /opt/kiwi
- Create override:
services:
web:
volumes:
- /opt/kiwi/ssl/localhost.crt:/Kiwi/ssl/localhost.crt:ro
- /opt/kiwi/ssl/localhost.key:/Kiwi/ssl/localhost.key:ro
- Restart Kiwi
docker compose down
docker compose up -d
SSL Integration Comparison
Feature | HAProxy (Re-Encrypt) | Mounting Certs into Container |
---|---|---|
Public HTTPS Support | ✅ Yes | ✅ Yes |
SSL Termination Outside App | ✅ Clean separation | ❌ Handled inside container |
Requires Container Changes | ❌ No | ✅ Yes (bind certs manually) |
Auto-updates Compatible | ✅ Yes | ⚠️ Must remount after rebuild |
Performance | ⚠️ Slight CPU cost | ✅ Slightly better |
Best for Production (multi-service) | ✅ Yes | ✅ Good for single app only |
- Enable Auto-Start with systemd
You can use systemd
to start Kiwi automatically on boot.
- Create service file
sudo vi /etc/systemd/system/kiwi.service
Paste:
[Unit]
Description=Kiwi TCMS Docker Compose Application
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
WorkingDirectory=/opt/kiwi
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
RemainAfterExit=yes
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
- Enable and start
sudo systemctl daemon-reload
sudo systemctl daemon-reexec
sudo systemctl enable --now kiwi.service
- Confirm it works after reboot
sudo reboot
Then check:
docker ps
systemctl status kiwi
- Auto-Renew Deploy Hook
Create a deploy hook:
sudo vi /etc/letsencrypt/renewal-hooks/deploy/reload-haproxy.sh
Paste:
#!/bin/bash
cat "$RENEWED_LINEAGE/fullchain.pem" "$RENEWED_LINEAGE/privkey.pem" > /etc/haproxy/certs/kiwi.maksonlee.com.pem
systemctl reload haproxy
Make it executable:
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-haproxy.sh