This guide walks through moving an existing glitch-soc instance from one server to another with minimal data loss. Expect some downtime during the migration window.
Note: This guide assumes Ubuntu 24.04 or Debian 13 on both machines. Adjust commands as needed for other setups.
At a high level, the process is:
- Prepare the new server (install dependencies, set up services)
- Stop glitch-soc on the old server
- Transfer the database, media files, config, and Redis data
- Start glitch-soc on the new server
- Rebuild feeds and search indices
- Cut over DNS
A day before migrating, set your domain's DNS TTL to 30–60 minutes. This ensures DNS propagates quickly once you point it to the new server's IP.
Optionally, edit ~/live/public/500.html on the old server to show a maintenance message to users during the migration window.
Set up the new server from scratch, but do not run mastodon:setup and only leave the PostgreSQL service running at the end. Follow the steps below.
apt install -y curl wget gnupg lsb-release ca-certificatesNode.js:
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.listPostgreSQL:
wget -O /usr/share/keyrings/postgresql.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/keyrings/postgresql.asc] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/postgresql.listapt update
apt install -y \
imagemagick ffmpeg libvips-tools libpq-dev libxslt1-dev file git \
protobuf-compiler pkg-config autoconf bison build-essential \
libssl-dev libyaml-dev libreadline-dev zlib1g-dev libffi-dev \
libgdbm-dev nginx nodejs redis-server postgresql certbot \
python3-certbot-nginx libidn-dev libicu-dev libjemalloc-devEnable Yarn via corepack:
corepack enableadduser --disabled-password mastodonOptional performance tuning: Use pgTune to generate a config for /etc/postgresql/18/main/postgresql.conf, selecting "Web application" as the DB type.
Create the database user. If your old server used a password for the mastodon PostgreSQL user, set the same password here for convenience:
sudo -u postgres psql
ALTER USER mastodon WITH PASSWORD 'YOUR_PASSWORD';
\qThen create an empty database using template0 (required for a clean pg_restore):
createdb -T template0 mastodon_productionSwitch to the mastodon user:
su - mastodonClone the glitch-soc repository:
git clone https://github.com/glitch-soc/mastodon.git live && cd live
git checkout maingit clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv installbundle config deployment 'true'
bundle config without 'development test'
bundle install
yarn installNote: Do not run
mastodon:setup. The database and config will come from the old server.
Switch back to root:
exitBefore copying the Redis data over, make sure Redis is not running on the new machine so it doesn't overwrite the incoming dump:
systemctl stop redis-server.serviceOn the old server, stop all glitch-soc services:
systemctl stop 'mastodon-*.service'Critical — the migration will not work without these:
- PostgreSQL database dump
~/live/public/system/— user-uploaded media (skip if using S3)~/live/.env.production— server config and secrets- Redis database at
/var/lib/redis/— unprocessed Sidekiq jobs
Recommended — copy for convenience:
- nginx config:
/etc/nginx/sites-available/mastodon - systemd service files:
/etc/systemd/system/mastodon-*.service - SSL certificates (see the Certbot section below)
- PgBouncer config:
/etc/pgbouncer(if applicable)
Note:
pg_dumpandpg_restorecan take hours for large databases (e.g. a ~15GB dump). Consider temporarily tuning Postgres performance before starting.
On the old server, as the mastodon user:
pg_dump -Fc mastodon_production -f backup.dumpCopy the dump to the new server:
rsync -avz backup.dump mastodon@example.com:~/backup.dumpOn the new server, as the mastodon user, restore the dump (replace # in -j# with your CPU count):
pg_restore -Fc -j# -U mastodon -n public --no-owner --role=mastodon \
-d mastodon_production backup.dumpIf the PostgreSQL username differs between servers, update both
-Uand--roleto match the new server's username.
On the old server, as the mastodon user:
rsync -avz ~/live/public/system/ mastodon@example.com:~/live/public/system/Re-run this command if any files change on the old server before DNS is cut over.
rsync -avz ~/live/.env.production mastodon@example.com:~/live/.env.productionOn the old server, as root, save and stop Redis, then copy the data:
redis-cli SAVE
systemctl stop redis-server.service
rsync -avz /var/lib/redis/ root@example.com:/var/lib/redisDo not copy the entire /etc/letsencrypt/live/ folder — Certbot will complain when you later try to renew. Instead, copy only the certificate files referenced by ssl_certificate and ssl_certificate_key in your nginx config to a temporary directory on the new server, and update the nginx config paths to match. Re-running Certbot later will overwrite them cleanly:
certbot certonly --nginx -d example.comCopy the nginx config from the Mastodon repo or from your old server:
cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon
ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon
rm /etc/nginx/sites-enabled/defaultEdit /etc/nginx/sites-available/mastodon:
- Replace
example.comwith your domain - Uncomment the SSL certificate lines:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;Allow nginx to access asset files:
chmod o+x /home/mastodonAs the mastodon user:
cd ~/live
RAILS_ENV=production bundle exec rails assets:precompileNote: glitch-soc ships with two front-end flavours, so this step takes more time and resources than on mainline Mastodon.
Switch back to root when done:
exitCopy the service files (or reuse those from your old server):
cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/Verify usernames and paths are correct:
$EDITOR /etc/systemd/system/mastodon-*.serviceStart everything:
systemctl daemon-reload
systemctl start redis-server
systemctl enable --now mastodon-web mastodon-sidekiq mastodon-streaming
systemctl restart nginxThis can take a long time depending on the number of users:
RAILS_ENV=production ./bin/tootctl feeds buildSkip this if you don't use Elasticsearch:
RAILS_ENV=production ./bin/tootctl search deployPoint your domain's DNS records to the new server's IP address. You can monitor propagation progress at whatsmydns.net. To test the new server before DNS fully propagates, edit your local /etc/hosts to point your domain to the new IP.
- DNS TTL lowered a day in advance
- Maintenance page shown on old server
- New server fully provisioned (no
mastodon:setuprun) - PostgreSQL dumped and restored
- Media files synced
-
.env.productioncopied - Redis database copied
- nginx configured and SSL in place
- Assets precompiled
- systemd services started
- Home feeds rebuilt
- Elasticsearch indices rebuilt (if applicable)
- DNS updated