In a dramatic turn of events, one of our servers was recently decommissioned without warning. It all happened too fast. Before we’ve even said our goodbyes, we’d been assigned a new server, with the old server’s disk temporarily attached to it as a saving grace.
Now this was a development server. So despite my dramatisation of the situation, it wasn’t that critical. It didn’t have any client data, nor did it have any production code. But it did have a bunch of sites with unique configurations and dummy data that allowed us to quickly test new ideas for our product.
So I wasn’t entirely happy with abandoning ship and starting fresh. There had to be a way to restore the valuable sites from the old server!
Let’s 🚀
The Challenge
Restoring the files was a breeze. We had used CWP so creating a new CWP user with the same domain and moving the files into the user’s public_html directory was all it took.
Restoring the DB was tricky though. We didn’t have the luxury of using mysqldump
before the old server was nuked. So all we had was a copy of /var/lib/mysql
which we grabbed during the grace period.
Operation Phoenix
I knew I could boot up a MariaDB container with my old /var/lib/mysql
as a volume map. But I couldn’t fully imagine how I should proceed from there. So out came the checklist:
- Identify the DB version
sudo strings /home/ruban/OldData/var/lib/mysql/ib_logfile0 | grep "MariaDB"# Output: MariaDB 10.6.7
- Create a container of the same version
without mariadb running on startup
docker pull mariadb:10.6.7docker run --name mariadb-container -v /home/ruban/OldData/var/lib/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=TheDragonAdvances -d mariadb:10.6.7 tail -f /dev/null
- Boot up mariadb in safe mode
I forgot the root password (sudoers woe)
docker exec -it mariadb-container bashmysqld_safe --skip-grant-tables &
- Reset the root password
docker exec -it mariadb-container bashmysql -u root
FLUSH PRIVILEGES;SET PASSWORD FOR 'root'@'localhost' = PASSWORD('TheDragonAdvances');FLUSH PRIVILEGES;exit
- Dump them all
I got ChatGPT to churn out a bash script to dump all my DBs in one go as timestamped SQL files.
So still in the container, I did a vi dump-all.sh && chmod u+x dump-all.sh
with the following going into the file:
#!/bin/bashUSER="root"PASSWORD="TheDragonAdvances"databases=`mysql -u $USER -p$PASSWORD -e "SHOW DATABASES;" | tr -d "| " | grep -v Database`timestamp=$(date +%Y%m%d-%H%M%S)for db in $databases; do if [[ "$db" != "information_schema" ]] && [[ "$db" != "performance_schema" ]] && [[ "$db" != "mysql" ]] && [[ "$db" != _* ]] ; then echo "Dumping database: $db" mysqldump -u $USER -p$PASSWORD --databases $db > "/var/lib/mysql/dumps/${db}_$timestamp.sql" fidone
Then I just had to run the script like so:
mkdir /var/lib/mysql/dumps && ./dump-all.sh
- Secure the salvage
docker cp mariadb-container:/var/lib/mysql/dumps /home/ruban/.
- Verify that the operation was a success
CREATE DATABASE ghostwater;CREATE USER 'northstrider'@'localhost' IDENTIFIED BY 'DragonMonarch';GRANT ALL ON ghostwater.* TO 'northstrider'@'localhost';FLUSH PRIVILEGES;
mysql -u root -p ghostwater < /home/ruban/dumps/ghostwater_20240405-133431.sql
And my site works!
Now I can go back to ignoring backup best practices /s