Migrating Pangolin to Another Host
Why this is easier than it sounds
You can move Pangolin to a new server without re-adding a single site. Almost everything Pangolin knows lives in one folder called config. Move that folder carefully, point your domain at the new server, and your sites reconnect on their own.
The one thing that trips people up is file permissions. I'll show you how to avoid that.
But why would you want to move?
I simply migrated for a better price model. Digital Ocean is fantastic and I enjoy their platform quite a bit, but I found that racknerd provided more resources for much cheaper per month. It lacks some of the advanced features and backup that Digital Ocean provides, but I'm working on adjusting my own backups to solve that issue.
Before you start
You need four things:
- Your old server, still running Pangolin, and a way to log in to it (like SSH).
- A new server with Docker and Docker Compose installed. A fresh Ubuntu or Debian VPS is fine. Be sure to follow my other blog on installing docker compose if you're running into issues!
- Access to your DNS settings, wherever your domain is managed (Cloudflare, your registrar, etc.).
- About an hour, and a quiet time when a few minutes of downtime won't bother anyone.
Your Newt sites (the little agents running in your homelab) don't need any changes, as long as you keep the same domain.
The steps
In the commands below, ~/pangolin is the folder that holds your docker-compose.yml and config folder. Swap in your own path, and swap you@new-server for your new server's login.
Step 1: Lower your DNS TTL (the day before)
TTL is how long the internet remembers where your domain points. In your DNS settings, set it to 5 minutes (300 seconds) on your Pangolin records. Do this a day early so the change has time to spread. Then, on moving day, the switch to the new server takes minutes instead of hours.
Step 2: Get the new server ready
Install Docker and Docker Compose. Then open these ports in the new server's firewall (and in your VPS provider's firewall, if it has one):
- 80 and 443 (TCP): normal web traffic
- 51820 and 21820 (UDP): the tunnels your sites connect through
Check the ports: section of your docker-compose.yml to confirm these match your setup.
Step 3: Stop Pangolin on the old server
cd ~/pangolin
sudo docker compose downStopping it first means nothing changes while you copy it. Your sites go offline from here until Step 9. Keep that in mind.
Step 4: Pack everything into one file
Every file on Linux carries a little label saying who's allowed to read it. Pangolin's certificate file, acme.json, is picky: only its owner may read it. If that label changes during the move, Traefik refuses to use the file and your HTTPS breaks.
So don't copy files one by one. Pack them into a single archive that keeps the labels:
cd ~
sudo tar -cpzf pangolin-backup.tar.gz pangolinThe p in -cpzf is the important part. It means "preserve permissions." This is necessary for your acme.json permissions, which will fail on the new host if permissions aren't intact.
Step 5: Copy the archive to the new server
scp pangolin-backup.tar.gz you@new-server:~Step 6: Unpack it on the new server
cd ~
sudo tar -xpzf pangolin-backup.tar.gzUse sudo here too. Without it, tar quietly resets the labels, which is exactly what we're trying to avoid.
The rsync way: Steps 4 to 6 in one command
rsync copies a folder straight from one server to another, so there's no archive to pack and unpack. It's faster, but the command looks scary. Here it is, then piece by piece.
First, install it on both servers:
sudo apt install rsyncThen, on the old server:
sudo rsync -a --numeric-ids -e "ssh -i /home/you/.ssh/id_ed25519" ~/pangolin/ root@new-server:/home/you/pangolin/
Piece | What it means |
|---|---|
| Run as the admin, so rsync can read |
| "Archive mode": copy every subfolder and keep permissions, owners and dates. This is the part that protects |
| Keep file owners by their number, not their name. User names can differ between servers; the numbers are what Docker cares about |
| Use your SSH key. Without this, |
| What to copy. The slash at the end means "the stuff inside this folder" |
| Where to put it. Logging in as |
Do a practice run first. Add -n ("pretend") and -v ("tell me what you're doing"). rsync lists what it would copy without copying anything:
sudo rsync -anv --numeric-ids -e "ssh -i /home/you/.ssh/id_ed25519" ~/pangolin/ root@new-server:/home/you/pangolin/If the list looks right, run it again without -n.
Can't log in as root on the new server? Many VPSes block it. Use your normal user and tell rsync to use sudo on the far side instead: swap root@new-server for you@new-server and add --rsync-path="sudo rsync". For this to work, your user must be able to run sudo on the new server without typing a password.
Common rsync errors
Error | What it means | Fix |
|---|---|---|
|
| Add the |
| rsync isn't installed on the other server |
|
|
| Log in as |
Files land in | No slash at the end of the source folder | Use |
|
| Run Step 7's |
In all honesty, I had Claude Code help me out a bit on the rsync piece. I'm learning as I go, too.
Step 7: Double-check the certificate file
ls -l ~/pangolin/config/letsencrypt/acme.jsonThe line should start with -rw-------. If it doesn't, fix it:
sudo chmod 600 ~/pangolin/config/letsencrypt/acme.jsonStep 8: Point your domain at the new server
In your DNS settings, change your Pangolin records to the new server's IP address. That's usually your dashboard record (like pangolin.example.com) and the wildcard record (*.example.com) that your services use.
Step 9: Start Pangolin on the new server
cd ~/pangolin
sudo docker compose up -d
sudo docker compose psAll the containers (pangolin, gerbil, traefik) should say "running" or "healthy." Give your sites a minute or two to find the new server.
Step 10: Check it all works
- Log in to the Pangolin dashboard.
- Look at your sites. They should show as online.
- Open one of your services in a browser and check for the padlock.
- Once you're happy, set your DNS TTL back to normal.
Keep the old server around for a week before you delete it, just in case.
If something goes wrong
What you see | Likely cause | Fix |
|---|---|---|
Certificate warning in the browser |
| Redo Step 7, then |
Sites stay offline | DNS still points at the old server, or the UDP ports are blocked | Wait for DNS to update, then check the firewall from Step 2 |
Dashboard won't load | DNS hasn't switched yet | Wait a few minutes; check with |
Containers keep restarting | Files unpacked without | Unpack again with Step 6, exactly as written |
Changed your mind? Stop Pangolin on the new server, point DNS back at the old server's IP, and run sudo docker compose up -d on the old one. Nothing there was touched, so it picks up right where it left off.