# Daily database backups and restore on your VPS ox backs up your app's databases every day with nothing to turn on. Back up now, keep copies in your S3 bucket, download a backup, and restore it safely. ox backs up your app's databases every day, soon after 03:00 UTC, with nothing to turn on: PostgreSQL with `pg_dump`, SQLite and a project's own Redis or MySQL as files, and the folders ox.toml keeps, such as uploads. Each backup is kept on your server, and a copy goes to your own S3 bucket when you add one. You can also back up now, download a backup, and restore from one with `ox restore`. Once a day, soon after 03:00 UTC, ox backs up each service it can, PostgreSQL with `pg_dump`. Your server keeps 7 daily backups, or 2 once S3 has a copy, 3 manual ones and 3 from before a migrate. Your S3 bucket keeps 30 daily and manual ones together. The counts are per service. ## Turn on daily backups There is no switch: backups are on for every service that can be backed up, from its first deploy. - **PostgreSQL** is backed up with `pg_dump` while it keeps running, whether the database is shared or only for this project. - **Redis, Neo4j, Qdrant, MySQL, ClickHouse, Meilisearch and RabbitMQ** are backed up as files (they always run only for their project). Redis and MySQL keep running: each is copied while it works, and the log says it kept running. MySQL's copy needs as much free disk as its data, and the backup says so when the disk is too full. RabbitMQ keeps running too: its backup is an export of its queues, exchanges and bindings, not the messages in them. Neo4j, Qdrant, ClickHouse and Meilisearch stop for a moment while their files are copied, and the log says for how long. - **A custom service** is backed up as files too. Set `backup = false` on it in ox.toml to skip it ([custom services](https://console.t57.sorv.dev/docs/config#custom-services)). - **SQLite files** in the project's data folder are backed up as well: the first 20 ox finds, in the folder and up to 3 folders below it. - **Each `[storage] keep` folder**, such as uploads or media, is backed up as a `.tar.gz` while the app keeps running; a file the app changes during the copy is saved as it was read. Each backup is a whole copy of the folder, not only what changed, so a big folder takes room: a 50 GB media folder can take up to 500 GB on your server (7 daily and 3 manual copies), within the 20% limit below. When the limit is reached, the biggest folder loses its oldest copies first, so your database keeps its daily backups. A SQLite file inside a kept folder that has its own backup is left out of the folder's copy, and a folder restore keeps every SQLite database in it as it is. Needs a current agent: on an older one the daily backup copies everything else, then fails and names the folders it skipped and the update, and each folder's card says **Not backed up yet**. The daily backup runs once a day, soon after 03:00 UTC. Each one is kept on your server. To keep a copy off the server too, add an S3 bucket in Settings, or from a terminal: Send backups to S3 as well: ```sh ox settings s3 --endpoint https://.r2.cloudflarestorage.com --bucket ox-backups --access-key --from-file secret.txt ``` `--from-file` reads the secret key from a file, or from standard input with `-`, so it never sits on the command line. Without S3, the backup log says `no S3 target in Settings; the backup stays on this host`. ## How many backups ox keeps | Kind | On your server | In S3 | | --- | --- | --- | | Daily | 7, or 2 once S3 has a copy | 30, daily and manual together | | Manual (Back up now) | 3 | 30, daily and manual together | | Before migrate | 3 | Not sent to S3 | The counts are per service. One project's backups may take up to 20% of the server's disk; past that, ox deletes the oldest ones first, but it always keeps the newest backup of each service. When less than 15% of the server's disk is free after a job, ox frees space until 20% is free. Among what it removes are older backups on the server that your bucket still holds: before it removes one, ox asks the bucket, and it removes the backup only if the bucket lists that exact copy, at the same size, right then. Without an S3 bucket, or when the bucket does not answer, every backup stays and the log of that job says why. The newest backup of each service always stays. A deleted project's trash goes before any backup does. Otherwise it stays 7 days: the server's agent empties older trash every day on its own, even while the ox control plane is unreachable. Once you forget the server its agent leaves, and the trash stays in `/var/lib/ox/trash` until you run `sudo ox uninstall` there. Both rules run in the agent on your server, so they hold only on a current agent. A server whose agent is older shows **Update available** until ox updates it, once ox's own servers ran that build for a day. Such an agent, when the disk runs low, removes backups the bucket once confirmed without asking whether the bucket still has them, empties no trash on its own, and no longer removes services no project uses. To do it now, press **Update agent** on the server's page, or run `ox servers update web-1`. While the agent is stopped, nothing is cleaned and no backup is taken; if it is back before midnight UTC, the day's backup runs then. A **before migrate** backup is the copy ox makes of each PostgreSQL database that has tables, right before a deploy runs its migrate step. It is the one to restore when a [rollback](https://console.t57.sorv.dev/docs/operate/rollback#database) needs the old tables back. ## What is not backed up A backup holds a service's data and nothing else. These are in no backup and no S3 copy, so copy them yourself if you need them: - **Files in the project's data folder outside a `[storage] keep` folder**, other than the SQLite databases there (the first 20 found, at most 3 folders down). - A custom service with `backup = false`. - **Messages waiting in a RabbitMQ queue.** A restore brings back the same queues, empty. - **Your variables.** They live only on your server. ox keeps their last 20 versions there ([variable history](https://console.t57.sorv.dev/docs/operate/variables#history)), but no backup holds them. - **Releases and build caches.** ox keeps 3 releases on the server and builds again from your repository. The copy in your bucket is encrypted on your server before it leaves, with [age](https://age-encryption.org), and its name ends in `.age`. This protects the copy if your bucket or its keys leak. It does not hide your backups from ox itself: ox keeps the key, sealed, so it can restore them for you, and it holds your S3 keys. The copy kept on your server is not encrypted. A server whose agent is older still uploads plain copies until its agent is updated; Settings names those servers. Copies made before this stay as they were, and age out of the 30 kept. To open a downloaded `.age` copy yourself, get the key and use the `age` tool: Open an encrypted copy: ```sh ox backups key > backup.key age -d -i backup.key daily-20261007T030512Z.dump.age > daily-20261007T030512Z.dump ``` Settings has the same key under **Backup key**, behind one click. Showing it is written to the audit log. Keep a copy of the key somewhere other than ox: it is the only way to read your bucket if ox is gone. Before migrate backups are kept on your server only; they are not sent to S3. Unless you add an S3 bucket, every backup is on the same server as the app, so losing the server loses them too. [What ox backs up, and how to leave](https://console.t57.sorv.dev/docs/operate/leaving) says where each copy lives, what pauses when ox is down, and how to take everything with you. ## Run a database backup now In the dashboard, open the project's **Backups** tab and press **Back up now** on the service. From a terminal, name the service entry as it is in ox.toml: Back up now: ```sh ox backups shop now postgres --wait ``` Without `--wait`, it prints `Started backups on shop: run ` and the command to read its log. ## List and download backups The Backups tab lists each backup with its time, size and kind, and a **Download** button. From a terminal: List and download: ```sh ox backups shop ox backups shop download postgres backup:daily-20261007T030512Z.dump ``` The SOURCE column of the list is what the other commands take: - `backup:` is a backup on your server. - `s3:` is a copy in your S3 bucket. - `trash: