Pl
Storage Azure

Plik on Ubuntu 24.04 on Azure User Guide

| Product: Plik on Ubuntu 24.04 LTS on Azure

Overview

Plik is a scalable, open source, self hosted temporary file upload and sharing service. Users upload one or more files through a clean web interface or an HTTP API, choose how long they should live, and receive short shareable links that expire automatically. One shot links that self destruct after a single download, password protected uploads, streaming uploads that are never written to disk, and markdown comments make it a flexible replacement for emailing large attachments or standing up ad hoc file drops.

The cloudimg image installs the official prebuilt Plik server at /opt/plik/plikd, running as the plik service bound to loopback 127.0.0.1:8080, behind nginx which terminates TLS on port 443. The metadata database and the uploaded files live on a dedicated data disk, so the appliance is production ready within minutes of launch with no package installation and no proxy configuration.

Secure by default, no anonymous uploads: Plik ships wide open by default, accepting anonymous uploads from anyone. This image never does that. Authentication is forced, so every upload requires a valid account or API token, and open self registration is disabled. A plik-firstboot.service oneshot creates a unique administrator account and API token on each VM's first boot, writes them to a root only file, regenerates a per VM TLS certificate, and then disables itself. The plik service requires the first boot unit, so it can never serve before the per VM credentials exist. No two VMs share credentials and none is baked into the image.

Dedicated data disk: the SQLite metadata database (plik.db) and the file store (files/) live on a dedicated data disk mounted at /var/lib/plik, captured into the image so every VM is provisioned with it. The server binary and web frontend stay on the OS disk.

What is included:

  • Plik 1.4.2, the official prebuilt server binary and bundled web frontend
  • The full Plik web UI, served over TLS: upload, set an expiry, get shareable links
  • plik.service bound to loopback 127.0.0.1:8080
  • nginx terminating TLS on 443, with 80 redirecting to HTTPS and an unauthenticated /healthz probe
  • plik-firstboot.service for the first boot admin account, API token, per VM TLS certificate and info note
  • Forced authentication with anonymous uploads disabled and self registration turned off
  • A dedicated data disk mounted at /var/lib/plik for the metadata database and file store
  • Ubuntu 24.04 LTS base, fully patched
  • 24/7 cloudimg support, 24h response SLA

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet with a subnet. Recommended VM size: Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and light sharing, or a Standard_D2s_v5 or larger for busier workloads. The dedicated data disk holds your uploads, so resize it to suit how much you expect to store at once (the default maximum time to live is 30 days).

Step 1: Deploy from the Azure Portal

Search the Marketplace for Plik on Ubuntu 24.04, choose your VM size, and attach an NSG that allows TCP 22 (SSH) from your management network and TCP 443 (the web UI and API) from the networks and users that need to share files. Port 80 only issues an HTTPS redirect.

Step 2: Deploy from the Azure CLI

RG="plik-prod"; LOCATION="eastus"; VM_NAME="plik-01"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/plik-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create -g "$RG" --name plik-vnet --address-prefix 10.90.0.0/16 --subnet-name plik-subnet --subnet-prefix 10.90.1.0/24
az network nsg create -g "$RG" --name plik-nsg
az network nsg rule create -g "$RG" --nsg-name plik-nsg --name allow-ssh --priority 100 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp
az network nsg rule create -g "$RG" --nsg-name plik-nsg --name allow-https --priority 110 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 443 --access Allow --protocol Tcp
az vm create -g "$RG" --name "$VM_NAME" --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2s --storage-sku StandardSSD_LRS \
  --admin-username azureuser --ssh-key-values "$SSH_KEY" \
  --vnet-name plik-vnet --subnet plik-subnet --nsg plik-nsg --public-ip-sku Standard

Step 3: Connect via SSH

ssh azureuser@<vm-ip>

Step 4: Verify the services are running

Plik listens on loopback 127.0.0.1:8080; nginx fronts it with TLS on port 443. The /healthz endpoint is public for load balancer probes; the web UI and API require your per VM credentials.

sudo systemctl is-active plik nginx plik-firstboot
ss -tln | grep -E '127.0.0.1:8080|:443 '
curl -ks -o /dev/null -w 'healthz HTTP %{http_code}\n' https://127.0.0.1/healthz
cat /opt/plik/VERSION

You should see the services active, plikd listening on loopback with nginx on 443, healthz HTTP 200, and the installed Plik version.

Terminal showing the plik, nginx and plik-firstboot services active, plikd bound to loopback 127.0.0.1:8080 with nginx on ports 80 and 443, and the installed Plik 1.4.2 version

The web UI is served over TLS at https://<your-vm-ip>/. Because the certificate is self signed per VM, your browser will warn on first visit; accept the exception (or trust /etc/nginx/tls/plik.crt) to reach it. Because authentication is forced, you are met with a sign in screen rather than an open upload form.

The Plik web UI sign in screen served over TLS, prompting for a login and password because anonymous uploads are disabled

Step 5: Read your per VM credentials and confirm auth is enforced

The administrator account and API token were generated on this VM's first boot and stored in a root only file. Read them and keep them secret. Then confirm that an unauthenticated upload is rejected while the per VM token is accepted.

sudo cat /root/plik-info.txt
echo "anonymous   -> HTTP $(curl -ks -o /dev/null -w '%{http_code}' -X POST https://127.0.0.1/upload -d '{}')"
echo "wrong token -> HTTP $(curl -ks -o /dev/null -w '%{http_code}' -X POST -H 'X-PlikToken: wrong' https://127.0.0.1/upload -d '{}')"
PLIK_TOKEN=$(sudo grep '^PLIK_API_TOKEN=' /root/plik-info.txt | cut -d= -f2-)
echo "per-VM tok  -> HTTP $(curl -ks -o /dev/null -w '%{http_code}' -X POST -H "X-PlikToken: $PLIK_TOKEN" -H 'Content-Type: application/json' https://127.0.0.1/upload -d '{}')"

The info note holds PLIK_ADMIN_LOGIN, PLIK_ADMIN_PASSWORD and PLIK_API_TOKEN, owned root:root with mode 0600. An anonymous upload returns 400 anonymous uploads are disabled, a wrong token returns 403 invalid token, and only your per VM token returns 200.

Terminal showing the per VM credentials with the password and token masked, then an anonymous upload rejected with HTTP 400 anonymous uploads are disabled, a wrong token rejected with 403, and the per VM token accepted with 200

Step 6: Upload and share a file from the API

Load your token into a shell variable, create an upload, add a file, and Plik returns a shareable link and gives you the file back on download. Use the X-PlikToken header to authenticate every request.

PLIK_TOKEN=$(sudo grep '^PLIK_API_TOKEN=' /root/plik-info.txt | cut -d= -f2-)
printf 'Q3 revenue report - cloudimg demo\n' > /tmp/report.txt
UPID=$(curl -ks -X POST -H "X-PlikToken: $PLIK_TOKEN" -H 'Content-Type: application/json' https://127.0.0.1/upload -d '{}' | jq -r '.id')
FILE=$(curl -ks -X POST -H "X-PlikToken: $PLIK_TOKEN" -F "file=@/tmp/report.txt" https://127.0.0.1/file/$UPID)
FID=$(echo "$FILE" | jq -r '.id'); FNAME=$(echo "$FILE" | jq -r '.fileName')
echo "share link: https://<your-vm-ip>/#/?id=$UPID"
curl -ks -H "X-PlikToken: $PLIK_TOKEN" https://127.0.0.1/file/$UPID/$FID/$FNAME

The upload is created, the file uploads over TLS with status uploaded, you get a share link that expires with the upload, and downloading it returns the original content byte for byte.

Terminal showing an API round trip over TLS: create an upload, add report.txt which reports status uploaded, print the share link, and download the file back returning the original Q3 revenue report contents

Step 7: Upload and share from the web UI

Sign in at https://<your-vm-ip>/ with the PLIK_ADMIN_LOGIN and PLIK_ADMIN_PASSWORD from your info note. Drag a file onto the upload area (or click to select), choose an expiry and any options such as one shot or password protection, then click Upload.

The Plik upload page after signing in, showing the drop area with a file selected, the upload settings for destruct after download, streaming, removable, end to end encryption, password and comment, and a 30 day expiry

Plik returns a shareable link and an admin link for the upload, along with a QR code, a zip archive of all files, and a preview of each file. Share the link with anyone who needs the file; it stops working when the upload expires.

The Plik share view for an uploaded file, showing the upload expiry, the share URL and admin URL, a QR code and zip archive actions, and the file with view and download buttons

Step 8: One shot and expiring links

Set "oneShot": true when creating an upload so the file self destructs after a single download, ideal for sending a secret or a one time file. Combine it with a short time to live for links that expire quickly.

PLIK_TOKEN=$(sudo grep '^PLIK_API_TOKEN=' /root/plik-info.txt | cut -d= -f2-)
printf 'one time secret - cloudimg demo\n' > /tmp/secret.txt
UPID=$(curl -ks -X POST -H "X-PlikToken: $PLIK_TOKEN" -H 'Content-Type: application/json' https://127.0.0.1/upload -d '{"oneShot":true,"ttl":3600}' | jq -r '.id')
FILE=$(curl -ks -X POST -H "X-PlikToken: $PLIK_TOKEN" -F "file=@/tmp/secret.txt" https://127.0.0.1/file/$UPID)
echo "one shot upload $UPID created, expires in 1 hour, file self destructs after the first download"
echo "$FILE" | jq -r '"file: \(.fileName)  status: \(.status)"'

The default and maximum time to live are 30 days; the appliance also supports password protected and removable uploads through the same API and the web UI.

Step 9: Manage the server from the admin panel

Your account is an administrator, so the Admin menu opens a dashboard showing the server configuration and live statistics, and lets you manage users and uploads. The statistics confirm that anonymous uploads stay at zero because authentication is forced.

The Plik admin panel showing the server version 1.4.2 and configuration with a 10 GB max file size and 30 day default and maximum TTL, plus server statistics including zero anonymous uploads

Step 10: Persistence and the data disk

The metadata database and the uploaded files live on the dedicated data disk mounted at /var/lib/plik, so uploads survive reboots and the disk is captured into the image. You can confirm the mount and that authentication is forced.

findmnt -no SOURCE,TARGET,FSTYPE /var/lib/plik
df -h /var/lib/plik | tail -1
sudo ls /var/lib/plik
curl -ks https://127.0.0.1/config | jq '{feature_authentication, maxFileSize, defaultTTL}'

The data disk is ext4 mounted at /var/lib/plik, holding plik.db (the SQLite metadata database) and the files store, and /config reports feature_authentication: forced.

Terminal showing the ext4 data disk mounted at /var/lib/plik with the plik.db metadata database and files store on it, and the config endpoint reporting feature_authentication forced with a 10 GB max file size

Step 11: Enable a real TLS certificate

The appliance ships with a self signed certificate generated per VM. For production, point a DNS record at the VM and replace it with a CA signed certificate. With certbot you can obtain one and drop it into the nginx TLS paths.

sudo apt-get update && sudo apt-get install -y certbot
sudo certbot certonly --standalone -d your-domain.example.com
sudo cp /etc/letsencrypt/live/your-domain.example.com/fullchain.pem /etc/nginx/tls/plik.crt
sudo cp /etc/letsencrypt/live/your-domain.example.com/privkey.pem  /etc/nginx/tls/plik.key
sudo systemctl reload nginx

Clients can then verify the certificate normally instead of using -k.

First boot, credentials and updates

The first boot service creates the per VM administrator account and API token, regenerates the per VM TLS certificate, resolves the instance URL and writes the root only info note at /root/plik-info.txt, then disables itself so subsequent reboots are unaffected. To rotate the API token, run sudo /opt/plik/plikd --config /etc/plik/plikd.cfg token create --login admin and store the new token. The OS ships fully patched with unattended security upgrades enabled.

Support

Every cloudimg deployment includes 24/7 support with a 24 hour response SLA. Contact support@cloudimg.co.uk for help with deployment, configuration or scaling.

This is a repackaged open source software product with additional charges for cloudimg support services. Plik is a trademark of its respective owner. 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.