Migrating Servers
To migrate an installation of Site Wrangler and the websites installed on it to a new instance, follow this guide. This guide assumes you are using Deban Linux. Substitute your distribution’s installation commands where applicable.
THIS GUIDE ASSUMES YOU ARE MOVING TO AN EMPTY SERVER! THE COMMANDS HERE MAY OVERWRITE IMPORTANT DATA IF YOU MIGRATE DATA TO A SYSTEM WITH SITE DATA ALREADY ON IT!
Set Up the New Server
The first step is to create a new instance of Site Wrangler on a fresh server if you have not already done so. Follow the guide here to set up the new server, but skip the section called “First Build” since we will migrate the list of compiled packages from the old server.
Next take a look over your Site Wrangler settings on both servers to check for inconsistencies. The most common settings to change are enable_php_legacy_versions
, enable_php_super_legacy_versions
, enable_php_prerelease_version
, and email_admin_on_build_success
.
Set up the new server to have SSH access to the old server using the root user of each. Once that is complete, you may want to add your new server’s IP address to the old servers /etc/csf/csf.ignore
file.
Initialize Variables
The rest of this guide assumes you have set the following variables in your terminal. If your terminal session is ended, make sure you set these again after reconnecting to your server.
The first variable is target, which is set to the old server’s IP address.
target="127.0.0.1"
Install Webhosting Stack
Use the following command to install all the packages installed on the old server onto the new server.
ssh $target 'cat /opt/sitewrangler/etc/enabled-packages' | xargs sw build install
Setup System Users
Next, let’s create the Linux users on the new server and authorize them to access the old server via SSH. Again, we are using the old server’s IP in place of 127.0.0.1.
for username in `ssh $target 'sw user list'`; do sw user add "$username"; key=`su - "$username" -c 'mkdir -p ~/.ssh; if [ ! -f ~/.ssh/id_rsa ]; then ssh-keygen -N "" -f ~/.ssh/id_rsa >/dev/null; fi; cat ~/.ssh/id_rsa.pub'`; ssh $target "su - '$username' -c \"mkdir -p ~/.ssh/; echo '$key' >> ~/.ssh/authorized_keys\" "; su - "$username" -c "ssh -o StrictHostKeyChecking=accept-new '$target' 'whoami'";echo "Authorized: $username"; done
Certificates
Next, we’ll transfer the certificates along with the renewal configurations
dir="/etc/letsencrypt/live"; mkdir -p "$dir"; scp "$target":"$dir/*" "$dir/"; dir="/etc/letsencrypt/renewal"; mkdir -p "$dir"; scp "$target":"$dir/*" "$dir/"; dir="/etc/letsencrypt/archive"; mkdir -p "$dir"; rsync -az "$target":"$dir/" "$dir"
Nginx
First, lets copy custom nginx templates (if any) from the old server. You can skip this command if you are sure that there are no custom templates on the old server.
dir="/opt/sitewrangler/etc/nginx-templates/custom"; mkdir -p "$dir"; scp "$target":"$dir/*" "$dir/"
Now is a good time to make sure that the old server does not have any custom tweaks to the configuration files directly in the directory /usr/local/nginx/conf
and copy over and needed modifications.
Now lets copy the nginx templates from the old server.
dir="/usr/local/nginx/conf/vhosts"; scp "$target":"$dir/*" "$dir/"
dir="/opt/sitewrangler/etc/modsec/sites/"; scp "$target":"$dir/*" "$dir/"
Then have the new server rebuild all the nginx templates with the new local settings.
for domain in `ls /usr/local/nginx/conf/vhosts/*.conf|sed 's/\.conf$//'|cut -c 30-`; do sw nginx retemplate "$domain"; done
PHP Sites
We can transfer all the PHP configuration files from the old server with this command:
for dir in `ls -d /opt/php-*/`; do scp "$target":"${dir}etc/php-fpm.d/*" "${dir}etc/php-fpm.d/"; done
Email Domains and Users
First, we need to transfer the association of domain names to Linux usernames.
domain_file=`sw setting get mail_domain_file`; scp "$target":"$domain_file" "domain_file"
Now we need to transfer the user accounts.
shadow=`sw setting get mail_shadow_file`; scp "$target":"$shadow" "$shadow"
Now we need to update the shadow file to use the correct group and user IDs.
/opt/sitewrangler/bin/repairUserIds.sh
Now let’s transfer SpamAssassin training data.
ssh $target 'sa-learn --backup' > sa-backup
sa-learn --restore=sa-backup
Don’t forget to migrate any changes you may have made to /etc/spamassassin/local.cf
Site and Email Files
Now we need to transfer the website/email files
for username in `sw user list`;do echo "Syncing $username"; su - "$username" -c "rsync -az --exclude '.ssh' --exclude 'php-fpm.sock' $target:\$HOME/ \$HOME;"; done
Database Content
Now we need to transfer the database content
list=$(for database in `ssh $target 'sw db list'`; do echo -n " '$database'"; done); ssh $target "mysqldump --databases $list 2>/dev/null" | mysql
Next we can copy over the database users
ssh $target "mysqldump mysql --tables user db 2>/dev/null" | grep '^INSERT' | mysql mysql
Lastly, we will copy over the database privileges
ssh $target "mysql -B --disable-column-names --execute 'SELECT CONCAT(QUOTE(User), \"@\", QUOTE(Host)) FROM mysql.db WHERE User<>\"root\"' 2>/dev/null | while read user; do output=\$(mysql -B --disable-column-names --execute \"SHOW GRANTS FOR \$user;\" | sed -e 's/^.*IDENTIFIED/ IDENTIFIED/' -e 's/ALL PRIVILEGES/ALL/'); cleaned=\$(echo -n \"\$output\" | grep -E '^GRANT (ALL|SELECT)'; echo -n \"\$output\" | grep 'IDENTIFIED BY'); echo -n \"\$cleaned\" | tr '\\n' ' '; echo ';'; done" | mysql
DNS
First, lets make sure the new server has a folder for DNS zones by making a zone file and then deleting it
sw dns add example.com; sw dns remove example.com
Now lets copy the zone files over
scp "$target":/etc/bind/zones/* /etc/bind/zones/
sw dns reindex
The next thing to do is to change your nameservers glue records to point to the new server’s IP.
Now that DNS server is up and running, test each site before you change it’s IP address to the new server in the nameserver.
Here is a dirty and simple way to update the data in a zone file to your new information. Beware of IP addresses that may match each other when searched, like searching for 127.0.0.1 can match 127.0.0.11.
$domain="example.com"
sed -i -e 's/127\.0\.0\.1/127.0.0.2/' -e 's/2600::b16b/2600::98c2/' /etc/bind/zones/$domain.db
sw dns soa $domain
Enabling Nginx Proxy
While updating the DNS for each site, we can have one server proxy to the other. This will allow sites that have dynamic content like comments to minimize downtime.
Make sure your site files are up-to-date on the new server, re-syncing as needed. Then change your old server to point to the new server by proxy. On the old server run this command:
sw nginx add example.com example_linux_user
Select php-ssl, then enter the IP address of the new server, and leave the port set to 443.
If you are setting up all or most of the domains the old server to proxy to it’s replacement, it may be cumbersome to enter the IP over and over. To set the default value to the new server’s IP address, run these commands:
cp /opt/sitewrangler/etc/nginx-templates/proxy-ssl /opt/sitewrangler/etc/nginx-templates/custom/
nano /opt/sitewrangler/etc/nginx-templates/custom/proxy-ssl
Then change the IP address on the line with PROXYIPP
. Don’t forget to delete this custom template if the old server is going keep running after your transfers are complete.
End Notes
Here are some other commands that may be useful
(Re)Syncing a WordPress site database and files, followed by setting up the old server to proxy:
username="linux_user"
domain="example.com"
su - "$username" -c "rsync -az --delete --exclude '.ssh' --exclude 'php-fpm.sock' $target:\$HOME/ \$HOME; cd \$HOME/public_html/; ssh $target 'cd public_html/; wp db dump -' | wp db import -"
You can re-sync the email messages under a user by running this command:
username="linux_user"
su - "$username" -c "rsync -azv --delete $target:\$HOME/mail/ \$HOME/mail;"