Your nightly Postgres dump succeeded. The retention policy kept thirty days. The monitoring is green. Then a disk dies, you restore the dump into a fresh database — and the app still does not come back, because half of what the app needed was never in the database. Uploaded files, local caches, plugin data, the SQLite sidecar the app writes to on every request: all of it lived in a Docker volume that no backup job ever named.
That split — a tested, scheduled path for database state and an ad-hoc afterthought for everything else the container writes — is the most common backup gap on self-hosted infrastructure. Portabase, the open-source backup and restore platform that started as a database-dump scheduler, closed it in 2026 by promoting Docker volumes to first-class backup targets alongside Postgres and MySQL.
The tool is aimed at single Docker hosts, not multi-node fleets, so this is not a "go install it on your cluster" post. The verdict that matters for a self-hosted PaaS is the thesis underneath: database state and container state are one backup problem, and every platform that schedules, retains, and restore-tests them as two separate problems is carrying the exact gap Portabase just deleted.
What Portabase actually shipped
Portabase (the name is Portainer plus Database) is a self-hosted backup and restore platform built around a central server with a dashboard, lightweight agents that run on each Docker host and do the heavy lifting, and a CLI with a TUI wizard for registering what to protect. The server holds schedules, retention policies, storage backends, and notifications; agents execute dump and archive jobs where the data lives. Coverage of the new capability landed in July 2026, including a hands-on walkthrough from Brandon Lee at Virtualization Howto and a maintainer-published guide backing up a full Nextcloud stack.
The notable design decision is that Docker volumes were not added as a side feature with their own screen. They were added as another backup type in the same model as every database engine:
| Capability | How it works for Docker volumes |
|---|---|
| Registration | docker-volume type; give the exact volume name, optionally the container using it so the agent restarts that container after a restore |
| Backup | Hot archive of the named volume, no container stop required |
| Restore | Restore into place from the dashboard like any database restore |
| Schedule | Same scheduler as database jobs — one cron surface for both |
| Retention | Same retention policies — volume archives age out under the same rules as dumps |
| Destination | Same pluggable storage (local disk, S3, Azure Blob, GCS) |
| Notify | Same notification path reporting success or failure |
| Migrate | Built-in migration wizard moves a protected volume to another host |
The supported-engine table now reads as one continuum: PostgreSQL, MySQL, MariaDB, MongoDB, SQLite, Redis, Valkey, Firebird, MS SQL Server — and Docker Volume, marked Stable for Engine 20.10 and up, with restore supported. Volumes registered this way show up in the dashboard's managed list next to databases, get grouped into Projects, and back up on the same cadence. That is the whole point: there is no longer a "database backup story" and a separate "volume backup story" to keep in sync. There is one schedule, one retention policy, one destination, one restore screen.
The split this kills: two backup paths become one
To see why that matters, inventory the typical self-hosted setup before unification. The database gets the royal treatment: a native dump tool (pg_dump, mysqldump, mongodump), a cron schedule, compression, upload to object storage, thirty days of retention, and a success notification. The Docker volumes get whatever is left over: maybe a tar script someone wrote two years ago, maybe a "we back up the whole host" assumption, maybe nothing, because the container is disposable and disposable was misread as not needing backups. The container is disposable. The named volume it mounts is the data, and it dies with the disk like anything else.
Put side by side, the asymmetry is stark:
| Concern | Database dumps (before) | Volume copies (before) | Unified (after) |
|---|---|---|---|
| Schedule | Nightly cron, monitored | Irregular script or nothing | One schedule covering both |
| Mechanism | Native dump tool, consistent | Raw tar, crash-consistent at best | Dump for live DBs, archive for the rest — each in its right lane |
| Destination | Object storage | Local disk, if anywhere | One backend for both |
| Retention | 30 days, enforced | Forever until the disk fills, or never | One policy |
| Restore path | Documented, occasionally drilled | "Read the script and hope" | One dashboard flow, same drill |
| Failure signal | Alert on failure | Silent until the disk dies | One notification path |
The Nextcloud case Portabase's own guide walks through is the canonical example of why the unified column is the only honest one. A running Nextcloud is a database and a data volume: file metadata lives in MariaDB or Postgres, file contents live on disk. Restore the dump without the volume and you have an index pointing at files that do not exist. Restore the volume without the dump and you have files no database row references.
Either half restored alone is a broken app wearing a green checkmark. Portabase's answer is to protect both halves as one Project and restore both from one screen — which is less a product feature than a restatement of what "backed up" was always supposed to mean.
For a self-hosted PaaS, this is the paragraph to sit with. A platform that offers managed Postgres with point-in-time recovery but leaves tenant volume snapshots as an undocumented extra — or the reverse, host-level snapshots with no database-aware dumps — is selling the top row of that table while quietly shipping the middle row. Tenants cannot tell the difference until restore day, which is exactly when the difference stops being academic.
The honest limits
Unification is the right shape, but Portabase's implementation is a single-host Docker tool, and its docs are refreshingly explicit about the edges. Four limits matter before anyone extrapolates:
A hot file copy is not a consistent live-database backup. The docker-volume provider archives the volume as-is, on the fly, without stopping the container. That is exactly right for uploaded files, caches, and static assets. It is the wrong mechanism for a running Postgres or MySQL data directory, where files change mid-copy and a torn archive may not start. Portabase's own model says the same thing: live databases keep their native dump drivers, and the volume provider covers everything without a dedicated dump tool. Use each lane for what it is for; "one tool" never meant "one mechanism."
Staging needs disk. The agent builds the volume archive in a temp directory (system /tmp by default, overridable with TMPDIR) before shipping it to the destination. The archive runs roughly the size of the volume, so a 20 GB volume needs about 20 GB free at the temp location — and a cramped root filesystem fails the job with No space left on device. Size the agent host's temp storage like backup infrastructure, not like an afterthought mount.
The agent holds root-equivalent trust. Archiving a named volume requires Docker daemon access, so the agent container mounts /var/run/docker.sock. Anyone who can talk to that socket can start privileged containers; that is the standard Docker-backup tradeoff (every volume-backup agent pays it), but it means the agent host is in the trust boundary and the server-to-agent channel — encrypted with the project's secret — deserves the same care as any backup control plane.
Single-host scope. This is Docker Engine backup, host by host: an agent per machine, volumes by exact name. It is not a fleet answer — no Kubernetes PVC discovery, no multi-node scheduling, no cluster-aware restore ordering. A PaaS running on Cluster API and Hetzner cannot point this at a fleet and call the problem solved. What it can do is steal the shape, which is the next section.
What a self-hosted PaaS should steal
Portabase does not run on your cluster, but its checklist ports directly. Every row in the unified column above has a fleet equivalent, and most platforms have built the database half while postponing the volume half:
| Unified primitive | PaaS equivalent to build |
|---|---|
| One schedule | Managed-database backup schedules (e.g. CloudNativePG scheduled backups) and persistent-volume snapshot schedules on the same cadence, not two calendars nobody cross-checks |
| Right mechanism per lane | Native DB dumps or WAL archiving for databases; storage-level snapshots for volumes — never a raw file copy of a live data directory |
| One destination | Both lanes landing in the same object storage backend with the same encryption and lifecycle rules |
| One retention policy | Snapshot retention matched to dump retention, so day-29 of one is never missing day-29 of the other |
| One restore runbook | A single documented flow that restores both halves of a tenant app, in dependency order, from one starting point |
| One failure signal | Snapshot-job failures alerting on the same path as database-job failures — no silent lane |
| Restore verification | Periodic drill restores of both halves together, because an untested restore is a rumor |
Two of these deserve emphasis because they are where platforms most often stop one step short. The first is retention symmetry: a thirty-day database history paired with seven days of volume snapshots is a thirty-day story that quietly becomes a seven-day story the moment anyone needs both. Match the windows or document — loudly, to tenants — that they differ.
The second is the joint drill. The Nextcloud lesson generalizes to every tenant app with a database plus a data directory: restore both halves into a scratch namespace on a regular cadence and boot the app, or admit the restore path is untested. Portabase's contribution here is making the joint restore the default path rather than a heroic cross-team exercise; a PaaS should aim for the same default, even if the machinery underneath is CloudNativePG plus volume snapshots instead of one agent binary.
There is also a scoping lesson in what Portabase did not do. It did not build fleet orchestration, multi-cluster discovery, or a control plane for anything beyond its backup domain. It took one sharp problem — two backup paths that drift apart — and merged them. A PaaS backup story earns the same focus: unify the two lanes you already have before adding a third system, a new backend, or a fancier dashboard.
Backups are one problem
The container-is-disposable mantra taught a generation of operators to back up the database carefully and wave at the volumes. Portabase's Docker volume support is a small feature with a large implied correction: if the restore needs it, it is the backup, whatever storage primitive it happens to live on. Schedule it together, retain it together, restore it together, drill it together — or stop claiming the app is backed up.
For self-hosters, that correction is installable today on a single Docker host. For PaaS builders, it is a design review to run against your own platform: pull up your database backup schedule and your volume snapshot schedule side by side, and ask whether a tenant could tell they belong to the same system. If the answer is no, you now know what to build next.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



