Deployment guide

Shlink

Overview

Shlink is a self-hosted URL shortener that gives you complete ownership of your short links, their data and their analytics. This SecureAnyCloud image runs Shlink 5.1.0 behind nginx with PHP 8.4 FPM on a hardened Ubuntu 24.04 LTS base, patched at build time.

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. The web client's server entry is wired to the key automatically.

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

What you get:

  • 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 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. The Azure CLI is required only if you deploy from the command line.

Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point. Size up for higher redirect volumes.

Configure these network security group inbound rules: allow 22/tcp from your management network, and allow 80/tcp (and 443/tcp once you add TLS) from the networks that will use your short links.

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 SecureAnyCloud. 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, set 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. Select Review + create. First-boot initialisation completes about a minute after the VM reaches the Running state.

2

Launch from the Azure CLI

This command creates a VM from the SecureAnyCloud Shlink image. Replace the angle-bracket values with your own. The image reference is shown on the Marketplace offer page.

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:shlink-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-resource-group> \
  --name shlink-01 \
  --image sac1647283583153:shlink-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values <path-to-your-public-key> \
  --public-ip-sku Standard \
  --nsg-rule SSH

When 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.

3

Connect and Retrieve the API Key

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

ssh azureuser@<public-ip>

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:

4

Confirm the Service Is Healthy

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

systemctl is-active nginx php8.4-fpm
curl -s http://127.0.0.1/rest/health

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

5

Open the Shlink Web Client

Browse to http://<public-ip>/ in a web browser. The Shlink web client loads and connects to this VM automatically using the generated API key, so no manual server setup 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 List short URLs page lists every short URL with its destination, tags and visit count, and provides search and filtering.

6

Create a Short URL

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

You can also create a short URL directly through the REST API with the key from Step 3. This command reads the key from the credentials file and creates a short URL for https://secureanycloud.com:

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://secureanycloud.com","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.

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. This request omits the header and returns HTTP 401, which confirms that the API is protected:

curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1/rest/v3/short-urls
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.

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

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, and 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.

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. Shlink shows the full key only once, at creation:

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

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. Set 'DEFAULT_DOMAIN' to your domain, and set 'IS_HTTPS_ENABLED' to true once you have TLS in place. Restart the service afterwards with sudo systemctl restart php8.4-fpm nginx.

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. Certbot prompts interactively for an email address and agreement to the terms of service, so 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.

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.

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.

13

Service Management

systemd manages the Shlink stack. The web tier is php8.4-fpm.service and nginx.service, and visit processing is shlink-visits.timer. Check their state:

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

SecureAnyCloud supports this image. For help with deployment, custom domains, REST API integration, analytics or database administration, contact SecureAnyCloud 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.

Deploy on Azure

Launch Shlink 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

Deploy on Azure