Kitsu
Overview
Kitsu, by CGWire, is an open source collaborative production tracking platform for animation, VFX and games studios. It gives a studio one place to run a production. You break a project down into episodes, sequences, shots and assets, define the task pipeline, assign the work, and track the status of every task on a board. You can also review and annotate media, and follow progress and workload across the whole team.
This SecureAnyCloud image runs Kitsu bare metal behind nginx, with PostgreSQL and Redis on the same VM. The whole platform is reachable on port 80. The administrator account, the PostgreSQL password and the token-signing secret are generated on the first boot of every VM, so no studio users, no production content and no shared secret ship in the image.
What you get:
- Kitsu 1.0.56 (the pre-built Vue web application) served by nginx on
:80, which also reverse-proxies the API and the events stream - Zou 1.0.64 (the Kitsu API) under gunicorn on loopback
:5000, with a second gunicorn process serving the Socket.IO events stream for real-time updates on:5001 - An RQ background worker (
zou-jobs) that processes preview and playlist encoding jobs with FFmpeg - PostgreSQL as the database, and Redis as the key-value store and job broker, both bound to loopback only
- Per-VM administrator, database and token-signing credentials generated at first boot. Two VMs launched from the same image never share a credential or a token-signing secret.
- The initial administrator email and password and the PostgreSQL password, written to
/root/kitsu-credentials.txtwith mode 0600 so that only the root user can read them - Six systemd units enabled and active
- 24/7 SecureAnyCloud support
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 starting size for a multi-user studio, because preview and movie encoding are processor- and memory-intensive. The image also runs comfortably on Standard_B2s (4 GiB) for small teams and evaluation.
Configure the network security group (NSG) to allow inbound 22/tcp from your management network. Also allow 80/tcp (plus 443/tcp once you enable HTTPS) from the networks your team will use to reach Kitsu.
Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Kitsu 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 HTTP (80).
Select Review + create, then Create. First-boot initialization takes approximately one to two minutes after the VM starts.
Deploy from the Azure CLI
Run the following commands. Replace the resource group, VNet and subnet with your own:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:kitsu-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name kitsu \
--image sac1647283583153:kitsu-ubuntu-24-04:default:latest \
--size Standard_B2ms \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name kitsu --port 80 --priority 1010Connect and Retrieve Initial Credentials
Connect over SSH with the key pair you supplied at deployment:
ssh azureuser@<vm-public-ip>The per-VM administrator and PostgreSQL passwords are written to a root-only file. Read the file with sudo, and confirm the versions you are running:
/opt/zou/zouenv/bin/pip show zou | awk -F': ' '/^Version/{print "Zou " $2}' cat /opt/kitsu/dist/.version.txt | sed 's/^/Kitsu SPA /'
sudo cat /root/kitsu-credentials.txtThe file lists the Kitsu administrator email and password, the database name, user and password, and the URL of the web interface. Keep these details somewhere safe.
Confirm the Services Are Running
The image runs six systemd units. Confirm that they are all active, that the datastores are bound to loopback only, and that the web application and API answer:
systemctl is-active postgresql redis-server nginx zou zou-events zou-jobs ss -tln | grep -E '127.0.0.1:5000|127.0.0.1:5001|127.0.0.1:5432|127.0.0.1:6379|:80 ' curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/api/statusExpect the following:
- All six units report
active. - PostgreSQL (
5432), Redis (6379) and the Zou API and events stream (5000/5001) listen on127.0.0.1only. - nginx listens on
:80. - Both the web application and the API return
200.
First Login to the Kitsu Web Interface
Open a web browser and go to http://<vm-public-ip>/. Kitsu shows its sign-in page. Enter the administrator email (<KITSU_ADMIN_EMAIL>) and the password from /root/kitsu-credentials.txt, then select Log in.
For a production deployment, change the administrator password that was generated on first boot. Use the user menu after you sign in.
Track a Production - Assets, Shots and Tasks
Kitsu organizes work by production. Create one from the Productions page with the Add a production button. Give it a name and a type, such as a short, a feature or a TV show. Each production carries its own resolution, frame rate and pipeline.
Inside a production, break the work down into assets (characters, props, environments) and shots (grouped into sequences). Then assign task types such as Modeling, Shading, Rigging, Layout and Animation.
Kitsu shows a breakdown grid per entity type, with a color-coded status cell for every task. A producer can see at a glance where the production stands, and an artist can see exactly what to do next.
As artists work, they set a task's status (to do, work in progress, waiting for approval, retake, done), publish previews for review, and leave comments. Supervisors review and approve from the same board.
The REST API
A REST API under /api/ backs everything in the web interface, and it requires authentication. You can drive it from curl: log in to obtain an access token, then pass the token as a bearer token. The examples below use the administrator password from the credentials file (shown as <KITSU_ADMIN_PASSWORD>):
# Log in and capture an access token
TOKEN=$(curl -s -H 'Content-Type: application/json' \
-d '{"email":"<KITSU_ADMIN_EMAIL>","password":"<KITSU_ADMIN_PASSWORD>"}' \
http://127.0.0.1/api/auth/login | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
# List productions with the token curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1/api/data/projects \
| python3 -m json.toolThe image is secure by default. The Zou project's default administrator (super.user@mycgstudio.com / mysecretpassword) does not exist on your VM and is rejected, and unauthenticated API calls are refused. Only the per-VM administrator generated at first boot can sign in:
# The Zou default admin is rejected (HTTP 400)
curl -s -o /dev/null -w '%{http_code}\n' -H 'Content-Type: application/json' \
-d '{"email":"super.user@mycgstudio.com","password":"mysecretpassword"}' \
http://127.0.0.1/api/auth/login
# An unauthenticated API request is rejected (HTTP 401)
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/api/data/projectsAdd Studio Users
Kitsu has no public self-registration by design. An administrator or manager invites each user, so a stranger cannot seize a freshly launched instance.
Add people from Studio → People in the web interface, or through the API. Set each person's role and department, and assign them to the productions they work on. New users receive their own login and see only the productions they are members of.
Real-Time Events and the Background Worker
Kitsu is collaborative in real time. When a colleague changes a task status or publishes a preview, everyone else's board updates live. The zou-events unit serves these updates as a Socket.IO stream on 127.0.0.1:5001, which nginx proxies at /socket.io.
Heavier work is handed to the zou-jobs RQ worker, which uses FFmpeg. This work includes normalizing uploaded movies, generating thumbnails and building playlists. Check both units:
systemctl status zou-events --no-pager | head -n 5
systemctl status zou-jobs --no-pager | head -n 5 ffmpeg -version | head -n 1Services and Operations
The zou unit runs the API under gunicorn on 127.0.0.1:5000. nginx reverse-proxies port 80 to the API, and to the events stream on :5001.
Configuration lives in /etc/zou/zou.env: the loopback database and Redis settings, the token-signing secret and the preview folder. Confirm the layout, then run Zou management commands as the zou user with the environment file loaded:
ls -ld /opt/zou/zouenv /opt/kitsu/dist /opt/zou/previews
sudo -u zou --preserve-env bash -c 'set -a; . /etc/zou/zou.env; set +a; /opt/zou/zouenv/bin/zou --help' | head -n 12Enable HTTPS with Let's Encrypt
For any production deployment, serve the site over HTTPS so that sign-in and media transfers cannot be intercepted. The image ships with nginx, which certbot can configure automatically.
Before you start, point a DNS record for your fully qualified domain name at the VM's public IP address, and add an NSG rule that allows 443/tcp. Then run:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d kitsu.your-domain.example \
--non-interactive --agree-tos -m you@your-domain.example \
--redirectWhen certbot finishes, set the public domain so that Kitsu generates correct links, then restart the API:
sudo sed -i 's|^DOMAIN_NAME=.*|DOMAIN_NAME=kitsu.your-domain.example|; s|^DOMAIN_PROTOCOL=.*|DOMAIN_PROTOCOL=https|' /etc/zou/zou.env
sudo systemctl restart zou zou-eventsBackups and Maintenance
Back up two things together: the PostgreSQL database (zoudb) and the preview store under /opt/zou/previews. This is a simple, coordinated backup:
sudo -u postgres pg_dump -Fc zoudb | sudo tee /var/backups/kitsu-$(date +%F).dump > /dev/null
sudo tar czf /var/backups/kitsu-previews-$(date +%F).tgz -C /opt/zou previews
sudo ls -lh /var/backups/Ship the dump and the preview archive to Azure Blob Storage or another object store on a schedule.
Ubuntu's unattended-upgrades is enabled, so kernel and package security patches apply automatically. To update Kitsu itself, follow the upgrade workflow in the official documentation at https://dev.kitsu.cloud/.
Scaling Beyond a Single VM
For larger studios, decouple Kitsu from the single-VM pattern:
- Move PostgreSQL to Azure Database for PostgreSQL and update
DB_HOSTin/etc/zou/zou.env. - Move Redis to Azure Cache for Redis and point
KV_HOSTat the cache endpoint. - Move the preview store to Azure Blob Storage mounted through BlobFuse, or to Azure Files.
- Put the web tier behind Azure Application Gateway, add the gateway hostname to
DOMAIN_NAME, and run thezou-jobsworker on dedicated VMs.
The official Kitsu documentation at https://dev.kitsu.cloud/ covers each of these.
Support
This image is backed by 24/7 SecureAnyCloud support, with a guaranteed response within 24 hours and a one-hour average for critical issues.
Contact sales@secureanycloud.com for help with deployment, upgrades, studio and user configuration, TLS termination, preview and encoding tuning, and database administration.
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 Azure
Launch Kitsu 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