-
-
Notifications
You must be signed in to change notification settings - Fork 112
Migrating a Production Server
The following guide outlines the procedure for migrating an OFN instance to a new server. For a step-by-step checklist see the issue template: https://github.com/openfoodfoundation/ofn-install/issues/new?template=server-migration.md
Note that it is more efficient to migrate without provisioning with the temporary subdomain, but a process for that hasn't been recorded.
Check all the requirements for server (for example system specs, and are any other services running on it?)
Get a new server. Create a uniqe subdomain for it, eg. prod2.openfoodnetwork.com
. The DNS will take a while to propagate, but you can start with just the new IP address.
Add a new entry in your copy of ofn-install in the /inventory/hosts
file, and a new directory in /inventory/host_vars/
for the new server.
In the host_vars
entry for the new server (prod2.openfoodnetwork.com), define the domain variables, and set them like this:
domain: prod2.openfoodnetwork.ca # might be required for testing. remember to change before switchover
host_id: ca-prod2
...
certbot_cert_name: openfoodnetwork.com # Current domain name
certbot_domains:
- openfoodnetwork.com # Current domain FIRST in the list
- www.openfoodnetwork.com # www subdomain, if you use it
- prod2.openfoodnetwork.com # New domain LAST
In the hosts
file, add the new entry alongside the current entry. It helps to make sure both IP addresses are defined with ansible_host
, eg:
[x_prod]
openfoodnetwork.com ansible_host=123.183.204.127
[x_prod2]
prod2.openfoodnetwork.com ansible_host=123.190.252.221
Before provisioning, run the letsencrypt_proxy.yml
playbook on the current production server, and specify proxy_target
with the domain or the IP address of the new server, eg:
ansible-playbook playbooks/letsencrypt_proxy.yml -l x_prod -e "proxy_target=prod2.openfoodnetwork.com"
The above hack (and the earlier config steps) should ensure the new server can successfully create a Letsencrypt certificate during provisioning that will be valid for any of the listed subdomains.
When that's done, and the DNS has propagated for the temporary domain, follow the normal steps for setup
, provision
, and deploy
on the new server. You can refer to the secrets for the existing server, eg:
ansible-playbook site.yml -l x_prod2 -e "@../ofn-secrets/x_prod/secrets.yml"
Important
Subscriptions may start getting processed. Stop and disable the sidekiq service to avoid this.
If you have a lot of data or need to minimise downtime, it's worth setting up an SSH key to allow direct transfer from the old to new server. In short:
For db_transfer:
ofn-admin@x-prod2: ssh-keygen -t ed25519 && cat ~/.ssh/id_ed25519.pub
ofn-admin@x-prod: vim .ssh/authorized_keys
For transfer_assets:
openfoodnetwork@x-prod2: ssh-keygen -t ed25519 && cat ~/.ssh/id_ed25519.pub
openfoodnetwork@x-prod: vim .ssh/authorized_keys
You might need to manually ssh first to ensure it's added to known_hosts
The current server may have custom assets such as instance-specific logos, or PDFs with the instance's Terms and Conditions in a localised language. These are generally located under: /home/openfoodnetwork/apps/openfoodnetwork/shared/
.
If local storage is used instead of S3, a lot of images will be stored under storage
. You will want to copy assets directly to the new server with transfer_assets.yml
, making sure to set up authorised key:
ansible-playbook playbooks/transfer_assets.yml -l x_prod -e "rsync_to=x_prod2"
If you haven't got the authorised key setup, just use the pull_assets.yml
playbook on the current server, then push_assets.yml
on the new server. The assets will show up on the new site when it's deployed again.
ansible-playbook playbooks/pull_assets.yml -l x_prod
ansible-playbook playbooks/push_assets.yml -l x_prod2
It's important to copy the sidekiq redis DB. But keep sidekiq offline for now, to avoid subscriptions being taken etc.
# old server: this file will be dumped when redis-jobs is stopped.
ofn-admin@ca-prod:~$ sudo systemctl stop redis-jobs
ofn-admin@ca-prod:~$ sudo cp /var/lib/redis-jobs/dump.rdb ~/
ofn-admin@ca-prod:~$ sudo chown ofn-admin: ~/dump.rdb
# new server:
ofn-admin@ca-prod2:~$ sudo systemctl stop redis-jobs
ofn-admin@ca-prod2:~$ rsync openfoodnetwork.com:dump.rdb ~/
ofn-admin@ca-prod2:~$ sudo cp ~/dump.rdb /var/lib/redis-jobs/
ofn-admin@ca-prod2:~$ sudo systemctl start redis-jobs
When redis starts, it will automatically load this file.
Ensure sure it has the exact same release as the current server:
ssh [email protected] -C "(cd ~/apps/openfoodnetwork/current && git show)"
# (refer to commit on latest release: https://github.com/openfoodfoundation/openfoodnetwork/releases)
ansible-playbook playbooks/deploy.yml -l x_prod2 -e "git_version=vX.Y.Z"
If the new server is a subdomain of the old one, you may end up with conflicting cookies. In some cases, it will be necessary to open devtools and manually remove the cookies for old prod, just before clicking "login". After logging in, it should work.
Test emails at Admin > Configuration > Mail Methods > Send test email.
Announce some downtime to users, and get ready for the switch. At the scheduled time, follow these steps:
- Put the current server into maintenance mode with the
maintenance_mode
playbook. The default message is in English, but you can specify a custom message like so:-e "maintenance_mode_message='Estamos manteniendo el servidor'
#ansible-playbook playbooks/maintenance_mode.yml -l x_prod
- Stop sidekiq and redis-jobs
sudo systemctl stop sidekiq redis-jobs
- Transfer database and files:
ansible-playbook playbooks/db_transfer.yml -l x_prod -e rsync_to=x_prod2 && ansible-playbook ansible-playbook playbooks/transfer_assets.yml -l x_prod -e "rsync_to=x_prod2"
- Transfer redis-jobs db^
sudo systemctl stop puma postgres
- restart
puma
and startsidekiq
andredis-jobs
on the new server at this point to pick up the newly imported data, like mail configs and site settings. - Run the
temporary_proxy
playbook on the current server, specifying the IP address of the new server with theextra_vars
option, eg:-e 'proxy_target=123.456.7.8'
.
This should not take too long, and after the last step the site will now be back up, with requests to the old server being transparently proxied to the new one.
If it's all working, you can change the DNS of the domain name from the old server's IP to the new server's IP. It can theoretically take up to 48 hours to propagate, but the change will appear instant to users because of the temporary_proxy.yml
playbook.
You can also run the playbooks for asset migration again (push and pull) to pick up any new changes, if the images are hosted on the server. The tasks in the playbook are idempotent and should cleanly update only the changed or missing assets.
After 48 hours you can shut down the old server, and make sure the entries in ofn-install
are up to date: remove the temporary entry made for the migration, and set the new IP address.
Provisioning
Deployment
Sysadmin
External services
- Sending emails from OFN
- Email Deliverability
- SSL certificates
- Google Maps
- File storage
- Backups
- Server monitoring
- Issue reporting (Bugsnag)
Contributing