Rs
Storage Azure

Rest Server on Ubuntu 24.04 on Azure User Guide

| Product: Rest Server 0.14.0 on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of Rest Server on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Rest Server is an open source, high performance HTTP server that implements restic's REST backend protocol. This image turns a virtual machine and its dedicated data disk into a self hosted backup repository server: point any restic client at it over HTTPS and read and write backup repositories exactly as you would against any restic remote, entirely within your own subscription.

The image installs Rest Server 0.14.0 from the official release as a single static binary, run under systemd as an unprivileged restic user. The server binds to loopback only and is exposed through an nginx reverse proxy that terminates TLS on port 443, so the REST endpoint is reachable securely over HTTPS. It is a headless service: there is no web interface, so you operate it with the restic client from the machines you back up.

Secure by default — HTTP Basic auth required, no default credentials. Rest Server can be run with --no-auth, which serves an open, anonymous repository server. This image closes that gap: it runs with --htpasswd-file and --private-repos, so every request must be HTTP Basic authenticated against a bcrypt htpasswd file, and each user is confined to their own repository namespace. On the very first boot of every VM it generates a unique username and password, writes them into the htpasswd file and records them in /root/rest-server-info.txt (mode 0600, root only), and the service is configured to refuse to start until a credential is present. As a result an unauthenticated or wrong password request is rejected with HTTP 401, and no two instances share a credential.

What is included:

  • Rest Server 0.14.0 from the official release, run under systemd as the unprivileged restic user (rest-server.service)

  • An HTTPS REST endpoint on port 443, terminated by nginx with a self signed certificate generated per virtual machine on first boot

  • Repository data stored on a dedicated data disk mounted at /var/lib/restic

  • A unique username and password generated on first boot and documented in /root/rest-server-info.txt (0600), with --htpasswd-file and --private-repos so every request is authenticated and confined to its own namespace

Prerequisites

  • Active Azure subscription, SSH public key, VNet + subnet in target region

  • Subscription to the Rest Server listing on Azure Marketplace

  • Network Security Group rules allowing TCP 22 (admin) and TCP 443 (the HTTPS REST endpoint) from the client networks that will back up to the server. Port 80 answers a redirect to HTTPS and an unauthenticated /healthz load balancer probe

  • The restic client installed on the machines you want to back up (from https://restic.net or your OS package manager). Rest Server is the destination; restic is the client that talks to it

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for development and small production workloads. Scale to a larger size, or attach a larger data disk, for higher throughput or capacity.

Step 1: Deploy from the Azure Portal

Launch the image from the Azure Marketplace listing, choosing your resource group, region, size (Standard_B2s or larger) and SSH key. Attach the offer's data disk and open ports 22 and 443 in the Network Security Group. Equivalent Azure CLI:

RG="rest-server-prod"; LOCATION="eastus"; VM_NAME="rest-server1"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/restic-rest-server-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 443 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1002

Step 2: Retrieve your per-VM credentials

On first boot the VM generates a unique username and password and writes them to a root only file. SSH in as azureuser and read them:

sudo cat /root/rest-server-info.txt

You will see REST_SERVER_USER, REST_SERVER_PASSWORD, REST_SERVER_URL (the HTTPS endpoint using this VM's public IP) and REST_SERVER_REPO (a ready to use restic repository string). These credentials are unique to this VM and were not baked into the image. Keep this file secret.

Step 3: Verify the service is running

Confirm the server and the network listeners. Rest Server binds to loopback (127.0.0.1:8000); nginx binds the public HTTPS endpoint on 0.0.0.0:443:

sudo systemctl start rest-server.service nginx.service
systemctl is-active rest-server.service nginx.service
/opt/rest-server/rest-server --version
ss -tlnH | grep -E ':8000|:443'

rest-server.service and nginx.service both report active, rest-server prints its 0.14.0 version, and ss shows rest-server listening on loopback 127.0.0.1 port 8000 while nginx listens on 0.0.0.0 port 443

Step 4: Back up and restore with restic

The restic client talks to this server over HTTPS. Because the endpoint is an IP address with a self signed certificate, use --insecure-tls (or trust the certificate, see below). The following block installs a restic client on the VM for a quick self test, reads this VM's own credentials, then runs a full round trip against the local endpoint: initialise a repository, back up a file, list the snapshot, then restore it and print its contents.

curl -fsSL -o /tmp/restic.bz2 https://github.com/restic/restic/releases/download/v0.18.0/restic_0.18.0_linux_amd64.bz2
bunzip2 -f /tmp/restic.bz2 && chmod +x /tmp/restic
U=$(sudo grep '^REST_SERVER_USER=' /root/rest-server-info.txt | cut -d= -f2-)
P=$(sudo grep '^REST_SERVER_PASSWORD=' /root/rest-server-info.txt | cut -d= -f2-)
export RESTIC_REPOSITORY="rest:https://$U:$P@127.0.0.1/restic/demo"
export RESTIC_PASSWORD="choose-a-strong-repository-encryption-password"
echo "hello from cloudimg" > /tmp/demo.txt
/tmp/restic --insecure-tls init
/tmp/restic --insecure-tls backup /tmp/demo.txt
/tmp/restic --insecure-tls snapshots
/tmp/restic --insecure-tls restore latest --target /tmp/restored
cat /tmp/restored/tmp/demo.txt

the restic client initialises a repository at rest https 127.0.0.1 restic demo, backs up demo.txt, lists one snapshot, then restores it and prints hello from cloudimg, all over the appliance HTTPS endpoint with the per VM username and password

The RESTIC_PASSWORD above is the repository encryption password you choose; it encrypts the backup data and is separate from the REST_SERVER_PASSWORD that authenticates you to the server. Keep both safe: without the repository password your backups cannot be decrypted.

Step 5: Authentication is enforced

There is no anonymous access. A request with no credentials is rejected with HTTP 401, and a request with the wrong password is also rejected with HTTP 401:

curl -ks -o /dev/null -w 'no credentials:   HTTP %{http_code}\n' https://127.0.0.1/restic/
U=$(sudo grep '^REST_SERVER_USER=' /root/rest-server-info.txt | cut -d= -f2-)
curl -ks -o /dev/null -w 'wrong password:   HTTP %{http_code}\n' -u "$U:wrong-password" https://127.0.0.1/restic/
curl -ks -o /dev/null -w 'correct password: HTTP %{http_code}\n' \
  -u "$U:$(sudo grep '^REST_SERVER_PASSWORD=' /root/rest-server-info.txt | cut -d= -f2-)" https://127.0.0.1/restic/

an unauthenticated curl request to the endpoint returns HTTP 401, a request with a wrong password returns HTTP 401, and a request with the correct per VM password returns HTTP 200, proving only authenticated requests are authorised

Step 6: Security posture and where your data lives

The credentials file is root only (0600), the server runs with --htpasswd-file and --private-repos, and repository data lives on the dedicated data disk mounted at /var/lib/restic:

sudo stat -c '%n %a %U:%G' /root/rest-server-info.txt
systemctl show rest-server.service -p ExecStart --value | grep -o -- '--htpasswd-file[^ ]* --private-repos'
df -h /var/lib/restic | tail -1

the credentials file is 0600 root root, the service command line shows the htpasswd file and private repos flags, and df shows the repository data directory mounted on the dedicated 30 GB data disk at /var/lib/restic

Connecting from a remote client

From a machine you want to back up, install the restic client and point it at this VM's public endpoint with your username and password. Use path style URLs where the first path element is your username (private repositories confine each user to their own namespace):

export RESTIC_REPOSITORY='rest:https://<your-username>:<your-password>@<vm-ip>/restic/laptop'
export RESTIC_PASSWORD='choose-a-strong-repository-encryption-password'
restic --insecure-tls init
restic --insecure-tls backup ~/Documents
restic --insecure-tls snapshots

Replace <vm-ip> with the VM public IP (see REST_SERVER_URL in /root/rest-server-info.txt), and <your-username> / <your-password> with the values from that file. You can create as many named repositories under your namespace as you like, for example .../restic/laptop and .../restic/server1.

Using the TLS certificate

The certificate is self signed and regenerated per virtual machine on first boot, with the VM public IP, hostname and 127.0.0.1 in its subject alternative names. For quick testing pass --insecure-tls. For production, either distribute the certificate at /etc/nginx/tls/rest-server.crt to your clients as a trusted CA (then drop --insecure-tls), or place the appliance behind a load balancer or reverse proxy with a certificate issued by a public CA for your own domain, and point clients at that hostname.

Adding users and rotating passwords

Credentials live in the bcrypt htpasswd file /etc/rest-server/.htpasswd. Add another user, or change a password, with htpasswd, then keep /root/rest-server-info.txt in step and restart the service. This example rotates the restic user's password to a value you supply:

sudo htpasswd -B /etc/rest-server/.htpasswd restic <new-password>
sudo sed -i "s|^REST_SERVER_PASSWORD=.*|REST_SERVER_PASSWORD=<new-password>|" /root/rest-server-info.txt
sudo systemctl restart rest-server.service
echo "password rotated"

To add a second user, run sudo htpasswd -B /etc/rest-server/.htpasswd <new-username> and restart the service. With --private-repos, that user can only access repositories under their own namespace.

Hardening: append only repositories

For ransomware resistant backups you can run the server in append only mode, where clients can create and read snapshots but cannot delete or overwrite existing data. Add --append-only to the ExecStart line in /etc/systemd/system/rest-server.service (via sudo systemctl edit --full rest-server.service) and restart the service. Pruning then has to be performed out of band by an administrator with direct disk access.

Managing the service

systemctl status rest-server.service nginx.service --no-pager
sudo journalctl -u rest-server.service -n 50 --no-pager

The server restarts automatically on failure and starts on boot. Repository data persists on the data disk across restarts and reboots.

Troubleshooting

  • restic reports 401 Unauthorized: confirm the client is using the exact username and password from /root/rest-server-info.txt, and that the first path element of the repository URL matches your username.

  • restic reports a certificate error: the certificate is self signed. Trust /etc/nginx/tls/rest-server.crt, use --insecure-tls for testing, or front the appliance with a real certificate as described above.

  • A client cannot connect: confirm the Network Security Group allows TCP 443 from the client network, and that systemctl is-active rest-server.service nginx.service reports active.

Support

Every cloudimg deployment includes 24/7 support. Contact the cloudimg team for help with configuration, retention policies, scaling or integration.