Kill Bill
Overview
Kill Bill is a mature open-source platform for subscription billing and payments, released under the Apache License 2.0. It manages the whole recurring-revenue lifecycle: catalogs and price plans, subscriptions with trials, upgrades, downgrades and cancellations, usage metering, invoice generation and dunning, payments through pluggable gateways, refunds and chargebacks, credits and account balances, and a full audit trail over every change.
Kill Bill is multi-tenant from the ground up. Everything it exposes over its REST API is also available in the Kaui administration console that ships with this image.
This image ships Kill Bill 0.24.21 (released 12 August 2026) with Kaui 4.0.31 (released 15 September 2026). The version number is easy to misread: 0.24 is a pre-1.0 version number, not a pre-1.0 project. The 0.24 line has been Kill Bill's production series for years, across twenty-one patch releases, with a documented security process, and Kill Bill has a production lineage that began at Groupon.
What you get:
- Kill Bill 0.24.21 running in its own Apache Tomcat 9.0.122 instance as the unprivileged
killbilluser, bound to127.0.0.1:8080only - Kaui 4.0.31, the administration console, in a second Tomcat instance as the unprivileged
kauiuser, bound to127.0.0.1:9090only - Each application on the Java runtime its own upstream supports: Kill Bill on OpenJDK 17, Kaui on OpenJDK 21
- MySQL 8.0 bound to localhost, holding the
killbillandkauischemas - nginx as the only network front door, serving everything over HTTPS on port 443 with a certificate generated for your VM; port 80 issues a permanent redirect and answers load balancer probes at
/healthz - A default-deny host firewall, so the only ports reachable from outside your VM are 22, 80 and 443
- No default login and no data. The administrator password, the tenant API key and secret, both database passwords, the console's session and encryption keys and the TLS certificate are all generated on the first boot of your VM
Kill Bill and Kaui are trademarks of their respective owners. KILL BILL is separately a registered trademark of Miramax LLC for an unrelated film franchise. SecureAnyCloud is not affiliated with, endorsed by or sponsored by any of them. This image packages the unmodified open-source software.
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.
Standard_B2ms (2 vCPU, 8 GiB RAM) is the recommended size and the size this image is tested on. Kill Bill and Kaui are two JVMs whose configured heaps total 3.5 GiB, and with MySQL alongside them a 4 GiB VM cannot hold the stack without swap.
Configure the network security group (NSG) with these inbound rules: 22/tcp from your management network, 443/tcp for the console and API, and optionally 80/tcp, which only redirects to HTTPS.
Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Kill Bill by SecureAnyCloud, and select Create.
On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTPS (443). Then select Review + create and Create.
Deploy from the Azure CLI
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:killbill-ubuntu-24-04:default:latest
az vm create \
--resource-group my-resource-group \
--name killbill \
--image sac1647283583153:killbill-ubuntu-24-04:default:latest \
--size Standard_B2ms \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardOpen HTTPS to your users, and HTTP as well if you want the redirect:
az vm open-port --resource-group my-resource-group --name killbill --port 443 --priority 900
az vm open-port --resource-group my-resource-group --name killbill --port 80 --priority 910Connect to your VM
ssh azureuser@<vm-public-ip>Confirm the Kill Bill stack is running
First boot creates your databases, generates this VM's secrets and starts both applications before anything is served. Allow about three minutes after the VM is created. Kaui is a JRuby application and takes the longest to warm up. When the four services report active, the stack is ready:
systemctl is-active mysql killbill kaui nginxactive active active activeEach application runs on the Java runtime its own upstream supports, and Kill Bill answers its own health check:
curl -s -o /dev/null -w 'Kill Bill health: HTTP %{http_code}\n' http://127.0.0.1:8080/1.0/healthcheckKill Bill health: HTTP 200Check what the network can reach
Only SSH and the two web ports are reachable from outside your VM. Kill Bill, Kaui and MySQL are all bound to the loopback address:
ss -H -lnt | awk '{print $4}' | sort -u*:1099 *:36003 0.0.0.0:22 0.0.0.0:443 0.0.0.0:80 127.0.0.1:3306 127.0.0.53%lo:53 127.0.0.54:53 [::]:22 [::]:443 [::]:80 [::ffff:127.0.0.1]:8080 [::ffff:127.0.0.1]:9090Three entries deserve an explanation. [::ffff:127.0.0.1]:8080 and :9090 are the IPv4-mapped form of 127.0.0.1, which means Kill Bill and Kaui listen on loopback only.
*:1099 and the second high-numbered port beside it belong to an RMI registry that the Kill Bill plugin framework starts for its own use. The port is 36003 here, but the kernel picks a different one on every boot, so expect another number on your VM. Kill Bill only ever contacts the registry on 127.0.0.1, but the Java call that creates it accepts no bind address, so it binds every interface.
For this reason the image ships a default-deny firewall, which is what actually decides the reachable surface:
nft list chain inet sac_killbill input | grep -E 'policy|tcp dport'type filter hook input priority filter; policy drop; tcp dport { 22, 80, 443 } acceptPort 80 serves only a health probe and a permanent redirect to HTTPS:
curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' http://127.0.0.1/301 -> https://127.0.0.1/Retrieve this VM's credentials
Every secret this image uses is generated on the first boot of your own VM and written to a file only root can read. Nothing is shared with any other VM, and none of the credentials published in Kill Bill's own documentation works here.
ls -l /root/killbill-credentials.txt-rw------- 1 root root 977 /root/killbill-credentials.txtsudo sed -E 's/=(.+)/=<generated-on-your-vm>/' /root/killbill-credentials.txt# Kill Bill on Ubuntu 24.04 by sac - generated on first boot, unique to THIS VM.
# Keep this file safe. Change the administrator password after your first sign in. KILLBILL_URL=<generated-on-your-vm> KILLBILL_API_URL=<generated-on-your-vm> KILLBILL_ADMIN_USER=<generated-on-your-vm> KILLBILL_ADMIN_PASSWORD=<generated-on-your-vm> KILLBILL_TENANT_API_KEY=<generated-on-your-vm> KILLBILL_TENANT_API_SECRET=<generated-on-your-vm> KILLBILL_DB_USER=<generated-on-your-vm> KILLBILL_DB_PASSWORD=<generated-on-your-vm> KAUI_DB_USER=<generated-on-your-vm> KAUI_DB_PASSWORD=<generated-on-your-vm>To read the real values on your own VM, print the file:
sudo cat /root/killbill-credentials.txtRun the built-in self-test
The image ships a self-test that proves the appliance is working and that every credential published in the Kill Bill documentation is refused on your VM. These include the built-in admin/password administrator, the bob/lazar tenant from the tutorials, blank and weak passwords, and the root/root database login:
sudo /usr/local/sbin/killbill-selftest.sh /root/killbill-credentials.txt | tail -26The last line is KILLBILL_SELFTEST_OK when every check passed.
Sign in to the Kaui console
Open the KILLBILL_URL value from the credentials file in a browser. It is https://<vm-public-ip>/. Sign in as admin with KILLBILL_ADMIN_PASSWORD.
Your browser warns about the certificate because the image generates a self-signed certificate for your VM's address at first boot. Step 12 explains how to install your own.
Register your tenant
Kill Bill is multi-tenant, and first boot has already created a tenant for you with the API key and secret in your credentials file. Kaui stores tenant API secrets itself, encrypted at rest, so it asks you to register that tenant the first time you sign in. This is the normal Kill Bill onboarding, not an error.
On the Add tenant page, enter any name you like (for example production). Paste KILLBILL_TENANT_API_KEY into API key and KILLBILL_TENANT_API_SECRET into API secret, then save.
Load a catalog and create your first subscription
Kill Bill bills against a catalog: the products, plans and prices you sell. Until you upload one, there is nothing to subscribe an account to. The commands below use the REST API with the credentials from Step 6. Export the credentials first so that they never appear in your shell history:
read -rs KBPW && export KBPW read -rs KBKEY && export KBKEY read -rs KBSEC && export KBSECUpload a minimal catalog with one GBP 29/month plan. The catalog endpoint requires the text/xml content type:
curl -sS -X POST \
-u "admin:$KBPW" \
-H "X-Killbill-ApiKey: $KBKEY" -H "X-Killbill-ApiSecret: $KBSEC" \
-H 'X-Killbill-CreatedBy: setup' -H 'Content-Type: text/xml' \
--data-binary @catalog.xml \
https://<vm-public-ip>/1.0/kb/catalog/xmlCreate an account:
curl -sS -X POST \
-u "admin:$KBPW" \
-H "X-Killbill-ApiKey: $KBKEY" -H "X-Killbill-ApiSecret: $KBSEC" \
-H 'X-Killbill-CreatedBy: setup' -H 'Content-Type: application/json' \
-d '{"name":"Northwind Trading Ltd","email":"billing@northwind.example","currency":"GBP","externalKey":"northwind"}' \
https://<vm-public-ip>/1.0/kb/accountsThen subscribe it to a plan, using the accountId the previous call returned in its Location header:
curl -sS -X POST \
-u "admin:$KBPW" \
-H "X-Killbill-ApiKey: $KBKEY" -H "X-Killbill-ApiSecret: $KBSEC" \
-H 'X-Killbill-CreatedBy: setup' -H 'Content-Type: application/json' \
-d '{"accountId":"<account-id>","planName":"standard-monthly"}' \
'https://<vm-public-ip>/1.0/kb/subscriptions?callCompletion=true&callTimeoutSec=40'Accounts you create appear immediately in Kaui:
Opening an account shows what billing has produced: the balance, the bill cycle day and the date of the next invoice.
The Subscriptions tab shows the recurring plan itself, with the date it is charged up to.
Using the REST API
Kaui is built on the REST API at https://<vm-public-ip>/1.0/kb/, so everything Kaui does is available there. Requests use HTTP basic authentication with the administrator credentials, plus the two tenant headers:
curl -sS -u "admin:$KBPW" \
-H "X-Killbill-ApiKey: $KBKEY" -H "X-Killbill-ApiSecret: $KBSEC" \
'https://<vm-public-ip>/1.0/kb/accounts/pagination'Any call that changes data also requires X-Killbill-CreatedBy, which Kill Bill records in its audit log.
Two groups of endpoints are deliberately refused at the front door on this image. /1.0/kb/test is Kill Bill's integration-test clock, which can move time forward and cause invoices to be generated; it is disabled in the application and blocked by nginx. /1.0/kb/admin contains cache-flush and queue endpoints which, in this release, check only that you are authenticated and not what permissions you hold. Both are reachable from a shell on the VM via http://127.0.0.1:8080 if you genuinely need them.
curl -sk -o /dev/null -w '/1.0/kb/test/clock -> %{http_code}\n' https://127.0.0.1/1.0/kb/test/clock/1.0/kb/test/clock -> 404Use your own domain and certificate
Point a DNS record at your VM's public IP address, then replace the self-signed certificate. To do this with certbot, run:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d billing.example.comCertbot rewrites the nginx server block and reloads it. To install a certificate you already hold instead, replace /etc/ssl/killbill/killbill.crt and /etc/ssl/killbill/killbill.key (keep the key 0600 root:root) and reload nginx.
Back up and restore
Everything transactional lives in the two MySQL schemas. Back both up together. The Kaui schema holds your tenant registrations, and a killbill backup without it means re-registering tenants by hand:
sudo mysqldump --single-transaction --routines --databases killbill kaui \
| gzip > killbill-backup-$(date +%F).sql.gzAlso copy /root/killbill-credentials.txt somewhere safe: it holds the tenant API secret, which Kill Bill stores only as a hash and cannot show you again.
To restore onto a fresh VM, stop the applications, load the dump, and start them again:
sudo systemctl stop kaui killbill gunzip < killbill-backup-2026-09-20.sql.gz | sudo mysql
sudo systemctl start killbill kauiKeep the VM patched
The image is built entirely from Ubuntu's main archive and unattended-upgrades is enabled, so operating system security updates install themselves. To apply everything pending immediately:
sudo apt-get update && sudo apt-get -y upgradeKill Bill, Kaui and Tomcat are installed from upstream release artifacts rather than Ubuntu packages, so they are upgraded by replacing the deployed application. Check the running versions before and after any upgrade, and always take a database backup first, because Kill Bill applies schema migrations on start-up.
Troubleshooting
Kaui shows a 500 error just after boot. Kaui is a JRuby application, and its first start takes a minute or two on a 2 vCPU VM. Check progress with journalctl -u kaui -f. If the error persists, confirm that /etc/killbill/kaui.env exists and that first boot completed with systemctl status killbill-firstboot.
The sign-in page rejects the password from the credentials file. Confirm you are using KILLBILL_ADMIN_PASSWORD and the username admin. Kill Bill records failed sign-ins and rate-limits by source address, so wait a moment between attempts.
Kaui signs in but shows no data. The tenant is not registered in Kaui yet. See Step 9.
Check everything at once. The self-test in Step 7 exercises the services, the reachable port set, the credential round trip and the refusal of every published default, and prints a line per check.
Deploy on Azure
Launch Kill Bill on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com