Applications Azure

Shlink on Ubuntu 24.04 on Azure User Guide

| Product: Shlink on Ubuntu 24.04 LTS on Azure

Overview

Shlink is a self hosted URL shortener that gives you complete ownership of your short links, their data and their analytics. This cloudimg image runs Shlink 5.1.0 behind nginx with PHP 8.4 FPM on a hardened, fully patched Ubuntu 24.04 LTS base. Short URLs, their visits and all analytics are stored in a SQLite database on a dedicated Azure data disk mounted at /opt/shlink-data, so the data tier is separate from the operating system disk. The official Shlink web client, a single page application, is served on the same VM and is pre connected to the local REST API.

The Shlink REST API and short URL redirects are served at the VM root, with the API under the /rest path. Browsing to the VM address opens the web client management console. A systemd timer runs Shlink's visit processing every fifteen minutes.

A per VM administrator API key is generated on the first boot of every deployed VM. Two VMs launched from the same image never share a key, and no demo data, short URLs or keys ship in the image. The generated key is written to /root/shlink-credentials.txt with mode 0600 so only the root user can read it, and the web client's server entry is wired to it automatically.

On first boot the image reads the VM address from Azure instance metadata and uses it as Shlink's default short domain, so generated short URLs use the address customers reach the VM on. To serve short links on your own branded domain, set a custom domain as described later in this guide.

What is included:

  • Shlink 5.1.0 served by nginx and PHP 8.4 FPM, managed by systemd
  • The official Shlink web client 4.7.1, pre connected to the local REST API
  • A SQLite database on a dedicated Azure data disk at /opt/shlink-data
  • A per VM administrator API key generated on first boot and recorded in a root only file
  • shlink-visits.timer, which processes and geolocates visits every fifteen minutes
  • The REST API under /rest for programmatic link creation and analytics
  • 24/7 cloudimg support

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 sensible starting point; size up for higher redirect volumes. Network security group inbound: allow 22/tcp from your management network and 80/tcp (and 443/tcp once you add TLS) from the networks that will use your short links. The Azure CLI is required only if you deploy from the command line.

Step 1: Launch from the Azure Marketplace

Sign in to the Azure portal, select Create a resource, and search the Marketplace for Shlink on Ubuntu 24.04 LTS by cloudimg. Select the offer, choose the plan, and select Create.

On the Basics tab pick your subscription and resource group, a region, and a VM size of Standard_B2s or larger. Set the authentication type to SSH public key, the username to azureuser, and provide your public key. On the Networking tab select your VNet and subnet and a network security group that allows inbound 22/tcp and 80/tcp. Review and create. First boot initialisation completes about a minute after the VM reaches the Running state.

Step 2: Launch from the Azure CLI

The following block creates a VM from the cloudimg Shlink image. Replace the placeholders with your own values. The image reference is shown on the Marketplace offer page.

az vm create \
  --resource-group <your-resource-group> \
  --name shlink-01 \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values <path-to-your-public-key> \
  --public-ip-sku Standard \
  --nsg-rule SSH

After the VM is running, open ports 80 (and 443 once you add TLS) on its network security group, then retrieve its public IP with az vm show -d -g <your-resource-group> -n shlink-01 --query publicIps -o tsv.

Step 3: Connect and Retrieve the API Key

Connect over SSH as azureuser with the VM's public IP address:

ssh azureuser@<public-ip>

Once connected, read the generated API key. It is stored in a root only file, so use sudo:

sudo cat /root/shlink-credentials.txt

The file contains the web client URL, the REST API base URL, and the per VM API key:

The per VM Shlink credentials file, showing the web client URL, the REST API base URL and the generated administrator API key

Step 4: Confirm the Service Is Healthy

Shlink exposes an unauthenticated health endpoint. Confirm it reports pass and the expected version, and check that nginx and PHP FPM are active:

systemctl is-active nginx php8.4-fpm

The nginx and php8.4-fpm services active, with nginx listening on port 80

curl -s http://127.0.0.1/rest/health

A healthy VM returns a JSON document containing "status":"pass" and "version":"5.1.0".

The Shlink REST health endpoint returning status pass and version 5.1.0, with PHP 8.4 and the Shlink and web client versions

Step 5: Open the Shlink Web Client

Browse to http://<public-ip>/ in a web browser. The Shlink web client loads and automatically connects to this VM using the generated API key, so no manual server set up is required. The Overview page shows total visits, the number of short URLs, recently created links, and a form to create a new short URL.

The Shlink web client overview dashboard showing total visits, short URL and tag counts, and recently created short URLs

The List short URLs page lists every short URL with its destination, tags and visit count, and provides search and filtering.

The Shlink web client list of short URLs, each with its title, tags and visit count

Step 6: Create a Short URL

Open Create short URL in the web client, paste the long URL you want to shorten into URL to be shortened, optionally set a title, custom slug, tags or access limits, and select Save. The web client returns the generated short URL, which you can copy with one click.

The Shlink web client create short URL form with fields for the long URL, custom slug, tags and access limits

You can also create a short URL directly through the REST API with the key from step 3. The following command reads the key from the credentials file and creates a short URL for https://www.cloudimg.co.uk:

SHLINK_KEY=$(sudo grep '^shlink.api.key=' /root/shlink-credentials.txt | cut -d= -f2-)
curl -s -X POST -H "X-Api-Key: ${SHLINK_KEY}" -H 'Content-Type: application/json' \
  -d '{"longUrl":"https://www.cloudimg.co.uk","findIfExists":true}' \
  http://127.0.0.1/rest/v3/short-urls

The response is a JSON document describing the new short URL, including its shortCode and full shortUrl.

Step 7: List and Protect the REST API

The same key authenticates read requests. List all short URLs:

SHLINK_KEY=$(sudo grep '^shlink.api.key=' /root/shlink-credentials.txt | cut -d= -f2-)
curl -s -H "X-Api-Key: ${SHLINK_KEY}" http://127.0.0.1/rest/v3/short-urls

Requests without a valid key are rejected. The following request omits the header and returns HTTP 401, confirming the API is protected:

curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1/rest/v3/short-urls

Step 8: Read Visit Analytics

Every time a short URL is followed, Shlink records a visit. In the web client, select the visit count beside any short URL to open its analytics, which break visits down by time, by context (browser, operating system, referrer) and by location.

The Shlink visit analytics view for a short URL, showing the total visits and a visits over time chart

Visit geolocation is resolved by a systemd timer, shlink-visits.timer, which runs every fifteen minutes. Inspect its status with:

systemctl status shlink-visits.timer --no-pager

Geolocation requires a free MaxMind GeoLite2 license key. Without one, visits are still recorded and analysed by time and context; only the location breakdown is unavailable. To enable location resolution, obtain a license key from MaxMind, add 'GEOLITE_LICENSE_KEY' => '<your-key>', to the array in /opt/shlink/config/params/generated_config.php, and run sudo -u www-data php8.4 /opt/shlink/bin/cli visit:download-db.

Step 9: Manage API Keys

Shlink supports multiple API keys with different roles. List the keys on the VM:

sudo -u www-data php8.4 /opt/shlink/bin/cli api-key:list

To generate an additional key, for example for a separate application, use the api-key:generate command. Run it interactively from your SSH session and record the key it prints, because Shlink only shows the full key once at creation:

sudo -u www-data php8.4 /opt/shlink/bin/cli api-key:generate --name=my-application

Step 10: Use a Custom Short Domain

By default short URLs use the VM's address. To serve short links on your own domain, point a DNS record at the VM, then edit /opt/shlink/config/params/generated_config.php and set 'DEFAULT_DOMAIN' to your domain and 'IS_HTTPS_ENABLED' to true once you have TLS in place. Restart the service afterwards with sudo systemctl restart php8.4-fpm nginx.

Step 11: Enable HTTPS

For production use, terminate TLS in front of Shlink. The simplest approach on a single VM is Let's Encrypt with Certbot. Because Certbot prompts interactively for an email address and agreement to the terms of service, run it directly in your SSH session rather than from a script:

sudo apt-get install -y certbot python3-certbot-nginx

sudo certbot --nginx -d your-domain.example.com

Certbot edits the nginx configuration to serve HTTPS and installs a renewal timer. After it completes, set 'IS_HTTPS_ENABLED' => true in the configuration file and reload nginx with sudo systemctl reload nginx.

Step 12: Where Your Data Lives and How to Back It Up

All Shlink data lives in the SQLite database on the dedicated Azure data disk at /opt/shlink-data/data/database.sqlite. The disk is captured into the image and re provisioned on every VM, so the data tier stays independent of the operating system disk.

The dedicated ext4 Azure data disk mounted at /opt/shlink-data, holding the SQLite database, with its fstab entry keyed by UUID

Back up the database with a consistent copy:

sudo sqlite3 /opt/shlink-data/data/database.sqlite ".backup '/tmp/shlink-backup.sqlite'"

For a complete point in time backup of the data tier, create an Azure managed disk snapshot of the data disk from the Azure portal or the Azure CLI. To restore, stop the web tier, replace the database file, and start the web tier again.

Step 13: Service Management

The Shlink stack is managed by systemd. The web tier is php8.4-fpm.service and nginx.service; visit processing is shlink-visits.timer. Check their state with:

systemctl is-active nginx.service php8.4-fpm.service

To restart the web tier after a configuration change:

sudo systemctl restart php8.4-fpm nginx

Support

This image is supported by cloudimg. For assistance with deployment, custom domains, REST API integration, analytics, or database administration, contact cloudimg support 24 hours a day, 7 days a week by email and chat.

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.