Published 2026-04-22 by TechNet New England
Uptime Kuma v2 is a major upgrade that includes a database migration for all historical monitoring data. If that migration gets interrupted for any reason, the application gets stuck in a loop showing "Migration is in progress" and refusing to start. This guide covers how to update safely, what to back up, how to recover from a stuck migration, and a reusable backup script. ## Before You Start: What You Need - SSH access to the server running Uptime Kuma - Node.js 20.4 or newer (check with `node -v`) - PM2 process manager (the standard way to run Uptime Kuma in production) - Enough disk space for a full backup of the data directory ## Step 1: Back Up Everything Do not skip this. The v1 to v2 migration modifies your database structure. If something goes wrong, you need to be able to roll back. ### Quick manual backup ```bash cd /opt/uptime-kuma cp -a data data.pre-v2-backup-$(date +%F-%H%M) ``` Replace `/opt/uptime-kuma` with your actual install path throughout this guide. Common locations include `/opt/uptime-kuma`, `/home/youruser/uptime-kuma`, or wherever you cloned the repository. ### Verify the backup exists ```bash ls -lh data.pre-v2-backup-* ``` You should see a copy of the entire data directory including `kuma.db`, `kuma.db-wal`, `kuma.db-shm`, the `screenshots` folder, and the `upload` folder. ## Step 2: Update Uptime Kuma ### Stop the running instance ```bash pm2 stop uptime-kuma ``` ### Pull the latest version ```bash cd /opt/uptime-kuma git fetch --all --tags git checkout 2.2.1 --force ``` Replace `2.2.1` with whatever the latest stable tag is at the time of your update. ### Clean install dependencies ```bash rm -rf node_modules package-lock.json npm install --omit=dev --no-audit npm run download-dist ``` Removing `node_modules` and `package-lock.json` before reinstalling prevents stale dependency issues that can cause silent failures. ## Step 3: Start the Migration Manually This is the most important part. Do NOT use PM2 for the initial v2 startup. Run the server directly so you can watch the migration in real time: ```bash cd /opt/uptime-kuma node server/server.js ``` You should see output like: ``` Connected to the database [DON'T STOP] Migrating monitor data - 2025-10-28 - total migration progress 0.21% [DON'T STOP] Migrating monitor data - 2025-10-29 - total migration progress 0.25% [DON'T STOP] Migrating monitor data - 2025-10-30 - total migration progress 0.30% ``` **Do not interrupt this process.** Do not close the terminal. Do not restart PM2. Do not press Ctrl+C. The migration processes your entire monitoring history day by day, and for a large database it can take anywhere from a few minutes to over an hour. The browser will show "Migration is in progress" during this time. That is normal. When the migration completes, the logs will show the server finishing its startup and the browser will show the login page or dashboard. ## Step 4: Move Back to PM2 Once the migration is complete and the UI loads normally, stop the manual process with Ctrl+C and register it in PM2: ```bash cd /opt/uptime-kuma pm2 start server/server.js --name uptime-kuma --cwd /opt/uptime-kuma pm2 save pm2 status ``` Confirm it shows as "online" and check the logs: ```bash pm2 logs uptime-kuma --lines 50 ``` ## What Goes Wrong: The Stuck Migration If the migration gets interrupted (terminal closed, server rebooted, PM2 restarted the process, Ctrl+C pressed), you will see this in the logs: ``` [DB] WARN: Aggregate table migration is already in progress, or it was interrupted [DB] ERROR: Database migration failed [SERVER] ERROR: Failed to prepare your database: Aggregate table migration is already in progress ``` The application will keep restarting and showing this same error in a loop. PM2 will show the process as "online" but the migration never completes. The browser shows the "Migration is in progress" page forever. ### Why this happens Uptime Kuma sets a flag in the database when it starts the aggregate table migration. If the process dies before the migration finishes, that flag stays set. On the next startup, Kuma sees the flag and refuses to continue because it does not know whether the database is in a consistent state. ### How to fix it #### Option A: Restore from backup and retry (recommended) This is the safest path. If you made a backup before the update: ```bash pm2 stop uptime-kuma # Remove the failed data directory rm -rf /opt/uptime-kuma/data # Restore the pre-upgrade backup cp -a /opt/uptime-kuma/data.pre-v2-backup-YYYY-MM-DD-HHMM /opt/uptime-kuma/data # Start manually again (not PM2) cd /opt/uptime-kuma node server/server.js ``` Watch the migration complete without interrupting it this time. #### Option B: Clear the migration lock (if no backup available) If you do not have a pre-upgrade backup, you can try clearing the migration state. First, stop Uptime Kuma and back up the current database: ```bash pm2 stop uptime-kuma cd /opt/uptime-kuma cp data/kuma.db data/kuma.db.before-lock-clear ``` Check what migration state exists: ```bash sqlite3 data/kuma.db "SELECT * FROM knex_migrations_lock;" sqlite3 data/kuma.db "SELECT name, value FROM setting WHERE name LIKE '%aggregate%' OR name LIKE '%migrat%';" ``` If `knex_migrations_lock` shows `is_locked = 1`, unlock it: ```bash sqlite3 data/kuma.db "UPDATE knex_migrations_lock SET is_locked = 0;" ``` If there is a migration flag in the `setting` table, clear it based on what you find. Then remove any file-based lock if it exists: ```bash rm -f data/migration.lock ``` Restart manually: ```bash cd /opt/uptime-kuma node server/server.js ``` Watch the logs. If the migration picks up where it left off, let it finish. If it errors again with data integrity issues, you may need to restore from a backup or start with a fresh database. ## Common Pitfalls ### Permission denied on backup commands If you run: ```bash cp data/kuma.db data/kuma.db.bak ``` And get "Permission denied," the data directory is owned by a different user. Use `sudo` or switch to the correct user: ```bash ls -la data/ sudo cp data/kuma.db data/kuma.db.bak ``` ### Running commands from the wrong directory If `npm install` fails with: ``` ENOENT: no such file or directory, open '/home/youruser/package.json' ``` You are not in the Uptime Kuma directory. Make sure you `cd` into the install folder first. Find it with: ```bash pm2 show uptime-kuma ``` Look for the `cwd` or `script path` value. ### Mixed root and user ownership If you ran some commands as root (`sudo su`) and others as your normal user, file ownership can get mixed up. After the update is complete, fix it: ```bash sudo chown -R youruser:youruser /opt/uptime-kuma ``` Replace `youruser` with the account that normally runs Uptime Kuma. Mixed ownership causes future updates and backups to fail with permission errors. ### Using tilde (~) as root If you use `sudo su` and then reference `~/uptime-kuma`, the tilde expands to `/root/uptime-kuma` instead of `/home/youruser/uptime-kuma`. Always use full paths when running as root. ### PM2 shows "online" but nothing works PM2 will show the process as "online" even if the application is stuck in a migration loop. Always check the actual logs: ```bash pm2 logs uptime-kuma --lines 100 ``` If you see the "Aggregate table migration" error repeating, the process is not actually running. It is starting, failing, and restarting in a loop. ### Docker Compose version If you are using an older Docker installation and get errors with `docker compose`, try `docker-compose` (with a hyphen) instead. This applies to the Docker-based install method, not the git/PM2 method covered in this guide. ## Reusable Backup Script Save this as `/usr/local/bin/uptime-kuma-backup.sh` to run before updates or on a nightly schedule: ```bash #!/usr/bin/env bash set -Eeuo pipefail KUMA_DIR="/opt/uptime-kuma" BACKUP_ROOT="/var/backups/uptime-kuma" DATESTAMP="$(date +%F-%H%M%S)" RETENTION_DAYS=14 RUN_DIR="${BACKUP_ROOT}/${DATESTAMP}" mkdir -p "${RUN_DIR}" echo "[$(date)] Starting Uptime Kuma backup" # Back up the entire data directory if [[ -d "${KUMA_DIR}/data" ]]; then tar -czf "${RUN_DIR}/kuma-data.tar.gz" -C "${KUMA_DIR}" data echo "[$(date)] Data directory backed up" else echo "[$(date)] ERROR: Data directory not found at ${KUMA_DIR}/data" exit 1 fi # Generate checksum (cd "${RUN_DIR}" && sha256sum ./* > SHA256SUMS.txt) # Clean up old backups find "${BACKUP_ROOT}" -mindepth 1 -maxdepth 1 -type d -mtime +"${RETENTION_DAYS}" -exec rm -rf {} + echo "[$(date)] Backup complete: ${RUN_DIR}" ``` Install and schedule it: ```bash sudo chmod 700 /usr/local/bin/uptime-kuma-backup.sh sudo mkdir -p /var/backups/uptime-kuma # Run manually before an update sudo /usr/local/bin/uptime-kuma-backup.sh # Schedule nightly at 3 AM sudo crontab -e # Add: 0 3 * * * /usr/local/bin/uptime-kuma-backup.sh >/dev/null 2>&1 ``` ## Full Update Checklist ```bash # 1. Back up sudo /usr/local/bin/uptime-kuma-backup.sh # 2. Stop pm2 stop uptime-kuma # 3. Update cd /opt/uptime-kuma git fetch --all --tags git checkout 2.2.1 --force rm -rf node_modules package-lock.json npm install --omit=dev --no-audit npm run download-dist # 4. Start manually and watch migration node server/server.js # Wait for migration to complete. Do not interrupt. # 5. After UI loads, Ctrl+C and move to PM2 pm2 start server/server.js --name uptime-kuma --cwd /opt/uptime-kuma pm2 save # 6. Verify pm2 status pm2 logs uptime-kuma --lines 50 # 7. Fix ownership if you used sudo sudo chown -R youruser:youruser /opt/uptime-kuma ``` ## Key Takeaways - Always back up the entire data directory before updating. The database, WAL file, and SHM file are all part of the state. - Run the v2 migration manually with `node server/server.js` so you can watch it. Do not let PM2 manage the first startup. - Do not interrupt the migration. It processes historical data day by day and can take a long time on large databases. - If the migration gets stuck, restore from backup and retry. That is the supported recovery path. - Fix file ownership after any commands run as root. Mixed ownership breaks future updates. - PM2 showing "online" does not mean the app is healthy. Always check the logs. --- *Need help managing Uptime Kuma or other self-hosted monitoring tools? [Contact TechNet New England](/contact) for expert support.*