Applications Azure

Koillection on Ubuntu 24.04 on Azure User Guide

| Product: Koillection on Ubuntu 24.04 LTS on Azure

Overview

Koillection is a free, open source, self hosted service for managing any kind of collection. Books, comics, coins, stamps, trading cards, vinyl, video games, wine, model kits: Koillection gives you one private catalogue for all of it. Collections nest as deeply as you need, and custom templates let you define exactly the fields each kind of item carries, with typed values for text, numbers, dates, prices, ratings, lists, countries, links and images. The cloudimg image delivers Koillection fully installed and configured on Ubuntu 24.04 as a Symfony application on PHP 8.5, backed by a local PostgreSQL database, so a complete collection manager is serving within minutes of launch, with your catalogue staying on infrastructure you control. Backed by 24/7 cloudimg support.

Koillection is licensed under the MIT License. All product and company names are trademarks or registered trademarks of their respective holders. This image repackages the upstream open source release with cloudimg's provisioning and support.

What is included:

  • Koillection 1.8.3 (MIT), served from /var/www/koillection
  • PHP 8.5 (php8.5-fpm) + nginx, with the web UI and REST API on port 80
  • A local PostgreSQL 16 database, bound to localhost only
  • The project's own webpack frontend bundle, built from source at image build time
  • A per-VM administrator password, a fresh application secret, a rotated database password and a freshly generated API signing keypair, all created on first boot and written to a root-only file, so no default or shared credentials ship in the image
  • postgresql, php8.5-fpm and nginx as systemd units, enabled and active
  • 24/7 cloudimg support

Koillection sign-in page served on first boot

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point; scale up for very large catalogues or many concurrent users. NSG inbound: allow 22/tcp from your management network and 80/tcp (HTTP) from wherever you will browse the catalogue. Add 443/tcp if you enable HTTPS.

Step 1 — Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Koillection by cloudimg, and select Create. On Basics 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). Then Review + create and Create.

Step 2 — Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name koillection \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Open HTTP to reach the web UI:

az vm open-port --resource-group <your-rg> --name koillection --port 80 --priority 900

Step 3 — Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 — Confirm the Koillection stack is running

Koillection is served by nginx on port 80, in front of php8.5-fpm, and backed by a local PostgreSQL database. PostgreSQL is bound to 127.0.0.1, so no database port is exposed to the network.

for u in postgresql php8.5-fpm nginx; do
  printf '%-18s %s\n' "$u:" "$(systemctl is-active $u)"
done
ss -tln | awk '/:80 /{print "nginx     "$4} /127.0.0.1:5432 /{print "postgres  "$4}' | sort -u

All three units report active, and only nginx listens on a public port:

postgresql:        active
php8.5-fpm:        active
nginx:             active
nginx     0.0.0.0:80
nginx     [::]:80
postgres  127.0.0.1:5432

Koillection stack services and localhost-only database

Why the site may not answer for the first minute. On the very first boot, nginx is deliberately held back until koillection-firstboot.service has generated this VM's secrets and created its administrator account. That is a security control, not a fault; see Step 10. If nginx reports inactive immediately after launch, wait a minute and check again.

Step 5 — Retrieve the first-boot administrator credentials

On the first boot of your instance, a one shot service generates a fresh application secret and API signing keypair, rotates the PostgreSQL password, builds the database schema and creates an administrator with a fresh random password, writing the credentials to a root-only file. Read them with:

sudo cat /root/koillection-credentials.txt

The file is mode 0600 and owned by root, and the administrator password is unique to this VM:

sudo stat -c '%a %U:%G %n' /root/koillection-credentials.txt
600 root:root /root/koillection-credentials.txt

Per-VM Koillection credentials, root-only and masked

Step 6 — Sign in to the web UI

Browse to http://<vm-public-ip>/ and sign in as the generated administrator (username admin) with the password from Step 5. Koillection opens on your collections overview:

Koillection collections overview after sign in

Change the administrator password straight away from the avatar menu in the top right, under Profile.

Step 7 — Build your first collection

Choose Collections, then the + button, give the collection a title such as Vinyl Records, and save. Open the collection and use + again to add items. Each item can carry its own typed fields — text, numbers, dates, prices, ratings, lists, countries, links and images — and if you want every item in a collection to share the same fields, define them once as a Template and set it as the collection's default.

Each collection chooses how its items are displayed. The default is a picture grid; switching the collection to List display (pencil icon → Items display, set Display mode to List and tick the fields you want as columns) shows the catalogue as a sortable table of your own fields:

A Koillection collection displayed as a sortable table of custom fields

Opening an item shows its full record, including every custom field value:

A Koillection item detail page with its custom field values

Alongside collections, Koillection gives you tags and tag categories, wishlists, loan tracking, photo albums, an activity history, saved searches and statistics, all reachable from the left-hand navigation.

Step 8 — Use the REST API

Koillection ships a documented REST API. Authenticate with the same administrator credentials to receive a JSON Web Token, then send it as a bearer token. Browse the interactive documentation at http://<vm-public-ip>/api/docs.

TOKEN=$(curl -s -X POST http://127.0.0.1/api/authentication_token \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"<KOILLECTION_ADMIN_PASSWORD>"}' | jq -r .token)
curl -s -H "Authorization: Bearer $TOKEN" -H 'Accept: application/ld+json' \
  http://127.0.0.1/api/collections | jq -c '{totalItems, collections: [.member[].title]}'

Once you have created a few collections, that returns them as JSON:

{"totalItems":3,"collections":["Vinyl Records","Board Games","Vintage Cameras"]}

The token is signed with the keypair generated for this VM on first boot, and an unauthenticated call is refused:

curl -s -o /dev/null -w 'GET /api/collections (no token) : HTTP %{http_code}\n' \
  -H 'Accept: application/ld+json' http://127.0.0.1/api/collections
GET /api/collections (no token) : HTTP 401

Koillection REST API authentication and catalogue query

Step 9 — Version and stack

The image ships Koillection 1.8.3 on PHP 8.5, PostgreSQL 16 and nginx:

echo -n 'Koillection version: '
grep -oE '"version": *"[0-9.]+"' /var/www/koillection/composer.json | head -1 | grep -oE '[0-9.]+'
php -v | head -1
sudo -u postgres psql -tAc 'SHOW server_version' | awk '{print $1}'
nginx -v
Koillection version: 1.8.3
PHP 8.5.8 (cli) (built: Jul  3 2026 05:09:00) (NTS)
16.14
nginx version: nginx/1.24.0 (Ubuntu)

Koillection version and application stack

Step 10 — The first-boot security model

No shared or default credentials ship in the image. On first boot, koillection-firstboot.service:

  • generates a fresh per-VM application secret and JWT passphrase,
  • rotates the PostgreSQL koillection role password and writes it into /var/www/koillection/.env.local,
  • regenerates the API signing keypair (the image ships none),
  • builds the database schema from empty,
  • creates the administrator account with a fresh per-VM random password, and
  • writes the credentials to /root/koillection-credentials.txt (root only, 0600).

That ordering matters. Koillection presents an unauthenticated setup page whenever it has no users, and whoever reaches it first becomes an administrator. This image therefore holds nginx back until first boot has finished: nginx.service carries a condition on the sentinel file the first-boot service writes last, so the application is never reachable while it has no administrator. If first boot fails, the site stays down rather than opening unprotected.

systemctl is-active koillection-firstboot.service
systemctl is-enabled koillection-firstboot.service
sudo stat -c '%a %U:%G' /root/koillection-credentials.txt
grep -h ConditionPathExists /etc/systemd/system/nginx.service.d/10-cloudimg-koillection.conf
active
enabled
600 root:root
ConditionPathExists=/var/lib/cloudimg/koillection-firstboot.done

New user accounts are created by an administrator from within the application; there is no anonymous sign-up.

Step 11 — Enable HTTPS with a custom domain (recommended)

Koillection stores personal data and image uploads, so put it behind TLS before you load a real catalogue. Point a DNS A record at your VM's public IP, then install a Let's Encrypt certificate with certbot. Open 443/tcp in your NSG first.

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d collection.your-domain.com

Certbot obtains the certificate and reconfigures nginx to serve Koillection over HTTPS and redirect HTTP to HTTPS. Koillection derives every URL from the request host, so no application configuration change is needed.

Step 12 — Maintenance

  • Upload quota. Each account has a disk-space allowance for images; the administrator account is provisioned with 10 GiB. Adjust it per user from Administration → Users.
  • Add more users from Administration → Users. Each user gets their own private collections.
  • Scraping. Koillection can populate item fields from a URL using the Scrapers feature. This image intentionally does not include Chromium, so scraping uses the standard HTTP fetch path: static pages work, while sites that build their content entirely in the browser return less. If you need the headless-browser path, install chromium and chromium-driver on the VM and restart php8.5-fpm.
  • Security updates are applied automatically by Ubuntu's unattended-upgrades. PHP, PostgreSQL and nginx are managed by systemd and restart on failure.
  • Back up the PostgreSQL koillection database together with the uploaded images:

text sudo -u postgres pg_dump koillection | gzip > ~/koillection-$(date +%F).sql.gz sudo tar czf ~/koillection-uploads-$(date +%F).tar.gz -C /var/www/koillection/public uploads

Support

cloudimg provides 24/7 support for this image by email (support@cloudimg.co.uk) and live chat, covering deployment, first-boot credential retrieval, collections, templates and custom fields, user management, the REST API, backup and restore, HTTPS and custom domains, upgrades and troubleshooting. For billing or subscription changes, contact support@cloudimg.co.uk.