Files
ghost-docker/scripts/migrate.sh
James Loh 4251163b73 Add script to migrate existing Ghost config
- Ghost requires env variables to be in a special `__` format which is hard to construct manually
- This script automates that for ease of migration
- Currently doesn't meet our ESLint rules in the slightest so will need tweaking
2025-06-27 18:04:50 +10:00

148 lines
4.6 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# Check we're running as root
if [[ "$EUID" -ne 0 ]]
then
echo "Sorry, this script must be run as root!"
exit 1
fi
echo "WARNING: This script is currently in beta, please ensure you have a backup of your current installation!"
read -rp 'Are you sure you want to continue? (y/n): ' confirm
if [[ "x${confirm}" != "xy" ]]
then
echo "Aborting..."
exit 1
fi
# Check if we have jq installed
if [[ ! $(which jq) ]]
then
echo "jq is not installed, please install it first"
exit 1
fi
# Prompt for current installation location
read -rp 'Current installation location: ' current_location
if [[ -z "$current_location" ]]
then
echo "Current installation location is required"
exit 1
fi
# Start some safety checks
# Check whether we can find a Ghost-CLI installation
if [[ ! -f "${current_location}/.ghost-cli" ]]
then
echo "Could not find a Ghost-CLI installation at ${current_location}"
exit 1
fi
# Check whether we can find a Ghost installation
if [[ ! -d "${current_location}/content" ]]
then
echo "Could not find a Ghost installation at ${current_location}"
exit 1
fi
if [[ ! -f "${PWD}/.env" ]]
then
echo "Ensure you have a .env file setup for the new installation before continuing"
exit 1
fi
read -rp 'MySQL user to export the current database (must have permission to run mysqldump - defaults to root): ' mysql_user
mysql_user=${mysql_user:-root}
# Stop current installation
read -rp 'This script is about to stop the current installation whilst it migrates to the new installation. Are you sure you want to continue? [y/n]: ' confirm
if [[ "x${confirm}" != "xy" ]]
then
echo "Aborting..."
exit 1
fi
systemctl stop "ghost_$(jq -r < "${current_location}/.ghost-cli" '.name')"
systemctl disable "ghost_$(jq -r < "${current_location}/.ghost-cli" '.name')"
# Create new installation directory
# TODO: Ensure this is safe?
mkdir -p "${PWD}/data/ghost/"
# Copy current installations content dir
rsync -qHPva "${current_location}/content/" "${PWD}/data/ghost/"
echo "Fixing user permissions..."
chown -R 1000:1000 "${PWD}/data/ghost/"
# Starting MySQL container to import the database
docker compose up db -d
# Dump MySQL database to data dir so we can import it
echo "This script is about to dump the MySQL database, please enter the MySQL password for ${mysql_user} when prompted"
mysqldump -u "${mysql_user}" -p --host="$(jq -r < "${current_location}"/config.production.json '.database.connection.host')" "$(jq -r < "${current_location}"/config.production.json '.database.connection.database')" > "$PWD"/data/ghost_import.sql
# We do this _after_ the dump since the user will likely take time to input their password anyway
# Wait for MySQL container to be ready
echo "Waiting for new MySQL container to be ready..."
timeout=120
counter=0
until [ "$(docker compose ps db --format json | jq -r '.Health')" = "healthy" ] || [ $counter -eq $timeout ]; do
echo -n "."
sleep 1
((counter++)) || true
done
if [[ $counter -eq $timeout ]]; then
echo " Timed out waiting for MySQL to be ready, quitting..."
exit 1
fi
echo " MySQL is ready!"
echo "Importing database..."
docker compose exec -T db sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" $MYSQL_DATABASE' < "${PWD}/data/ghost_import.sql"
echo "The migrator will now try and import your existing configuration: "
# Run the config-to-env.js script
node "${PWD}/scripts/config-to-env.js" "${current_location}/config.production.json"
read -rp 'Are you happy with the configuration? [y/n]: ' confirm
case "$confirm" in
[yY][eE][sS]|[yY])
echo "Adding configuration to .env..."
node "${PWD}/scripts/config-to-env.js" "${current_location}/config.production.json" >> "${PWD}/.env"
;;
*)
echo "Skipping, you can manually add the configuration to .env later"
echo "Note: Mail configuration is not imported, if you send email you will need to set it up manually"
;;
esac
# Starting Ghost container
echo "Starting Ghost..."
docker compose up ghost -d
read -rp 'Would you like to start Caddy? This will stop your existing Nginx installation. [y/n]: ' confirm
case "$confirm" in
[yY][eE][sS]|[yY])
echo "Stopping Nginx..."
systemctl stop nginx
systemctl disable nginx
echo "Starting Caddy..."
docker compose up caddy -d
echo "Caddy is now running, you can access your site at https://$(grep 'DOMAIN' "${PWD}/.env" | cut -d '=' -f 2)"
;;
*)
echo "Ghost is now running inside Docker, you will need to expose it to the internet manually."
exit 0
;;
esac