Applications Azure

Invio on Ubuntu 24.04 on Azure User Guide

| Product: Invio on Ubuntu 24.04 LTS on Azure

Overview

Invio is a lightweight, self hosted invoicing app that keeps invoicing simple. You create clients, build invoices and quotes, track which invoices are paid, and share a secure link to an invoice so a client can view and download it without creating an account. Your data stays on your own virtual machine in a local database.

The cloudimg image runs Invio the officially supported way: the single upstream container image, pinned by digest to release v2.1.1, run under systemd. The app and its embedded SQLite database are bound to the loopback interface, and only an nginx front end that terminates TLS is exposed. Because every invoicing app signs its login sessions with a secret key, security is enforced from first boot, before the ports are reachable: a unique admin password and a unique JWT signing key are generated for each VM, the admin account is seeded into a brand new database, and a fresh self signed TLS certificate is created. Backed by 24/7 cloudimg support.

Invio is the work of its respective author (kittendevv). This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by Invio. It ships the unmodified upstream release, which its author has placed in the public domain under The Unlicense; the verbatim licence text ships inside the image under /usr/share/doc/cloudimg/third-party-licences.

The Invio sign in screen served over HTTPS

What is included:

  • Invio v2.1.1, the official upstream container pinned by digest to the release
  • An embedded SQLite database on a local path, with no external database to run
  • An nginx front end that terminates HTTPS with a per VM self signed certificate
  • A unique admin password and a unique JWT signing key generated per VM on first boot
  • A clean, empty instance on first boot with no default account and no shipped data
  • 24/7 cloudimg support

Before you begin

You will need an Azure subscription, an SSH key pair, and a virtual network. The web interface is served over HTTPS on port 443. In your network security group, allow inbound port 22 for SSH (ideally from your management address only) and port 443 for the web interface.

Recommended size: Standard_B2s (2 vCPU, 4 GiB). Invio is very light and runs comfortably on that size.

Deploy from the Azure Marketplace

  1. In the Azure portal, search the Marketplace for Invio on Ubuntu 24.04 LTS by cloudimg and select Create.
  2. Choose your subscription, resource group and region.
  3. Set the VM size to Standard_B2s, choose SSH public key authentication, and set the admin username.
  4. On the Networking tab, allow inbound 443 (HTTPS) and 22 (SSH). Restrict SSH to your own address where possible.
  5. Review and create. When the VM is running, note its public IP address.

Deploy with the Azure CLI

You can deploy the same image from the command line. Replace the placeholders with your own values.

az group create --name invio-rg --location eastus

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

# Allow the web interface (443) and SSH (22)
az vm open-port --resource-group invio-rg --name invio --port 443 --priority 1001

Once the VM is running, browse to https://<vm-ip>/ and continue below.

First boot: your unique admin password

On first boot, before the web port is reachable, the image generates a unique admin password and a unique JWT signing key for this VM, seeds the admin account into a fresh database, and creates a self signed TLS certificate. The upstream default password is never used. Read your VM's admin password over SSH:

sudo cat /root/invio-credentials.txt

The file is readable only by root and contains your Invio URL, the admin username (admin) and the per VM admin password. Keep it safe.

The per VM admin password and unique signing key generated on first boot; the upstream default password is rejected

Sign in

Browse to https://<vm-ip>/. Because the certificate is a per VM self signed certificate, your browser will warn once; accept the warning to continue (put your own domain and a trusted certificate in front for production, see below). Sign in with the username admin and the password from the credentials file.

The Invio dashboard after signing in with the per VM admin password

Create your first client and invoice

  1. Open Customers and add a client with their name and contact details.
  2. Open Invoices, select New, choose the client, add one or more line items (description, quantity and unit price), and save. Invio calculates the totals for you.
  3. When you are ready, Publish the invoice and use Download PDF or share the secure invoice link so your client can view and download it without an account.

The invoice list showing a real client and invoice

An invoice rendered for the client, with line item and total

Verify the deployment

Confirm the services are running and the web interface answers over HTTPS. These commands run on the VM over SSH:

# Docker, the Invio container and nginx should all be active
systemctl is-active docker invio nginx

# The login page is served through nginx over HTTPS (self signed -> -k)
curl -sk -o /dev/null -w 'https login page -> HTTP %{http_code}\n' https://127.0.0.1/login

# HTTP is redirected to HTTPS
curl -s -o /dev/null -w 'http redirect     -> HTTP %{http_code}\n' http://127.0.0.1/

Invio running: the pinned container under systemd, nginx TLS public, the app on loopback only

Secure by default

Invio signs every login session with the JWT_SECRET key, so a shipped default key would let anyone forge an admin session. This image generates a unique key and a unique admin password for each VM on first boot, so neither the upstream default password nor a shared signing key is ever present. You can prove the upstream default is rejected and only your per VM password authenticates:

# The upstream default password is rejected
curl -sk -o /dev/null -w 'default password -> HTTP %{http_code}\n' \
  -X POST https://127.0.0.1/api/v1/auth/login \
  -H 'content-type: application/json' \
  -d '{"username":"admin","password":"supersecret"}'

# Your per VM password authenticates (returns a session token)
curl -sk -o /dev/null -w 'your password    -> HTTP %{http_code}\n' \
  -X POST https://127.0.0.1/api/v1/auth/login \
  -H 'content-type: application/json' \
  -d '{"username":"admin","password":"<INVIO_ADMIN_PASSWORD>"}'

The first request returns 401 (rejected); the second returns 200.

A real authenticated round trip: a client and an invoice created and read back from the local SQLite database

Data and backups

Invio stores everything in a single SQLite database on the VM at /var/lib/invio/data/invio.db (mounted into the container at /app/data). To back up your data, stop the app briefly and copy the database file:

sudo systemctl stop invio
sudo cp -a /var/lib/invio/data/invio.db /var/lib/invio/data/invio.db.backup
sudo systemctl start invio

Keep the backup somewhere safe off the VM. Restoring is the reverse: stop the app, replace invio.db, and start it again.

Move to your own domain with TLS

For production, put your own domain name and a trusted certificate in front of Invio rather than the per VM self signed certificate. Point a DNS record at the VM, then terminate TLS for your domain (for example with your own certificate on the built in nginx, or behind an Azure Application Gateway or another reverse proxy). Restrict the network security group so only the addresses that need it can reach the VM.

Licensing

Invio is released into the public domain under The Unlicense, so there is no per seat fee for the software and no source or notice obligation. The verbatim licence text ships inside the image at /usr/share/doc/cloudimg/third-party-licences/invio-2.1.1-LICENSE.txt. The cloudimg charge covers packaging, security patching, image maintenance and 24/7 support. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by Invio or its author.

Support

Email support@cloudimg.co.uk for help with this image. For questions about Invio itself, see the upstream project at https://github.com/kittendevv/Invio.