---
title: "How to migrate Uptime Kuma to a different Machine"
url: https://bee.whoisjason.me/blogposts/cmljt2atw0004mhrohp1o31a4
author: Jason
published: 2026-02-12
reading_time_minutes: 3
word_count: 683
---
# How to migrate Uptime Kuma to a different Machine

In this guide I will attempt to explain how I was able to migrate my entire Uptime Kuma back end MariaDB to a new host machine. This serves as the alterative in version 2 since the Backup/Restore function has been depricated.

## [#](https://next.whoisjason.me/apps/notes/note/3057?new#h-setup-information)Setup Information:

To add some context so you can gauge how similar our setups are, here is my docker-compose.yml file

```yaml
services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    restart: unless-stopped
    volumes:
      - /uptime-kuma/data:/app/data
    ports:
      # <Host Port>:<Container Port>
      - "3009:3001"
```

You can see here that the only important detail is **/uptime-kuma/data/**

So we need to backup /uptime-kuma/data/ and restore it onto the new machine  
  

## Backup Script

To back up this directory I used a BASH script to backup the MariaDB within the /data directory and drop the backup inside /uptime-kuma/backups  

```bash
#!/bin/bash
# Uptime Kuma Backup Script
# Performs a live SQL dump of the embedded MariaDB database
# Schedule via cron: 0 2 * * * root /usr/local/bin/backup-uptimekuma.sh >> /var/log/uptimekuma-backup.log 2>&1

BACKUP_DIR="/uptime-kuma/backups"
RETENTION_DAYS=30
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
CONTAINER="uptime-kuma-uptime-kuma-1"

mkdir -p "$BACKUP_DIR"

# Verify container is running
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then
    echo "$(date) ERROR: Container $CONTAINER is not running. Backup skipped."
    exit 1
fi

# Dump via the running container's MariaDB socket
docker exec "$CONTAINER" \
  mariadb-dump --skip-lock-tables -S /app/data/run/mariadb.sock kuma \
  | gzip > "$BACKUP_DIR/kuma-$TIMESTAMP.sql.gz"

# Verify backup isn't empty or truncated
if [ ! -s "$BACKUP_DIR/kuma-$TIMESTAMP.sql.gz" ]; then
    echo "$(date) ERROR: Backup file is empty!"
    exit 1
fi

LAST_LINE=$(zcat "$BACKUP_DIR/kuma-$TIMESTAMP.sql.gz" | tail -1)
if [ "$LAST_LINE" != "-- Dump completed" ]; then
    echo "$(date) WARNING: Backup may be incomplete! Last line: $LAST_LINE"
fi

# Grab config files
cp /uptime-kuma/data/db-config.json "$BACKUP_DIR/db-config-$TIMESTAMP.json" 2>/dev/null
cp /uptime-kuma/compose.yaml "$BACKUP_DIR/compose-$TIMESTAMP.yaml" 2>/dev/null

# Prune old backups
find "$BACKUP_DIR" -name "kuma-*.sql.gz" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "db-config-*.json" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "compose-*.yaml" -mtime +$RETENTION_DAYS -delete

FILESIZE=$(du -h "$BACKUP_DIR/kuma-$TIMESTAMP.sql.gz" | cut -f1)
echo "$(date) Backup complete: kuma-$TIMESTAMP.sql.gz ($FILESIZE)"
```

  
Then I made a cron job out of it, however you just need to run the script once.  
  
btw, to run the script, you run to do  
  
**sudo bash** [**backupscript.sh**](http://backupscript.sh)

### Transferring the backup

I chose to use SFTP however you can do literally whatever you want to move the files over, essentially you will need to copy the files that look like this

> db-config-20260210-133044.json

> kuma-20260210-133044.sql.gz

Notice how the days match, if you were running this as a cron job make sure you pull the .json and .sql from the same day, then just send over your files. On the new host system I chose to use the same directory structure so I created the directories on the new host

```bash
# On the New Host
sudo mkdir -p /uptime-kuma/data
sudo mkdir -p /uptime-kuma/backups
```

You will transfer the files into the /backup directory. DO NOT transfer them into /data immediately unless you hate yourself and your data.

* * *

## Restoring the backup on the new host

I will assume now that your files are transferred into /uptime-kuma/backup on the new host

Also make sure the new host has docker installed

Next, using the same compose file, bring up the container as an empty uptime-kuma instance to allow for database initialization.  

```bash
# on the new host
sudo nano docker-compose.yml 
# paste in the compose CTRL+SHIFT+V
# paste in your compose, CTRL+X + CTRL+Y + ENTER to save 
docker compose up -d 
# wait for database initialisation
you can check the logs with 
docker logs -f uptime-kuma
# if your container is named something different check the name with 'docker ps'
# once that is done, bring down the container
docker stop uptime-kuma
```

Now that the container is shut down, and the database was able to initialize, then we can insert the data. To do that, run these commands

```bash
cp /uptime-kuma/backups/db-config-20260212-020001.json /uptime-kuma/data/db-config.json

docker compose up -d 
```

Once that starts up, it will be time for the big import

```bash
zcat /uptime-kuma/backups/kuma-20260212-020001.sql.gz | \
  docker exec -i uptime-kuma-uptime-kuma-1 \
  mariadb -S /app/data/run/mariadb.sock kuma
```

This command will import the SQL file into the new blank mariaDB, this can take a while depending on how large of a backup you are importing.

Then when that finishes up, restart the container

```bash
docker restart uptime-kuma-1
```

Now you can verify that your data has been 100% transfered
