How to Back Up and Restore a Coolify Server Properly
Tutorial

How to Back Up and Restore a Coolify Server Properly

Coolify's built-in backup covers less than most people assume, and a filesystem copy of a live Postgres data directory is not a valid database backup no matter how confident it looks in a file listing. Here's what actually has to be backed up, and a restore you've actually tried before you need it.

Published November 6, 202511 min readUpdated Sep 6, 2026

Written by · Full-Stack Agentic AI Software Engineer — AI Agents, Automation & Revenue Systems for GTM/RevOps teams

In brief

What actually needs to be backed up on a Coolify server, and how do I restore it when something goes wrong?

Five separate things, not one: Coolify's own instance data (projects, resource configs, deployment history), your applications' Docker volumes and bind mounts (uploaded files, generated assets, TLS state), your databases (which need a real dump, not a filesystem copy), your environment variables and secrets, and the Docker images themselves if you're not rebuilding from source. Coolify's built-in backup handles the first item and can schedule database dumps to S3-compatible storage, but it does not back up arbitrary volumes or bind mounts by default — that's on you. The single most common mistake is treating a live database's data directory like any other folder: copying files while Postgres is running captures a data directory mid-write, which can be internally inconsistent in ways that don't surface until you try to restore it and it doesn't start. A backup you haven't restored, on a fresh box, is a hypothesis, not a backup.

  • Coolify's instance backup saves its own config, projects, and deployment history — it explicitly does not cover data inside your applications, databases, or volumes
  • Database backups need a real dump command (pg_dump, mysqldump, mongodump) run through the database's own tooling, on a schedule, pushed to S3-compatible storage — Coolify supports scheduling this for Postgres, MySQL, MariaDB, MongoDB and Redis
  • A raw filesystem copy of a running Postgres data directory is not a valid backup — the files can be mid-write when copied, and a database restored from that state may not start, or may start with silent corruption
  • Docker volumes and bind mounts holding uploaded files, generated assets, and TLS certificate state are not covered by Coolify's instance backup and need their own plan, typically a scheduled rsync or restic job to off-box storage
  • An untested backup is not a backup — the only way to know a restore actually works is to run it, on a separate box, before you need it for real

Evidence notes

Coolify instance backup docs

Instance-level backup covers Coolify's own configuration, projects, and resources — not application data, databases, or volumes.

Coolify database backup support

Coolify supports scheduled backups for PostgreSQL, MySQL, MariaDB, MongoDB and Redis, pushing dumps to S3-compatible destinations including Amazon S3, MinIO, Backblaze B2, Cloudflare R2 and Wasabi.

Vultr / Coolify Postgres-to-S3 guide

Documented walkthrough of scheduling pg_dump-based backups to S3-compatible storage from within Coolify.

Cloudflare R2 pricing

Standard storage at $0.015/GB-month with zero egress fees, a common S3-compatible destination for Coolify's scheduled database backups.

Most people find out their backup strategy was wrong on the day they need it, which is the worst possible time to learn that. This is the post for the version of you that hasn't had that day yet. Coolify has a backup feature, and it's genuinely useful, but "Coolify has backups on" and "this server is actually recoverable" are not the same claim, and the gap between them is exactly where people get hurt. It comes down to a single, boring, and completely un-negotiable fact: your server isn't one thing to back up, it's five, and Coolify's own backup only reaches one and a half of them.

What actually has to be backed up?

Break "back up the server" into its actual parts and the scope of the problem stops being vague. There's Coolify's own instance data — the projects, resources, and deployment history that make Coolify itself useful rather than a blank dashboard. There's every application's Docker volumes and bind mounts, which is where uploaded files, generated assets, and anything written to disk at runtime actually lives. There's the databases, which need their own category entirely because a database isn't a folder of files you can copy, it's a live process with its own internal consistency rules. There's environment variables and secrets, which live in Coolify's own database and are easy to assume are covered by 'the instance backup' without checking. And there's TLS state — the certificates Traefik has already issued, which you'd rather not re-request from Let's Encrypt under rate limits during an actual outage. Readers who reach how to back up and restore a coolify server properly through a growth or RevOps role will want XenGrowth's marketing operations practice alongside this.

What

Does Coolify's built-in backup cover it?

What you actually need

Coolify's own config (projects, resources, deployment history)

Yes — this is exactly what instance backup covers

Schedule it, and store the export somewhere other than the same disk

Application Docker volumes / bind mounts (uploads, generated files)

No — explicitly out of scope per Coolify's own docs

A separate scheduled job (rsync, restic, or similar) to off-box storage

Databases (Postgres, MySQL, MariaDB, MongoDB, Redis)

Partially — Coolify can schedule real dump-based backups to S3-compatible storage, but only if you configure it per database

Confirm the schedule is actually set per database; don't assume it's on by default

Environment variables and secrets

Bundled inside instance backup, but easy to overlook as 'covered' without checking

Verify a restored instance actually shows your app's env vars before considering it done

TLS certificate state (Traefik's issued certs)

Not separately tracked as its own backup category

Either accept re-issuance on restore, or explicitly capture Traefik's cert storage volume

What Coolify's backup actually does — and where it stops

Coolify's instance backup, as documented, saves Coolify's own data: your projects, your resource configurations, your deployment history, the settings that make the dashboard useful. That's real and it matters — losing it means rebuilding every app's configuration from memory, which on a server running more than one or two things is a genuinely bad afternoon. But read the scope carefully, because it's stated plainly and often skimmed past: instance backup does not back up data stored inside your applications, your databases, or your volumes. Those are three different things sitting right next to the one Coolify actually protects for you, and assuming they're covered because 'Coolify has a backup feature' is the exact gap this post exists to close. The XenGrowth resource library approaches this from the the operations side of this side.

Where Coolify does help more than most self-hosted PaaS tools is database backups specifically. It supports scheduling real dump-based backups — pg_dump for Postgres, mysqldump for MySQL and MariaDB, mongodump for MongoDB, RDB snapshots for Redis — and pushing the result to S3-compatible storage: Amazon S3, MinIO, Backblaze B2, Cloudflare R2, or Wasabi. That's the right mechanism, and it's built in rather than something you have to script from scratch. The catch is that it's opt-in per database, not a blanket setting, and it's worth going and checking right now, on your actual server, whether it's configured on every database that matters — not whether Coolify supports it in principle.

Why a filesystem copy of a live Postgres directory isn't a backup

This is the mistake that trips people up most often, because it looks completely reasonable right up until it fails. Postgres stores its data as a directory of files on disk, so copying that directory — tar it up, rsync it somewhere, whatever — feels equivalent to backing up any other folder. It isn't, and the reason is specific: Postgres is a live process writing to those files continuously, and a filesystem-level copy taken while it's running can capture some files mid-write and others from a slightly different moment, because a plain copy has no concept of database transaction boundaries. The result is a data directory that's internally inconsistent in a way nothing about the copy operation itself will warn you about. Sometimes that inconsistent copy still starts up fine when you try to use it, which is almost worse than it failing outright, because you won't find the actual damage until a query returns wrong data or a table is silently missing rows nobody noticed were gone. Sometimes it refuses to start at all, and you find out exactly when you need it most: mid-recovery, server down, clock running. Postgres does have a correct way to do a filesystem-level backup — pg_basebackup, combined with WAL archiving — but that's a deliberate, consistent snapshot mechanism, not a bare cp or tar of a running data directory, and the two are not interchangeable no matter how similar the resulting file listing looks. XenGrowth on governed AI marketing workflows goes further into AI agents and marketing automation.

A backup you haven't restored is a hypothesis about a backup. The only way to know pg_dump actually captured something usable is to load it into a fresh Postgres instance and query it — not to see the file land in your S3 bucket and call it done.

Setting up the backups that actually matter

  1. Turn on Coolify's instance backup first — it's the cheapest win here and covers the one thing that's genuinely automatic. Schedule it to run daily and confirm the export target isn't the same disk the server itself runs on.

  2. For every database resource, go into its backup settings specifically and confirm a schedule is set with an S3-compatible destination configured — don't assume this inherited from the instance backup, it didn't.

  3. For anything writing to a Docker volume or bind mount outside of a database — uploaded user files, generated PDFs, anything under a path mounted into a container — set up a separate scheduled job. A simple restic or rsync cron job pushing to the same S3-compatible bucket is enough; the point is that it exists and runs on a schedule, not that it's sophisticated.

  4. Export your environment variables and secrets independently of whatever else you're backing up, at least occasionally, and store that export somewhere encrypted and separate from the server itself — if the box is gone, you want the values in hand before you're trying to reconstruct which API key went where from memory.

  5. Decide, explicitly, what you're doing about TLS state. The simplest answer is usually to accept re-issuance: Let's Encrypt certificates are free and fast to reissue, and Traefik requests them automatically the moment DNS resolves to a working box again. The only reason to capture cert storage separately is if you're near Let's Encrypt's rate limits already, which is rare for a normal app.

  6. Write down where every one of these backups lives and how to trigger a restore, somewhere that isn't only on the server itself — a dead server can't tell you where its own backups are stored.

The restore walkthrough: proving it actually works

None of the above matters if the first time you actually run a restore is during a real outage. Do this on a separate, disposable VPS — not the server you're trying to protect — before you ever need it for real.

  1. Provision a fresh, small VPS with nothing on it and install Coolify with the standard one-line installer, exactly as if this were a brand-new server.

  2. Restore the instance backup into this fresh install. You should end up looking at your real projects and resource configurations, not a blank dashboard — if you don't, the instance backup wasn't actually capturing what you assumed.

  3. Pull the most recent database dump from your S3-compatible storage and restore it into a fresh, empty database instance — not the same running instance, a genuinely new one, so you're testing the dump file itself and not the memory of a process that never stopped running.

  4. Run a real query against the restored database that would only return correct results if the data actually came through intact — count a table's rows, check a specific known record, something more meaningful than 'the database started without an error.'

  5. Restore the volume backup for at least one application that stores real files, and confirm a specific known file is present and opens correctly, not just that a folder with the right name exists.

  6. Time the whole exercise. This is the number that actually matters when someone asks 'how long until we're back up' during a real incident — not a guess, an actual rehearsed number from having done it once already.

  7. Tear the test VPS down once you've confirmed all of the above, and put a recurring reminder to repeat this quarterly, or whenever you materially change what's running on the real server.

What this restore drill actually proves, and what it doesn't

A successful restore drill proves your backups are structurally valid and your process for using them works end to end — which is most of what a real disaster recovery actually needs. It doesn't prove your backup frequency is tight enough for your actual tolerance for lost data; if your database backup runs nightly and the server dies at 4pm, you've lost most of a day's writes regardless of how clean the restore process is. That's a separate decision — how often to back up, not whether the backup works — and it's worth setting deliberately rather than accepting Coolify's default schedule without asking whether it matches how much data you can afford to lose. XenGrowth on building one SEO and GEO content system works through AI search, GEO and discovery in more operational detail.

Your situation

What to prioritize

Solo project, low write volume, downtime is annoying but not costly

Daily instance + database backups, quarterly restore drill is plenty

A SaaS with paying customers and real user-generated data

Database backups on a tighter schedule (hourly, or WAL-based continuous archiving), plus the volume backup for uploads, tested monthly

Multiple apps sharing one Coolify server

Confirm every database resource has its own backup schedule set — this is the setting most likely to be silently missing on app number three or four

Anything already near Let's Encrypt's rate limits

Explicitly capture Traefik's certificate storage volume rather than relying on re-issuance during recovery

Where this fits with the rest of running a Coolify server

Backup strategy is the part of self-hosting that's easiest to defer, because it produces nothing visible until the day it's the only thing that matters. If you haven't done the earlier, equally unglamorous work of securing the box in the first place, that's worth doing before this, not after — a server that's easy to compromise is a server whose backups you'll need sooner than you'd like. And if the failure mode you're most worried about is running out of headroom rather than losing the whole box, what happens when a VPS runs out of RAM covers the more common, less dramatic way these servers actually go wrong day to day. The deploy pipeline this backup plan is protecting is covered start to finish in the full Next.js-on-Coolify walkthrough, and it's worth reading both together — a working deploy pipeline and a tested restore are the same job looked at from opposite directions, and most people only budget time for one of them.

Further reading from XenGrowth

Where this work meets go-to-market

For the marketing and revenue operations view of how to back up and restore a coolify server properly, see XenGrowth's revenue operations work.

What does a Coolify backup have to include?

Four questions on backing up the thing that manages everything else. The control plane has its own state, and it's easy to back up the applications and lose the setup that ran them.

1 / 4
Beyond your app databases, what does Coolify itself hold that you'd lose?

Apply this article

How to turn insights into execution

A practical sequence for teams turning concepts into production outcomes.

CoolifyBackupDisaster RecoveryPostgreSQLSelf-HostingVPStutorials

Audit your current state

Map the bottlenecks and constraints connected to the article’s core problem.

Choose one bounded change

Test the most useful recommendation on one workflow before widening the scope.

Measure what changed

Keep the parts that improve the work, document what failed, and make the next decision from evidence.

Next step

Need help applying this in your stack?

I can translate these patterns into a concrete implementation plan for your team.

Discuss implementationBack to blog

Replies usually within 24 hours.

Next Steps

Continue reading

How I Restore an Entire Server From Backup (And How Long It Takes)

The order matters more than people expect, and the answer to "how long will this take" isn't a number I can hand you — it's dominated by your database size, your download bandwidth, and one DNS setting most people only think to change after they needed to.

Navigate

The Backup Strategy Every Self-Hosted SaaS Needs (3-2-1, Applied)

3-2-1 is easy to nod along to and easy to get wrong in the specific way that only shows up on the day you need it. Here's what it actually means for one VPS running Postgres and Docker volumes, not the generic version you've already skimmed past twice.

Navigate

How to Self-Host Next.js With Coolify: A Complete 2026 Walkthrough

Every Coolify tutorial stops at "push to deploy." This one covers the parts that actually break a real app: standalone output, a build that OOMs on a small box, env vars baked in at the wrong time, and a health check that would have caught all of it.

Navigate

How I Back Up PostgreSQL to S3-Compatible Storage on a Schedule

pg_dump, pg_basebackup and WAL archiving aren't three ways to do the same thing — they answer three different questions about how much data you're willing to lose. Here's which one to run, from a container that has no business having shell access to your host, pushed to storage that makes restoring free instead of expensive.

Navigate

The Simplest Production Architecture for a Bootstrapped SaaS

One box, a handful of managed pieces around the edges, and a very short list of things you're not allowed to build yet. Here's the architecture, priced out to $20 a month, and the exact signal that tells you when to add each thing you skipped.

Navigate

Should Your Database Live on the Same VPS as Your App?

The pitch for co-location is real: no network hop, no egress bill, one box to back up. So is the failure mode — one OOM event takes the app and the database down together, because they were never separate to begin with.

Navigate

What Happens If Your VPS Dies? My Disaster Recovery Plan

"The server died" isn't one scenario, it's at least five, and they don't require the same response. A disk failure and a compromised box both end with the same VPS gone, but only one of them means your backups might be compromised too. Here's the plan for each, written down before any of them happen, not after.

Navigate

How to Host Unlimited Domains on One VPS With Free SSL

"Unlimited domains, one server" sounds like a sales pitch, but it's a genuinely accurate description of what SNI-based virtual hosting and Let's Encrypt automation do together. The real ceiling isn't domain count. It's RAM.

Navigate

The Docker Concepts You Need Before Coolify Hides Them From You

Coolify's whole pitch is that you shouldn't have to think about Docker, and most days that's true. The days it isn't are the days a container is 'running' but unhealthy, a redeploy quietly ate a volume, or an env var vanished — and the dashboard doesn't explain any of it.

Navigate

Wildcard Domains With Coolify and Cloudflare

A wildcard certificate can't be proven the way a normal one is — there's no single page to fetch for a domain that doesn't exist yet. That's why it needs a DNS record instead of an HTTP request, and why Cloudflare's API has to be involved at all.

Navigate