Deployment guide

restic Rest Server

Overview

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 in your own Azure subscription. Point any restic client at it over HTTPS to read and write backup repositories, just as you would against any restic remote.

Rest Server 0.14.0 runs as a single static binary under systemd as an unprivileged restic user. It is a headless service with no web interface, so you operate it with the restic client from the machines you back up.

What you get:

  • 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 an nginx reverse proxy with a self-signed certificate generated per virtual machine on first boot. Rest Server itself binds to loopback only.
  • Repository data stored on a dedicated data disk mounted at /var/lib/restic
  • No anonymous access. Rest Server can be run with --no-auth, which serves an open repository server. This image never does. It runs with --htpasswd-file and --private-repos, so every request needs HTTP Basic authentication against a bcrypt htpasswd file, and each user is confined to their own repository namespace.
  • A unique username and password generated on the first boot of every VM, written to the htpasswd file and recorded in /root/rest-server-info.txt (mode 0600, root only). No two instances share a credential.
  • Credentials 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
  • A service that refuses to start until a credential is present, so an unauthenticated or wrong-password request is rejected with HTTP 401

Prerequisites

  • An active Azure subscription, an SSH public key, and a VNet with a subnet in the target region
  • A subscription to the Rest Server listing on Azure Marketplace
  • Network security group rules that allow TCP 22 (admin) and TCP 443 (the HTTPS REST endpoint) from the client networks that back up to the server. Port 80 answers with a redirect to HTTPS and serves 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, and 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. For higher throughput or capacity, choose a larger size or attach a larger data disk.

1

Deploy from the Azure Portal

Launch the image from the Azure Marketplace listing. Choose 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.

To deploy with the Azure CLI instead, run:

RG="rest-server-prod"; LOCATION="eastus"; VM_NAME="rest-server1" IMAGE_URN="sac1647283583153:restic-rest-server-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:restic-rest-server-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --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
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 the file:

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

The file contains 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 are not part of the image. Keep the file secret.

3

Verify the service is running

Confirm that the services are active and check the network listeners. Rest Server binds to loopback (127.0.0.1:8000), and 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'
4

Back up and restore with restic

The restic client talks to this server over HTTPS. The endpoint is an IP address with a self-signed certificate, so use --insecure-tls or trust the certificate (see below).

The following block runs a quick self-test on the VM. It installs a restic client, reads the VM's own credentials, and runs a full round trip against the local endpoint: initialise a repository, back up a file, list the snapshot, then restore the file 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 sac" > /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_PASSWORD above is the repository encryption password that you choose. It encrypts the backup data and is separate from the REST_SERVER_PASSWORD that authenticates you to the server. Keep both safe, because backups cannot be decrypted without the repository password.

5

Authentication is enforced

There is no anonymous access. A request with no credentials, and a request with the wrong password, are both rejected with HTTP 401. Run the following to see it:

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/
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. Confirm all three:

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

Connecting from a remote client

On 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 in which the first path element is your username, because 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). Replace <your-username> and <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 generated per virtual machine on first boot. Its subject alternative names include the VM public IP, the hostname and 127.0.0.1. For quick testing, pass --insecure-tls.

For production, choose one of two options. 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 a user or change a password with htpasswd, update /root/rest-server-info.txt to match, 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. Because the server runs with --private-repos, that user can access only repositories under their own namespace.

Hardening: append only repositories

For ransomware-resistant backups, run the server in append-only mode. Clients can then create and read snapshots, but they 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. An administrator with direct disk access must then prune repositories out of band.

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 public CA 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 SecureAnyCloud deployment includes 24/7 support. Contact the SecureAnyCloud team for help with configuration, retention policies, scaling or integration.

Deploy on Azure

Launch Rest Server 0.14.0 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