Restow. Backup you can prove is restorable.
Self-hosted backup and archive for Microsoft 365 and IMAP, with endpoint backup for Linux and macOS. Restow backs up Exchange Online mail, calendars and contacts, OneDrive, any IMAP mailbox and your servers and clients to storage you control, and every week reads a sample of each backup back through the restore path and compares it with the recorded hashes. A backup only counts as restorable once it has been read back.
Status: beta (0.4.12). Run it alongside your existing backups, not as your only one, until you have verified restores against your own data. Microsoft 365 backup and restore have been tested against a simulated Graph API, never against a real Microsoft 365 tenant. What works and what does not yet is in CHANGELOG.md, especially its Known Issues.
Website · Documentation · Live demo · Changelog · Updating
- Backup of Exchange Online (mail, calendar, contacts) and OneDrive through Microsoft Graph, incremental via delta queries, and of any IMAP mailbox. Graph is the only Microsoft interface Restow uses; Exchange Web Services, which Microsoft switched off for Exchange Online on 1 October 2026, are not.
- Endpoint backup of servers and clients with the Restow agent and restic:
Linux and macOS agents (Windows is planned), installed root-owned and updated
only with releases the maintainer signed, append-only so an agent can add
backups but never delete or overwrite one, with retention decided by the
server and a storage budget per machine and per tenant. Hooks run only where
root on the machine allowed them. Restores go into a new folder, never over
existing files. A machine backs up only once it is in a backup job: the
inventory marks every machine without one ("Without backup") and offers to
create a job for it or add it to an existing one. Servers back up their
application data (
/opt,/usr/local,/var/lib,/var/backups) besides/etc,/homeand/srvby default, and every machine can be assigned to a person of the directory. Included in the Community edition. - Proxmox VE (preview): VMs and containers on Proxmox VE 8.4 and newer through the Backup Provider API. VM disks are read over NBD with dirty bitmaps, so after the first run only changed blocks are uploaded; containers go through restic. Restores create a new VM or container. See docs/PVE.md.
- File shares (SMB, NFS): Windows servers, Samba and NAS shares and NFS exports backed up from the server side, without an agent on the file server: a short-lived container mounts the share read-only for one run, restic writes into a repository of its own, NTFS permissions are kept and restored, and a restore goes to a ZIP, a new folder, the original location or another share. Scheduled copy jobs keep a folder of another share in step. Needs the mounter (on by default for new installations; docs/FILESHARES.md).
- Backup jobs: one job covers many mailboxes or machines with one schedule, one set of folders and one retention, with per-member overrides. "Run now" on machines shows the request as queued until the agent picks it up at its next check-in.
- Restore of a single mail, a folder, a file, a file version or a whole account, next to the original, never over it; or as a ZIP download. People with the role "user" restore only their own mailbox and OneDrive. File restore lists the machines with their restore points on one timeline by day and a jump to any date; mailboxes and OneDrive are restored in the restore explorer.
- Restore checks: every week a sample of every backup is read back through the restore path and compared with the recorded hashes; the result is shown per mailbox, OneDrive and machine as recovery readiness. The checks do not restore into a Microsoft 365 or IMAP target.
- Archive: Exchange Online journal mail (Business and Service Provider) and imported mail files go into an append-only store with a SHA-256 hash chain, chain verification and search over subject, extracted text and addresses (not attachments). Business adds enforced retention (fixed at 8 years in 0.3.0) and legal hold, designed for GoBD-compliant use (not certified). Continuous IMAP and Graph archive sync are not part of 0.3.0. On local and NFS targets the archive's immutability is enforced by the application only, and on S3 with Object Lock 0.3.0 locks the archive item records but not the packs that hold the message content; see Known Issues in the changelog.
- Import and export of mail files: bring a legacy mailbox in from EML, MSG, MBOX, ZIP or a MailStore export folder (chunked, resumable, encrypted upload or a server-side import folder), browse and restore it like any mailbox, and optionally archive it. Export backed-up, imported or archived mail as EML in a ZIP or as MBOX, with checksums and an expiring download link.
- Encryption: AES-256-GCM per chunk with a separate key per tenant, before
anything leaves the server. Deduplication stays within a tenant. One master key
(
RESTOW_MASTER_KEY) wraps every tenant key: whoever holds it and can read the storage can decrypt it, so keep it offline and apart from the storage. - Storage you choose: repositories on local disk, S3-compatible object storage or NFS, with a copy repository next to the primary, promotion of a copy and replacement of the primary without losing access to existing backups (menu: Repositories). The installation's default repository is set in the web interface (or the environment); tenants on it stay separated by their own prefix and key. NFS shares are mounted from the web interface through the mounter container (Installation › Default repository & network shares, docs/MOUNTS.md).
- Multi-tenant for IT service providers (Service Provider edition), with a REST API (OpenAPI) and webhooks for RMM and PSA tools. The other editions run one organisation.
- Alerts and reports: rules that send an e-mail, a bell entry or a webhook (signed JSON, Discord, Slack or Microsoft Teams) when a backup fails, is overdue for its schedule or a restore check does not pass; warnings name the items that were not backed up and can be acknowledged. Notification mail goes out through SMTP, Microsoft 365 or Google Workspace. Business adds a daily, weekly or monthly summary report; every channel has a delivery log. The Overview, with its tabs Status and Statistics (CSV and PDF, always the active tenant), shows the state at a glance; the statistics of all tenants have a page of their own under Installation (Service Provider).
- Audit log: reads and restores of user data and administrative changes are recorded in a hash-chained, tamper-evident log in every edition and sealed daily. The viewer, with filter and chain verification, is a Business feature.
- Standalone restore:
restow-restorerestores from the chunk store and the keys alone, without a running Restow server or database. - Updates from the web interface: the opt-in updater installs signed releases with a database backup first and an automatic rollback, starts with one command and keeps itself current after every signed update. A Community installation switches to the full build from Installation › Edition.
- Built for daily work: right-click or ⋯ on any table row for its actions, multi-selection to put several machines or mailboxes into a new job, full-width tables, German and English.
Not included in 0.3.0: PST and OST import, PST and MSG export, a Windows agent, continuous IMAP and Graph archive sync, SharePoint, Teams, Google Workspace and public folders. The first backup of a large tenant can take days because Microsoft throttles Graph; Restow shows that wait instead of hiding it.
From the public demo, which runs the Service Provider edition with synthetic data (the audit log viewer is a Business and Service Provider feature), unretouched.
Restow is built by Lucas Flores, an IT systems engineer with 15 years of experience in IT and the owner of a small managed service provider in Bergisch Gladbach, Germany. He is an engineer, not a professional software developer.
A large part of the code is written with AI assistance (Claude Code), steered by that technical background: Exchange, Microsoft Graph, storage and running backups for customers every day. For a backup product that is a real risk, and it is treated as one:
- A feature is not done until its restore is tested automatically. The repository has more than 7,000 automated tests (Vitest across all packages and Go tests for the agent), including suites that run against a real PostgreSQL with Row Level Security, and restore tests that compare byte for byte. None of them has run against a real Microsoft 365 tenant yet.
- The release checklist requires a smoke check before a version is tagged (image build, migrations on a fresh and an upgraded database, backup and restore against a test tenant and a test IMAP server, standalone restore, image and dependency scans). The report is attached to every release; where a check was skipped, it says so.
- The storage format is open and documented (docs/ARCHITECTURE.md, in German), so your data never depends on Restow or its author.
| Part | Technology |
|---|---|
| Language | TypeScript on Node.js 22, one pnpm monorepo |
| API | Hono, OpenAPI for the integration API |
| Authentication | better-auth: passkeys (WebAuthn), authenticator app (TOTP), organizations for tenants (sign-in with Microsoft is planned) |
| Web interface | React 19, Vite, TanStack Router and Query, shadcn/ui, Tailwind CSS v4, i18next (German and English) |
| Jobs | Separate worker and scheduler processes on pg-boss (queue in PostgreSQL, no Redis) |
| Database | PostgreSQL 16 with Row Level Security per tenant, Drizzle ORM and migrations |
| Microsoft 365 | Microsoft Graph only (delta queries, own throttling layer), own client-credentials token client for app authentication (secret or certificate) |
| IMAP and SMTP | imapflow, mailparser, smtp-server for journal receipt |
| Endpoint agent | Go with the standard library only, driving restic; Linux and macOS |
| Storage | Own chunk store: content-defined chunking, SHA-256, AES-256-GCM, pack files; local disk, S3-compatible, NFS |
| Delivery | Two builds of every release (full and Community), each an application image with the roles api, worker and scheduler (plus the optional, opt-in updater) and a web image with Caddy for TLS and the web interface; Docker Compose |
| Tests and checks | Vitest, Playwright, Go tests, Biome, TypeScript strict, gitleaks, pnpm audit, Trivy |
Run Restow on a dedicated Linux VM, and put that VM on other hardware than the systems it backs up: a backup that fails together with the host it protects is no backup. Keep the backups off-site as well, preferably on S3-compatible object storage with Object Lock; the default target, a Docker volume on the VM itself, is meant for a first test. Running Restow natively, without Docker, is not supported.
The install script checks the following before it changes anything. A failed check stops it; a warning does not.
| What | Requirement | The installer |
|---|---|---|
| Operating system | Debian 12 or 13; Ubuntu 22.04, 24.04 or 26.04 LTS | Stops on any other system. |
| Architecture | amd64 or arm64 | Stops on any other. |
| Machine | A dedicated VM. LXC, OpenVZ and other containers work on a best-effort basis only (in LXC, Docker needs nesting and keyctl, and some hosts still break it). | Stops inside Docker, Podman and WSL; warns in LXC, OpenVZ and other containers. |
| Memory | At least 4 GiB assigned to the VM, 8 GiB recommended (mail parsing helper processes use up to 512 MB each). | Counts what the system reports plus the memory the kernel reserves for kdump. Warns below 7 GiB (a VM with 8 GiB shows a little less), stops below 3 GiB. See Memory on Proxmox and other hypervisors. |
| Disk | At least 1 GiB free for /opt/restow; at least 10 GiB free for Docker's data directory (/var/lib/docker by default; images and database), 50 GiB or more recommended, because the backups go into a Docker volume there until you add another storage target. |
Stops below 1 GiB for /opt/restow or below 10 GiB for Docker; warns below 50 GiB for Docker. On an LVM volume whose volume group has unused space it prints the command that grows it, see Disk on Ubuntu with LVM. |
| Clock | Synchronised (NTP): certificates, signature checks and authenticator codes need the right time. | Warns if it is not. |
| Rights | root, or sudo |
Stops without. |
| Tools | curl, awk, sed, od, base64, tr, df and mktemp |
Stops if one is missing. |
| Docker | Installed by the script from Docker's apt repository when it is missing. Docker from snap is not supported. An installed Docker needs Engine 24.0 and Compose 2.20 or newer. | Stops on Docker from snap, on an older version, and when Docker is missing and packages that conflict with Docker's own are installed (for example docker.io, containerd, runc). |
| Outbound HTTPS | Port 443 to github.com, ghcr.io, registry-1.docker.io, tuf-repo-cdn.sigstore.dev (signature checks) and, when Docker is missing, download.docker.com |
Stops if one does not answer. |
| Images | The images of the build and version you install can be pulled from ghcr.io without a login. |
Asks the registry before it changes anything. Stops if an image is not public or does not exist (check --version and --edition). |
| Ports | 80 and 443 free on the host (the Caddy edge). Behind a reverse proxy (--behind-proxy, from 0.2.0) only the one port the proxy forwards to: 443, or 80 for the plain HTTP hop. A journal receiver for Exchange Online (Business and Service Provider) needs one more port, usually 25; you set it up after the installation. |
Stops if 80 or 443 is in use (behind a reverse proxy: if the one port it needs is). Does not check the journal port. |
| Domain | Public installation: a domain whose A or AAAA record points at the server, with ports 80 and 443 reachable from the internet; Caddy gets the Let's Encrypt certificate there. Not needed with --local (evaluation only). Behind a reverse proxy: the name your proxy serves; this host needs no DNS record of its own and no inbound port from the internet. |
Warns if the domain does not resolve to this host (not behind a reverse proxy: the name points at the proxy, so DNS is not checked). |
A VM sees less memory than it is given: the kernel and the firmware keep some,
and where kdump (crash dumps) is enabled, as it can be on Ubuntu, the kernel
sets aside another 320 to 512 MB for a crash kernel (crashkernel= on the
kernel command line; Ubuntu's default is 320 MB for a machine with 2 to 4 GiB
and 512 MB for 4 to 32 GiB). free does not count that memory. The installer
adds it back before it judges the memory, so a VM with 4 GiB, which can show as
little as 3.3 GiB, only gets a warning and the installation goes on.
- Assign at least 4 GiB to the VM, 8 GiB recommended.
- With ballooning (Proxmox VE: a "Minimum memory" below "Memory"), the VM can be left with less than you assigned. Set "Minimum memory" equal to "Memory".
- After you change the memory, shut the VM down and start it again. A reboot from inside the VM does not apply the change.
- Check inside the VM:
free -hshows what the system sees, andcat /sys/kernel/kexec_crash_sizethe bytes reserved for kdump (0or no such file: nothing is reserved; newer kernels also offer/sys/kernel/kexec/crash_size).
Ubuntu Server's installer sets up LVM and often makes the root logical volume
smaller than the disk: on a 30 GB disk, / can be 15 GB and the rest of the
volume group stays unused. Docker's data directory (/var/lib/docker) lives on
/, so the disk check can stop the installer on a VM whose disk is large
enough. Check how much of the volume group is unused (column VFree), then
grow the root volume and its file system in one step:
sudo vgs
sudo lvextend -r -l +100%FREE /dev/ubuntu-vg/ubuntu-lvubuntu-vg and ubuntu-lv are Ubuntu's default names; sudo lvs shows yours,
and when the installer finds unused space it prints this command with the
right names. If VFree is 0, there is nothing to extend: the disk itself has to
be larger.
Every release carries install.sh, which sets up the release stack on such a
VM in /opt/restow. It checks the machine (operating system, architecture,
virtualization, memory, disk, ports 80 and 443, outbound HTTPS, clock, the
domain's DNS record, that the images can be pulled without a login, an earlier
installation), installs Docker Engine and the Compose plugin from Docker's
signed apt repository if Docker is missing, downloads docker-compose.yml and
env.example of the release and checks them against the release's signed
SHA256SUMS, writes .env (mode 0600) with freshly generated secrets, checks
the cosign signatures of the two images and starts the stack. Download it,
check it, then run it:
curl -fsSLO https://github.com/restow-backup/restow/releases/download/v0.4.12/install.sh
curl -fsSLO https://github.com/restow-backup/restow/releases/download/v0.4.12/install.sh.sha256
sha256sum -c install.sh.sha256
sudo bash install.shRun without options on a terminal, it starts with a short introduction (what it
will do, about 10 to 20 minutes, what you need) and asks how Restow is reached:
1 public, with its own certificate (a domain that points at the server,
ports 80 and 443 open to the internet), 2 behind a reverse proxy you already
run (Nginx Proxy Manager, Traefik, Caddy, ...), 3 a local evaluation (the
same as --local). It then asks for the domain (for option 2 also for the
proxy's address) and the build (full or Community, see step 2 below), shows its
plan, and before it starts the stack shows RESTOW_MASTER_KEY once: store it
offline then, it is never shown again and not written to the log. At the end it
waits until the api is healthy, reads the one-time setup token from the api's log
and prints, as its last lines, a box with the address to open and the token. The
token goes to the terminal only, never to /var/log/restow-install.log; a run
whose output is collected (no terminal) prints how to read it instead. The setup
wizard first asks for the language, then for the token, which stays valid until
the setup is finished. Read it again on the server with
cd /opt/restow && sudo docker compose logs api | grep 'SETUP TOKEN'. (The 0.1.0
script asks only for the domain and the build, and prints the setup URL and that
command.)
install.sh.sha256 only proves that the download is complete. To check that
the script is the one the release workflow published, verify the signed
checksum list with cosign first:
curl -fsSLO https://github.com/restow-backup/restow/releases/download/v0.4.12/SHA256SUMS
curl -fsSLO https://github.com/restow-backup/restow/releases/download/v0.4.12/SHA256SUMS.sigstore.json
cosign verify-blob SHA256SUMS --bundle SHA256SUMS.sigstore.json \
--certificate-identity https://github.com/restow-backup/restow/.github/workflows/release.yml@refs/tags/v0.4.12 \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
sha256sum -c --ignore-missing SHA256SUMSFor an unattended installation pass the answers as options; the master key is
then not shown, so copy it from /opt/restow/.env to an offline place right
away:
sudo bash install.sh --non-interactive --domain backup.example.com --edition communitybash install.sh --help lists every option and the exit codes: --domain,
--edition full|community (default full), --version, --dir (default
/opt/restow), --yes or --non-interactive, --with-updater (the opt-in
updater stays off unless you ask for it, see docs/UPDATING.md),
--no-mounter or --without-mounter (the mounter, which backs up file shares and
mounts NFS network shares, starts by default for 0.3.0 and newer; these leave it off,
--with-mounter is still accepted; see docs/MOUNTS.md),
--local (an evaluation without a public domain: the edge serves
https://localhost or an internal name such as restow.internal over HTTPS
with a certificate from Caddy's own authority, browsers warn about it and
passkeys are not offered; --http-local is a deprecated name for it),
--behind-proxy, --proxy-ip and --proxy-hop (from 0.2.0, see
Behind a reverse proxy below),
--dry-run (checks only, prints what it would do) and --skip-signature-check
(for tests and unsigned mirrors only, never for production). Its log is
/var/log/restow-install.log, without secrets.
Running the script again is safe: it finds the installation, never changes
.env, a secret or data, checks the images named in .env and makes sure the
stack runs. It brings docker-compose.yml to the checked file of the release
named in .env (an installation keeps its first file across updates, so an older
one lacks newer services such as the mounter); a file that differs is kept as
docker-compose.yml.bak-<time>. It refuses to start when Docker holds data of an earlier
installation without its .env. It never updates an installation (see
Updating) and has no uninstall (see
Removing Restow).
As a shortcut, the script also runs straight from the download:
curl -fsSL https://github.com/restow-backup/restow/releases/download/v0.4.12/install.sh | sudo bashThat runs whatever arrives without your own check of the script first. It still checks the signatures of everything it downloads afterwards, but prefer the steps above on a production server.
If a reverse proxy you already run holds your public names and certificates, Restow needs no public DNS record on its host, no inbound port 80 or 443 from the internet and no certificate of its own. The proxy terminates TLS and forwards to the Caddy edge on the Restow host, encrypted by default: the edge serves HTTPS with a certificate from Caddy's own authority. From 0.2.0:
sudo bash install.sh --behind-proxy --domain backup.example.com --proxy-ip 192.168.1.20--proxy-ip is the address of the proxy itself as the Restow host sees it (repeat
the option or separate several with spaces; a bare address gets /32 or /128),
not your network: Restow believes the client address these peers report in
X-Forwarded-For. It is required with --non-interactive. The script checks that
port 443 is free (port 80 is not needed), does not look at DNS, and writes to
.env:
RESTOW_APP_DOMAIN=backup.example.com
RESTOW_PUBLIC_URL=https://backup.example.com
RESTOW_EDGE_TLS=internal
RESTOW_EDGE_TRUSTED_PROXIES=192.168.1.20/32
RESTOW_HTTP_PORT=127.0.0.1:HSTS stays off (it belongs to the proxy), and port 80 is published on the
loopback only. The script copies the root certificate of the edge's own
authority to /opt/restow/edge-root-ca.crt, to verify the edge with. In the
proxy: scheme https, the Restow host's address, port 443 (not 80, and never
3000, which is the api on the loopback), response buffering off, and for nginx-based
proxies such as Nginx Proxy Manager, under Advanced:
proxy_ssl_server_name on;
proxy_ssl_name $host;
proxy_buffering off;(proxy_buffering off lets the live updates, server-sent events, through.)
Docker publishes port 443 on every interface and ufw rules do not cover it; to
let only the proxy in, publish it on one address (RESTOW_HTTPS_PORT=192.168.1.50:443)
or use the DOCKER-USER chain. The settings of Traefik and Caddy as the proxy,
the firewall rule, the plain HTTP hop (--proxy-hop http, not encrypted, for
a proxy on the same host or in an isolated network, any release) and the manual
way for an installation made with 0.1.0 (RESTOW_APP_DOMAIN=http://..., a
LAN-only unencrypted hop) are in the documentation:
Behind a reverse proxy.
On any Linux host with Docker and Docker Compose v2 (the steps the script automates). For a local evaluation on your own machine, see the note after step 2.
-
Get the release stack. It runs the published, signed images and builds nothing. Download
docker-compose.ymlandenv.examplefrom the release assets into an empty directory and runcp env.example .env, or clone the tag and work indeploy/release/:git clone --branch v0.4.12 https://github.com/restow-backup/restow.git cd restow/deploy/release cp .env.example .env -
Fill in
.env. Every variable is explained on docs.restowbackup.com; everything below "Optional" can stay empty. At minimum the two images of one build, either the full build (RESTOW_IMAGE=ghcr.io/restow-backup/restow:0.4.12,RESTOW_WEB_IMAGE=ghcr.io/restow-backup/restow-web:0.4.12; Business and Service Provider stay locked until a license key is installed) or the Community build (ghcr.io/restow-backup/restow-community:0.4.12,ghcr.io/restow-backup/restow-web-community:0.4.12; the Apache-2.0 core alone), thenPOSTGRES_PASSWORD, the three database connection strings (DATABASE_MIGRATION_URL,DATABASE_URL,DATABASE_PROVIDER_URL),RESTOW_MASTER_KEY,BETTER_AUTH_SECRET,RESTOW_PUBLIC_URLandRESTOW_APP_DOMAIN(the compose file refuses to start without it). Generate secrets with:openssl rand -base64 32 # RESTOW_MASTER_KEY, BETTER_AUTH_SECRET openssl rand -hex 16 # each database password
Back up
RESTOW_MASTER_KEYoffline before the first real backup. It wraps every tenant's key; without it no backup can ever be read again.Local evaluation: set
RESTOW_APP_DOMAIN=localhostandRESTOW_PUBLIC_URL=https://localhost. Caddy then serveshttps://localhostwith a certificate from its own local certificate authority, so your browser shows a warning until you trust it, and ports 80 and 443 on the machine must be free. Choose the local operating mode in the setup wizard; passkeys are not offered there, so the first administrator signs in with a password and an authenticator app. -
Start the stack
docker compose up -d
This pulls the images and starts PostgreSQL, the three Restow roles and Caddy. The
apicontainer applies the database migrations before it serves. -
Check it and open the setup wizard
curl -fsS http://127.0.0.1:3000/healthz
Open
RESTOW_PUBLIC_URLin a browser. The setup wizard first asks for the language (English or Deutsch, preselected from the browser), then for the one-time setup token, which proves that you operate the server and which only someone with access to it can read: theapicontainer prints it to its log at every start until the setup is complete.docker compose logs api | grep 'SETUP TOKEN'
Then it shows the operator notice, chooses the operating mode and the installation's time zone (the browser's is preselected; planned updates are read in it and new tenants start with it), asks for the name of your organisation (it becomes your own organisation, the place for your own backups), creates the first administrator (passkey first) and sets up notification mail, which you can skip and set up later under Installation, Settings, Mail. Then add a Microsoft 365 tenant or an IMAP mailbox as a source. For an unattended installation, set
RESTOW_SETUP_TOKENin.envinstead (see.env.example).
To build the images from source instead of pulling them, see CONTRIBUTING.md. The release images can be verified with cosign; see deploy/release. The operator guides, including the Entra app registration for Microsoft 365, are in the documentation; the release pipeline and its smoke checks are described in docs/CI.md.
The install script has no uninstall on purpose: removing an installation can
destroy backups. To remove one by hand, in its directory (/opt/restow for an
installation made by the script):
cd /opt/restow
sudo docker compose --profile updater downThis stops and removes the containers. The database, the local chunk store,
Caddy's certificates and the updater's database dumps stay in their Docker
volumes (restow_pgdata, restow_restow-data, restow_caddy-data, ...), and
.env stays in place. A database that was moved to another disk
(docs/DATABASE.md) is in the directory RESTOW_POSTGRES_DATA
in .env names, not in a volume; remove it there. Only when you are sure that no
backup in them is still needed:
sudo docker compose --profile updater down --volumes # deletes the database and the local chunk store
cd / && sudo rm -r /opt/restow # .env holds RESTOW_MASTER_KEYKeep an offline copy of RESTOW_MASTER_KEY as long as backups on other
storage (S3, NFS) may still be needed: restow-restore reads them with the
key alone. Those backups are not deleted by the steps above; remove them in the
storage itself. Docker stays installed.
The Upgrade Notes of every release state whether the update needs only a new image, runs database migrations (automatically, at start) or needs manual steps, how long it takes and how to roll back. The steps, the backup before the update and the rollback are in docs/UPDATING.md; release notes follow docs/releases/TEMPLATE.md. Internal builds before 0.1.0 cannot be upgraded; see Breaking Changes in the changelog.
If the last owner of an installation has lost their passkey, authenticator app
or password, recover the access on the server, in the api container:
docker compose exec api restow admin list
docker compose exec api restow admin recover --email owner@example.comadmin recover asks for confirmation and for a new password, then removes the
owner's authenticator app and passkeys and ends all their sessions. The owner
signs in with the new password and sets up an authenticator app again before
anything else. The recovery is recorded in the audit log. It works for owners
only; an owner resets every other administrator in the web interface
(Installation › Members, Reset access: password, passkeys and authenticator
app are removed, the sessions end, and the administrator gets a new link to
choose a password).
docker compose exec api restow help lists the options.
All editions are self-hosted, have no mailbox limit and never limit restore.
| Edition | For | Price |
|---|---|---|
| Community | One organisation: every backup source and restore function, endpoint backup, mail import and export, the archive (search, hash chain), alerts, dashboard and statistics, the REST API, tenant members with self-service restore. Several provider administrators with roles (owner, administrator, technician, read only), each with every tenant. Apache-2.0, no license key. | Free |
| Business | Adds the archive's GoBD layer (journal receiver, enforced retention, legal hold), scheduled summary reports and the audit log viewer. CSV and PDF export of the audit log is planned. Still one organisation. | One-time purchase |
| Service Provider | Adds multiple tenants, team members limited to chosen tenants, the cross-tenant API and the provider dashboard. | One-time purchase |
Every release comes in two builds. The full images (restow, restow-web)
contain the Business and Service Provider modules, which an offline-verified
license key (Ed25519, no phone-home) unlocks at runtime under Installation › License;
without a key they run as Community. The Community images (restow-community,
restow-web-community) contain the Apache-2.0 core alone and no license
screen. Both use the same database, so you can switch by changing the two image
lines in .env; a Community installation also offers the switch to the full build
under Installation › Edition, done by the opt-in updater when it runs (the full images
of the same version, signature-checked, with a backup and a rollback), and keeps a
license key entered there until the full build checks and applies it. The switch
goes one way: from Community to the full build. Mailbox and tenant counts are an honour rule of the license
terms, not a limit in the software. Prices and terms:
restowbackup.com.
Building from source, running the development servers and the checks are described in CONTRIBUTING.md.
Documentation lives in two places. The operator guides are at docs.restowbackup.com. The files in docs/ are for maintainers and contributors: the design documents ARCHITECTURE, STACK, MICROSOFT, IMAP, ARCHIVE, IMPORT, AGENT, ENTRA-SETUP and TESTING are written in German; STORAGE, SIZING, UPDATING and CI are in English. Code, commits, this README, the changelog and the public documentation are in English.
- Contributions are welcome; please read CONTRIBUTING.md. A contributor license agreement (CLA.md) is required before the first pull request is merged.
- Report vulnerabilities privately as described in SECURITY.md, never in a public issue.
The Restow core is published on GitHub under the Apache License 2.0.
The Business and Service Provider modules in ee/ are licensed under the
Restow license terms.
Made by IT Systeme Flores UG (haftungsbeschränkt), Bergisch Gladbach, Germany.








