Kiwi TCMS
Overview
Kiwi TCMS is an open source test case management system that QA and engineering teams use to plan, organise and track manual and automated testing. It manages products, test plans, test cases, test runs and executions, tracks requirements and history, integrates with bug trackers, and exposes a full REST/JSON-RPC API for automation.
This SecureAnyCloud image is built from Kiwi TCMS 16.2 (GPL-2.0). It runs the official Kiwi TCMS Docker Compose stack, the Kiwi web application plus a MariaDB database, behind host nginx. nginx terminates TLS on port 443 with a per-instance self-signed certificate.
Every application secret, the database passwords, the TLS certificate and a strong administrator account are generated uniquely on the first boot of each instance. No shared or default credential ships in the image, and public self-registration is disabled.
What you get:
- Kiwi TCMS 16.2 as the official Docker Compose stack: the Kiwi web application (Django + Apache/mod_wsgi) and a MariaDB 11.4 database
- Host nginx terminating TLS on port 443 with a per-instance self-signed certificate, and plain HTTP on port 80 redirecting to HTTPS
- The database on the internal container network only, with no externally reachable port
- The stack managed by a single
kiwi-tcms.servicesystemd unit, enabled and active on every boot - All stateful Docker volumes (the MariaDB database and uploads) relocated onto a dedicated EBS data volume mounted at
/var/lib/kiwi-tcms - A first-boot service that generates a fresh Django secret key, database passwords, a per-instance TLS certificate and a strong administrator account, and records the admin credentials in a root-only file
- 24/7 SecureAnyCloud support
Prerequisites
You need an AWS account, an EC2 key pair in the target region, and a VPC with a public subnet.
m5.large (2 vCPU / 8 GiB RAM) is the recommended instance type.
Configure the security group to allow inbound 22/tcp from your management network, and 443/tcp for the web console. Also allow 80/tcp, which redirects to HTTPS. The image serves the console over HTTPS on port 443 with a per-instance self-signed certificate. For production, replace it with a certificate for your own domain.
Step 1 - Launch the AMI
Subscribe to the listing in AWS Marketplace and choose Continue to Launch. Launch the AMI from the EC2 console or the AWS CLI. Select the m5.large instance type, your key pair, and a security group that opens ports 22, 80 and 443.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <security-group-id> \
--subnet-id <subnet-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=kiwi-tcms}]'Step 2 - Connect to your instance
Connect over SSH as the default login user for the OS variant you launched. This listing may include more than one OS variant, so use the login user that matches yours.
Ubuntu 24.04 LTS: log in as ubuntu with ssh ubuntu@<instance-public-ip>
Step 3 - Confirm the stack is running
Kiwi TCMS runs as a Docker Compose stack wrapped by a single systemd unit and fronted by nginx. A one-shot first-boot service rotates every secret on the first boot. Confirm that all four services are healthy:
systemctl is-active docker.service nginx.service kiwi-tcms.service kiwi-tcms-firstboot.serviceAll four report active. kiwi-tcms-firstboot.service is a one-shot unit that stays active after it completes.
Step 4 - Inspect the Compose stack
List the containers that make up the Kiwi TCMS appliance:
sudo docker compose -f /opt/kiwi-tcms/compose.yaml --env-file /opt/kiwi-tcms/.env ps --format 'table {{.Service}}\t{{.Status}}'Both web and db show Up, and the db container reports healthy. The web container publishes its HTTPS port on 127.0.0.1:8443 only. nginx on the host is the single public entry point.
Step 5 - Confirm the version and endpoints
Check the running Kiwi TCMS version and that the web endpoints answer through nginx:
sudo docker compose -f /opt/kiwi-tcms/compose.yaml --env-file /opt/kiwi-tcms/.env exec -T web python -c 'import tcms; print("Kiwi TCMS", tcms.__version__)' curl -ks -o /dev/null -w 'login page: HTTP %{http_code}\n' https://127.0.0.1/accounts/login/ curl -s -o /dev/null -w 'HTTP redirect: HTTP %{http_code}\n' http://127.0.0.1/The version reads Kiwi TCMS 16.2, the login page returns 200 over HTTPS, and plain HTTP returns 301, redirecting to HTTPS. The login page needs no authentication, so you can use it as a load balancer health check.
Step 6 - Check the data volume
The MariaDB database and the uploads live on a dedicated EBS data volume mounted at /var/lib/kiwi-tcms, separate from the OS disk. The Docker data-root is relocated there. Confirm the mount:
findmnt -no SOURCE,TARGET,FSTYPE /var/lib/kiwi-tcmsThe output shows an ext4 filesystem mounted at /var/lib/kiwi-tcms. To preserve your database and uploads, back up that volume, for example with an EBS snapshot.
Step 7 - Retrieve the per-instance admin credentials
The first-boot service generated a unique administrator account for this instance and wrote it to a root-only credentials file. Read the URL and username from the file. The password is stored on the KIWI_ADMIN_PASSWORD line and is set at first boot.
sudo stat -c '%a %U:%G %n' /root/kiwi-tcms-credentials.txt
sudo grep -E '^KIWI_(URL|ADMIN_USER)=' /root/kiwi-tcms-credentials.txtThe file is 600 root:root. To display the generated password, run sudo grep '^KIWI_ADMIN_PASSWORD=' /root/kiwi-tcms-credentials.txt.
Step 8 - Verify the admin credential end to end
Confirm that the generated administrator credential authenticates against the login form through nginx, and that a wrong password is rejected. The script reads the password into a shell variable and never prints it. It shows only the HTTP status: 302 on success, or 200 when the login form is re-rendered after a rejected attempt.
USER="$(sudo grep '^KIWI_ADMIN_USER=' /root/kiwi-tcms-credentials.txt | cut -d= -f2-)" PASS="$(sudo grep '^KIWI_ADMIN_PASSWORD=' /root/kiwi-tcms-credentials.txt | cut -d= -f2-)" JAR="$(mktemp)" CSRF="$(curl -ks -c "$JAR" https://127.0.0.1/accounts/login/ | grep -oE 'name="csrfmiddlewaretoken"[^>]*value="[^"]+"' | grep -oE 'value="[^"]+"' | head -1 | sed 's/value="//;s/"//')" curl -ks -o /dev/null -w 'valid login: HTTP %{http_code}\n' -b "$JAR" -c "$JAR" -H "Referer: https://127.0.0.1/accounts/login/" -X POST https://127.0.0.1/accounts/login/ --data-urlencode "csrfmiddlewaretoken=$CSRF" --data-urlencode "username=$USER" --data-urlencode "password=$PASS" curl -ks -o /dev/null -w 'wrong login: HTTP %{http_code}\n' -b "$JAR" -H "Referer: https://127.0.0.1/accounts/login/" -X POST https://127.0.0.1/accounts/login/ --data-urlencode "csrfmiddlewaretoken=$CSRF" --data-urlencode "username=$USER" --data-urlencode "password=wrong-pass-xyz" rm -f "$JAR"The valid credential returns 302, a successful login redirect. The wrong password returns 200, the login form re-rendered with an error.
Step 9 - Confirm the database is private
The MariaDB database runs on the internal container network only, with no host-published port, so it is not reachable from outside the instance. Confirm that nothing listens on 3306 on any host address:
sudo ss -ltnH | awk '{print $4}' | grep -E ':3306$' || echo '3306 is not listening on any host address'Step 10 - Sign in to the console
Browse to https://<instance-public-ip>/ in any modern browser. The image ships a per-instance self-signed certificate, so accept the browser warning or install a certificate for your own domain. Sign in with the username and password from Step 7.
Step 11 - Explore the dashboard
After you sign in, the dashboard shows your recent test executions with completion bars and the test plans you manage. On a fresh instance both start empty. They fill as you create products, plans, cases and runs.
Step 12 - Test plans and test cases
Kiwi TCMS organises testing into products, test plans and test cases. Create a product under TESTING -> Products and add a version. Then create a test plan for it and add test cases.
Each case captures a summary, steps, priority, category and status, and can be automated or manual.
Step 13 - Test runs and executions
A test run executes a plan's cases against a build. Create a run, then record each case as passed, failed, blocked or waived. The run's completion bar and per-status counts update as you go, giving you a live view of coverage and results.
Step 14 - Automate with the API
Kiwi TCMS exposes a JSON-RPC API at /json-rpc/. Use it to submit results from your CI/CD pipeline and to script any object the UI manages: products, plans, cases, runs and executions.
Authenticate with your administrator credentials, then call methods such as TestCase.filter, TestRun.create and TestExecution.update. See the Kiwi TCMS API documentation for the full method list. In this example, replace the host and password:
curl -s -c cookies.txt https://<instance-public-ip>/accounts/login/
# obtain a CSRF cookie
# then POST to /json-rpc/ with your session, calling e.g. TestCase.filter({})Step 15 - Configure email notifications (optional)
Kiwi TCMS can email notifications, for example when a test case a user follows changes. No SMTP server is configured out of the box, so notifications are skipped silently and never block an action. To enable them, configure your SMTP settings in the Kiwi TCMS environment and restart the web container:
sudo docker compose -f /opt/kiwi-tcms/compose.yaml --env-file /opt/kiwi-tcms/.env restart webSupport
SecureAnyCloud images come with 24/7 support. Our engineers can help with deployment, replacing the self-signed certificate with one for your own domain, bug-tracker and API integration, backup and storage planning, and scaling the stack. Contact support through the AWS Marketplace listing or the SecureAnyCloud website.
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.
Deploy on AWS
Launch Kiwi TCMS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com