# Postgres Migration :warning: Public Document :warning: ### State of The World - pgbouncer is not running anywhere #### freud - no sidekiqs (confirmed) - `postgresql.service` running - `/etc/cron.daily/pg_archive_cleanup.sh` dead #### neitzsche - `postgresql.service` running (replica) #### fritz - `mastodon-web.service` running - `mastodon-streaming.service` running - `mastodon-sidekiq-mailers.service` running - `mastodon-sidekiq-default@{1,2}` running - `mastodon-sidekiq-pull@1` running - `mastodon-sidekiq-push@1` running #### cdn-fremont-1 - no sidekiqs (confirmed) #### cdn-frankfurt-1 - sidekiq server - `mastodon-sidekiq@1.service` running - `mastodon-sidekiq-pushpull@1.service` running #### slappy - no sidekiqs (confirmed) #### esme - no sidekiqs (confirmed) #### franz - `mastodon-sidekiq-scheduler.service` running - `mastodon-sidekiq-default@{1..6}.service` running - `mastodon-sidekiq-ingress@{1..3}.service` running - `mastodon-sidekiq-pull@{1..5}.service` running - `mastodon-sidekiq-push@{1..5}.service` running # Migration Steps ## Fritz: Stop processes that generate jobs (web, streaming) ```shell ssh novix@fritz.hachyderm.io sudo systemctl stop \ mastodon-web.service \ mastodon-streaming.service ``` Wait for queues to be zero: https://hachyderm.io/sidekiq/queues ## All: Stop sidekiqs First, stop the scheduler ```shell ssh novix@franz.hachyderm.io sudo systemctl stop \ mastodon-sidekiq-scheduler.service ``` Then the rest ```shell ssh novix@fritz.hachyderm.io sudo systemctl stop \ mastodon-sidekiq-mailers.service \ mastodon-sidekiq-default@{1,2} \ mastodon-sidekiq-{push,pull}@1 ``` ```shell ssh novix@cdn-frankfurt-1.hachyderm.io sudo systemctl stop \ mastodon-sidekiq{,-pushpull}@1.service ``` ```shell ssh novix@franz.hachyderm.io sudo systemctl stop \ mastodon-sidekiq-default@{1..6}.service \ mastodon-sidekiq-ingress@{1..3}.service \ mastodon-sidekiq-{pull,push}@{1..5}.service ``` ## Nietzsche: Check replication delay ```shell ssh novix@nietzsche.hachyderm.io watch -n1 'sudo -u postgres psql -c "select now()-pg_last_xact_replay_timestamp() as replication_lag;"' ``` ## (Freud, Nietzsche): Stop postgres ```shell ssh novix@freud.hachyderm.io sudo systemctl stop postgresql sleep 4 # randomly chosen by fair dice roll ssh novix@nietzsche.hachyderm.io sudo systemctl stop postgresql ``` ## Nietzsche: Configure as main ```shell ssh novix@nietzsche.hachyderm.io sudo rm /var/lib/postgres/data/standby.signal ssh novix@nietzsche.hachyderm.io sudo sed -i 's/^primary_conninfo/#primary_conninfo/' /var/lib/postgres/data/postgresql.conf ssh novix@nietzsche.hachyderm.io sudo sed -i 's/^hot_standby/#hot_standby/' /var/lib/postgres/data/postgresql.conf ssh novix@nietzsche.hachyderm.io sudo systemctl start postgresql ``` ## Freud: Configure as replica ```shell ssh novix@freud.hachyderm.io sudo touch /var/lib/postgres/data/standby.signal ssh novix@freud.hachyderm.io sudo sed -i -e 's/^#primary_conninfo/primary_conninfo/' -e '/^primary_conninfo/s/alice/nietzsche/' /var/lib/postgres/data/postgresql.conf ssh novix@freud.hachyderm.io sudo sed -i 's/^#hot_standby/hot_standby/' /var/lib/postgres/data/postgresql.conf ssh novix@freud.hachyderm.io sudo systemctl start postgresql ``` ## Freud: Check replication delay ```shell ssh novix@freud.hachyderm.io watch -n1 'sudo -u postgres psql -c "select now()-pg_last_xact_replay_timestamp() as replication_lag;"' ``` ## All: Modify client configs to connect to Nietzsche ```shell for server in fritz cdn-frankfurt-1 franz; do ssh novix@$server.hachyderm.io sudo sed -i 's/DB_HOST=freud/DB_HOST=nietzsche/' /etc/mastodon.conf done ``` ## All: Start all clients First, start the scheduler sidekiq ```shell ssh novix@franz.hachyderm.io sudo systemctl start \ mastodon-sidekiq-scheduler.service ``` Then the rest ```shell ssh novix@fritz.hachyderm.io sudo systemctl start \ mastodon-sidekiq-mailers.service \ mastodon-sidekiq-default@{1,2} \ mastodon-sidekiq-{push,pull}@1 ``` ```shell ssh novix@cdn-frankfurt-1.hachyderm.io sudo systemctl start \ mastodon-sidekiq{,-pushpull}@1.service ``` ```shell ssh novix@franz.hachyderm.io sudo systemctl start \ mastodon-sidekiq-default@{1..6}.service \ mastodon-sidekiq-ingress@{1..3}.service \ mastodon-sidekiq-{pull,push}@{1..5}.service ``` Then start the web and streaming ```shell ssh novix@fritz.hachyderm.io sudo systemctl start \ mastodon-web.service \ mastodon-streaming.service ``` # Follow Up Tasks - [x] Install mastodon on freud - [x] Copy mastodon.conf to freud - [x] Move sidekiq from `cdn-frankfurt-1` -> `freud` - [x] `mastodon-sidekiq{,-pushpull}@1.service` - [ ] Move sidekiq from `fritz` -> `freud` - [X] `mastodon-sidekiq-mailers.service` - [X] `mastodon-sidekiq-default@{1,2}` - [X] `mastodon-sidekiq-pull@1` - [X] `mastodon-sidekiq-push@1` - [X] Start sidekiq extras on `freud` - [ ] 2 more ingress queues - [ ] 3 more default queues - [X] Clean up systemd sidekiqs on cdn-frankfurt-1 and fritz - [ ] Copy media/images/mailer/icon_email.png from fritz to freud --- ``` # cdn-frankfurt-1: # /etc/systemd/system/mastodon-sidekiq-pushpull@.service [Unit] Description=mastodon-sidekiq (%i) After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/var/lib/mastodon Environment="RAILS_ENV=production" Environment="DB_POOL=10" Environment="MALLOC_ARENA_MAX=2" Environment="LD_PRELOAD=libjemalloc.so" ExecStart=/usr/bin/bundle exec sidekiq -c 10 -q pull -q push TimeoutSec=15 Restart=always # Proc filesystem ProcSubset=pid ProtectProc=invisible # Capabilities CapabilityBoundingSet= # Security NoNewPrivileges=true # Sandboxing ProtectSystem=strict PrivateTmp=true PrivateDevices=true PrivateUsers=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectControlGroups=true RestrictAddressFamilies=AF_INET RestrictAddressFamilies=AF_INET6 RestrictAddressFamilies=AF_NETLINK RestrictAddressFamilies=AF_UNIX RestrictNamespaces=true LockPersonality=true RestrictRealtime=true RestrictSUIDSGID=true RemoveIPC=true PrivateMounts=true ProtectClock=true # System Call Filtering SystemCallArchitectures=native SystemCallFilter=~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid SystemCallFilter=@chown SystemCallFilter=pipe SystemCallFilter=pipe2 ReadWritePaths=/var/lib/mastodon [Install] WantedBy=multi-user.target ``` ``` # fritz # /etc/systemd/system/mastodon-sidekiq-mailers.service [Unit] Description=mastodon-sidekiq After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/var/lib/mastodon Environment="RAILS_ENV=production" Environment="DB_POOL=1" Environment="MALLOC_ARENA_MAX=2" Environment="LD_PRELOAD=libjemalloc.so" ExecStart=/usr/bin/bundle exec sidekiq -c 1 -q mailers TimeoutSec=15 Restart=always # Proc filesystem ProcSubset=pid ProtectProc=invisible # Capabilities CapabilityBoundingSet= # Security NoNewPrivileges=true # Sandboxing ProtectSystem=strict PrivateTmp=true PrivateDevices=true PrivateUsers=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectControlGroups=true RestrictAddressFamilies=AF_INET RestrictAddressFamilies=AF_INET6 RestrictAddressFamilies=AF_NETLINK RestrictAddressFamilies=AF_UNIX RestrictNamespaces=true LockPersonality=true RestrictRealtime=true RestrictSUIDSGID=true RemoveIPC=true PrivateMounts=true ProtectClock=true # System Call Filtering SystemCallArchitectures=native SystemCallFilter=~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid SystemCallFilter=@chown SystemCallFilter=pipe SystemCallFilter=pipe2 ReadWritePaths=/var/lib/mastodon [Install] WantedBy=multi-user.target ``` ``` # fritz # /etc/systemd/system/mastodon-sidekiq-default@.service [Unit] Description=mastodon-sidekiq default (%i) After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/var/lib/mastodon Environment="RAILS_ENV=production" Environment="DB_POOL=10" Environment="MALLOC_ARENA_MAX=2" Environment="LD_PRELOAD=libjemalloc.so" ExecStart=/usr/bin/bundle exec sidekiq -c 10 -q default TimeoutSec=15 Restart=always # Proc filesystem ProcSubset=pid ProtectProc=invisible # Capabilities CapabilityBoundingSet= # Security NoNewPrivileges=true # Sandboxing ProtectSystem=strict PrivateTmp=true PrivateDevices=true PrivateUsers=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectControlGroups=true RestrictAddressFamilies=AF_INET RestrictAddressFamilies=AF_INET6 RestrictAddressFamilies=AF_NETLINK RestrictAddressFamilies=AF_UNIX RestrictNamespaces=true LockPersonality=true RestrictRealtime=true RestrictSUIDSGID=true RemoveIPC=true PrivateMounts=true ProtectClock=true # System Call Filtering SystemCallArchitectures=native SystemCallFilter=~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid SystemCallFilter=@chown SystemCallFilter=pipe SystemCallFilter=pipe2 ReadWritePaths=/var/lib/mastodon [Install] WantedBy=multi-user.target ``` ``` # fritz # /etc/systemd/system/mastodon-sidekiq-push@.service [Unit] Description=mastodon-sidekiq push (%i) After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/var/lib/mastodon Environment="RAILS_ENV=production" Environment="DB_POOL=10" Environment="MALLOC_ARENA_MAX=2" Environment="LD_PRELOAD=libjemalloc.so" ExecStart=/usr/bin/bundle exec sidekiq -c 10 -q push TimeoutSec=15 Restart=always # Proc filesystem ProcSubset=pid ProtectProc=invisible # Capabilities CapabilityBoundingSet= # Security NoNewPrivileges=true # Sandboxing ProtectSystem=strict PrivateTmp=true PrivateDevices=true PrivateUsers=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectControlGroups=true RestrictAddressFamilies=AF_INET RestrictAddressFamilies=AF_INET6 RestrictAddressFamilies=AF_NETLINK RestrictAddressFamilies=AF_UNIX RestrictNamespaces=true LockPersonality=true RestrictRealtime=true RestrictSUIDSGID=true RemoveIPC=true PrivateMounts=true ProtectClock=true # System Call Filtering SystemCallArchitectures=native SystemCallFilter=~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid SystemCallFilter=@chown SystemCallFilter=pipe SystemCallFilter=pipe2 ReadWritePaths=/var/lib/mastodon [Install] WantedBy=multi-user.target ``` ``` # fritz # /etc/systemd/system/mastodon-sidekiq-pull@.service [Unit] Description=mastodon-sidekiq pull (%i) After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/var/lib/mastodon Environment="RAILS_ENV=production" Environment="DB_POOL=10" Environment="MALLOC_ARENA_MAX=2" Environment="LD_PRELOAD=libjemalloc.so" ExecStart=/usr/bin/bundle exec sidekiq -c 10 -q pull TimeoutSec=15 Restart=always # Proc filesystem ProcSubset=pid ProtectProc=invisible # Capabilities CapabilityBoundingSet= # Security NoNewPrivileges=true # Sandboxing ProtectSystem=strict PrivateTmp=true PrivateDevices=true PrivateUsers=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectControlGroups=true RestrictAddressFamilies=AF_INET RestrictAddressFamilies=AF_INET6 RestrictAddressFamilies=AF_NETLINK RestrictAddressFamilies=AF_UNIX RestrictNamespaces=true LockPersonality=true RestrictRealtime=true RestrictSUIDSGID=true RemoveIPC=true PrivateMounts=true ProtectClock=true # System Call Filtering SystemCallArchitectures=native SystemCallFilter=~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid SystemCallFilter=@chown SystemCallFilter=pipe SystemCallFilter=pipe2 ReadWritePaths=/var/lib/mastodon [Install] WantedBy=multi-user.target ``` ``` # franz # /etc/systemd/system/mastodon-sidekiq-ingress@.service [Unit] Description=mastodon-sidekiq After=network.target [Service] Type=simple User=mastodon WorkingDirectory=/var/lib/mastodon Environment="RAILS_ENV=production" Environment="DB_POOL=20" Environment="MALLOC_ARENA_MAX=2" Environment="LD_PRELOAD=libjemalloc.so" ExecStart=/usr/bin/bundle exec sidekiq -c 20 -q ingress TimeoutSec=15 Restart=always # Proc filesystem ProcSubset=pid ProtectProc=invisible # Capabilities CapabilityBoundingSet= # Security NoNewPrivileges=true # Sandboxing ProtectSystem=strict PrivateTmp=true PrivateDevices=true PrivateUsers=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectControlGroups=true RestrictAddressFamilies=AF_INET RestrictAddressFamilies=AF_INET6 RestrictAddressFamilies=AF_NETLINK RestrictAddressFamilies=AF_UNIX RestrictNamespaces=true LockPersonality=true RestrictRealtime=true RestrictSUIDSGID=true RemoveIPC=true PrivateMounts=true ProtectClock=true # System Call Filtering SystemCallArchitectures=native SystemCallFilter=~@cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid SystemCallFilter=@chown SystemCallFilter=pipe SystemCallFilter=pipe2 ReadWritePaths=/var/lib/mastodon ReadWritePaths=/mnt/mastodon-storage [Install] WantedBy=multi-user.target ``` # Resulting State of the World #### Nietzsche - Postgres primary - 4X Ingress queues - 4X Default queues #### Freud - Postgres secondary - 3X Ingress queues - 3X Default queues - 1X Mailers queues - 2X Pull queues - 2X Push queues #### Fritz - 1X Mastodon Web - 1X Mastodon Streaming #### Franz - 1X Schedulers - 6X Default queues - 3X Ingress queues - 5X Pull queues - 5X Push queues