Rest-server repositories for some 1000 clients?

I am an admin at the computing centre of my university.

I have set up an Ubuntu server with rest-server 0.14.0 and created some
restic repositories for our internal hosts.

So far, everything works fine :slight_smile:

But now, we want to offer restic as a service for about 50 institutes with
some 1000 hosts.
Adding so many repositories does not scale, way too much manual effort.

My first idea was one repository for each institute. The institute admins
then can use restic backup with host specific tags.
But I forget that restic uses locking and one cannot run more than one
restic backup at the same time (cronjobs!).

Using NFS instead of rest-server is not an option, because of
router-firewalls. We can offer restic only via https.

Is there another solution?

What about s3? I didn’t see an issue with minio for a long time, with ~8k clients. Although you might want to use a fork of it and apply some IAM policies / a bucket per institute etc. depending on your need.

Is this a rest-server limitation that I don’t know about? Parallel backups should be fine since backing up uses non-exclusive locks, no? What you cannot do is backing up while pruning/forgetting/checking (the operations which use exclusive locks).

My restic server does not offer S3, only rest-server via https.

We have an S3 server (Netapp StorageGrid), but with limited space, not enough for backup and it’s a too expensive storage.

The clients indeed do pruning/forgetting/checking.

@Framsfex I believe that on the server machine running your HTTPs rest-server you could try a self-hosted S3 compatible solution like GitHub - seaweedfs/seaweedfs: SeaweedFS is a distributed storage system for object storage (S3), file systems, and Iceberg tables, designed to handle billions of files with O(1) disk access and effortless horizontal scaling. · GitHub .

And by design you cannot do prune, forget and check without locking because of the exclusive locks like @gurkan mentioned above.

IMO (disregard if you have already considered this); you must do one repository per host by scripting some methodology to derive the repository path name based on a combination of institute identifiers and hostname identifiers (these can be probably handled by your institute admins). Also, the scripting can take Configuration file :: resticprofile templates and generate the configurations for you to manage at scale. Something like ansible will help you push these profiles to all the hosts.

seaweedfs as external addon software has the same problem like minio: some day the support will be terminated and I have to remove it.

As I wrote: we have 50 institutes with together about 30000 hosts.

With rest-server I must create an account for each of these hosts.

I even do not know the host names and I do not have access to them. Each institute administrates their hosts autarchic. Using ansible or something similar is not possible.

I think the hard part is less the number of repositories and more who is allowed to create/use them. If the institutes manage the hosts themselves, I would probably make the institute boundary explicit: one auth namespace/account per institute, and let them provision repo names inside their own path, with a written rule that prune/check jobs are scheduled by them and not mixed with backup windows. Backups can run in parallel; the exclusive lock problem is mainly prune/check/forget.

If you cannot delegate repo creation at all, then some provisioning API or wrapper around rest-server auth becomes unavoidable, because otherwise you are stuck maintaining 30000 identities by hand.

If you want a lock-free restic, have a look at rustic (disclaimer: I’m the maintainer).

You could also write your own or extend an existing REST-server to allow creation/deletion of accounts by service. But I must admit in that case you could also use an existing S3-providing solution which offers similar functionalities.

Note that there are more pro/cons to take into account when thinking about 1 large repo for many clients vs. many repos:

  • a repository has a single encryption key, i.e. all data is accessible by every client
  • deduplication is across the repo, i.e. better deduplication for a single repo
  • memory usage for the clients scales with the total data in the repository. If the repository gets really large, this could pose problems

How can a rest-user do this?

Example for my own hosts, rs1 is the server running rest-server, fex is a client running restic:

root@fex:~/.restic# cat rs1.env
RESTIC_REST_USERNAME=root@fex
RESTIC_REST_PASSWORD=xxxxxxxx
RESTIC_REPOSITORY=rest:https://rs1.tik.uni-stuttgart.de:8000/$RESTIC_REST_USERNAME

On rs1 I have:

root@rs1:/home/restic/data/root@fex# ll
drwx------ restic backup   - 2024-06-12 09:09:51 data
drwx------ restic backup   - 2026-06-14 00:16:41 index
drwx------ restic backup   - 2024-06-12 09:09:53 keys
drwx------ restic backup   - 2026-06-14 00:16:57 locks
drwx------ restic backup   - 2026-06-14 00:16:41 snapshots
-rw------- restic backup 155 2024-06-12 09:09:53 config

“it is not recommended to use it for production backups”

“Windows support still being experimental”

Sorry, but this is not an option for us.

You could also write your own or extend an existing REST-server to allow creation/deletion of accounts

This is way over my knowledge…

I do not know go language, sorry.

Using a S3 server is also not possible: too expensive or not available in the Ubuntu software repository.

The solution for my problem is MUCH easier, than I thought:

Every rest-server user (in my case: institute’s admin) can create subdirectory repositories - out of the box!

https://github.com/restic/rest-server

“Users can also create their own subrepositories, like /foo/bar"

I testet it with:

RESTIC_REPOSITORY=rest:$REST_SERVER/$RESTIC_REST_USERNAME/test restic init

works like a charm :slight_smile:

Everyone here is talking about the REST server, but what about Rclone? See restic · Using rclone as a restic Backend . This is what we have in the BackUpScale architecture.

Disclosure first: I run a managed rest-server service, so “autonomous tenants I don’t control, HTTPS only, at scale” is basically my day job. No pitch, you’re building the same thing in-house, so here’s what actually works.

gurkan is right and it’s worth underlining: parallel backup is fine, those locks are non-exclusive. Only prune/forget/check take an exclusive lock. quietlotte is pointing at the real answer too: your management unit is the 50 institutes, not the 30,000 hosts. You should never need to know a hostname.

The mechanism is rest-server’s --private-repos. One htpasswd account per institute, and --private-repos confines each account to its own /<institute>/ path. Inside that namespace the institute runs restic init for as many repos as it wants, named however it wants, with zero involvement from you. So “30,000 unknown hosts I can’t reach” collapses to “50 accounts I create once.”

Do not do one shared repo per institute with tags. It looks simpler but has three traps: every host shares one encryption key so they can all read each other’s data, one host running prune locks out every other host, and one buggy or compromised host can damage the shared repo for everyone. Instead each host inits its own repo under the institute path, e.g. rest:``https://physics:pass@server/physics/``<hostname>. Now each host has its own key, its own lock, and prunes only its own repo, so the exclusive-lock problem you were worried about disappears entirely.

Two layers do two different jobs here, which is what makes it safe: the per-institute htpasswd credential gates HTTP access to that namespace, and the per-repo restic password (set by each host at init, which you never see) gates decryption. So even though hosts in one institute share a transport credential, host A still cannot decrypt host B’s repo. Access control is per-institute, confidentiality is per-host.

You also do not need minio, seaweedfs, or S3, and your instinct to avoid software that might lose support is sound. rest-server on your existing filesystem is enough. Your “provisioning API” is then about ten lines: to add an institute you append one htpasswd -B entry, make the directory, set a quota. It runs 50 times, not 30,000.

Three operational notes. Quotas: rest-server enforces none, so set a per-institute filesystem quota (XFS project quotas, or a ZFS dataset per institute) or one institute fills the disk for all 50. append-only: --append-only stops a compromised host from deleting history, but it also takes prune/forget away from the clients who currently run it themselves, so weigh that workflow change against your threat model rather than flipping it blindly. Proxy body size: if you terminate TLS with nginx in front of rest-server, set client_max_body_size 0 or large packs silently 413 and backups die after looking fine; if rest-server does its own --tls, ignore it.

Last thing, unsolicited: at 30,000 repos you cannot eyeball health, and a write landing is not a restore working. Whatever you build, script a periodic end-to-end restore of a canary and alert on it. That is the one check that tells you the service is doing its job.