mirror of
https://github.com/d0zingcat/ghost-docker.git
synced 2026-05-13 15:09:34 +00:00
Improved MySQL migration system
no ref - Currently we prompt a user for a username to dump their Ghost database with which can be confusing if users can't remember their database details - The Ghost user _likely_ has the required permissions to dump the database itself so we can first try that without prompting the user and _then_ prompt them if it doesn't work - We added `--no-tablespaces` to the dump command to try and reduce the likelyhood of hitting users not having the `PROCESS` permission since most hosted DBs don't let this and Ghost's DB setup doesn't require DBs be dumped with that anyway
This commit is contained in:
@@ -52,10 +52,17 @@ cleanup() {
|
||||
|
||||
if [[ $exit_code -ne 0 && -f "$RECOVERY_SCRIPT" ]]; then
|
||||
echo ""
|
||||
echo "ERROR: Migration failed!"
|
||||
echo "════════════════════════════════════════════════════════════"
|
||||
echo "❌ MIGRATION FAILED!"
|
||||
echo "════════════════════════════════════════════════════════════"
|
||||
echo ""
|
||||
echo "Don't worry - your data is safe!"
|
||||
echo ""
|
||||
echo "To restore your original Ghost installation, run:"
|
||||
echo " bash $RECOVERY_SCRIPT"
|
||||
echo ""
|
||||
echo "Need help? Check the migration logs above for error details."
|
||||
echo "════════════════════════════════════════════════════════════"
|
||||
fi
|
||||
|
||||
exit $exit_code
|
||||
@@ -66,6 +73,7 @@ trap cleanup EXIT INT TERM
|
||||
|
||||
# Create recovery script
|
||||
create_recovery_script() {
|
||||
local service_name="$1"
|
||||
cat > "$RECOVERY_SCRIPT" << EOF
|
||||
#!/usr/bin/env bash
|
||||
# Recovery script generated by Ghost migration on $(date)
|
||||
@@ -79,15 +87,19 @@ echo "Restoring original Ghost installation..."
|
||||
docker compose down 2>/dev/null || true
|
||||
|
||||
# Re-enable and start the original Ghost service
|
||||
systemctl enable "${ghost_service_name}"
|
||||
systemctl start "${ghost_service_name}"
|
||||
|
||||
echo "Original Ghost installation has been restored."
|
||||
echo "You can check the status with: systemctl status ${ghost_service_name}"
|
||||
if [[ -n "${service_name}" ]]; then
|
||||
systemctl enable "${service_name}" 2>/dev/null || true
|
||||
systemctl start "${service_name}" 2>/dev/null || true
|
||||
echo "Original Ghost installation has been restored."
|
||||
echo "You can check the status with: systemctl status ${service_name}"
|
||||
else
|
||||
echo "Note: Ghost service was not yet stopped, so no restoration needed."
|
||||
echo "Your original installation should still be running."
|
||||
fi
|
||||
EOF
|
||||
|
||||
chmod +x "$RECOVERY_SCRIPT"
|
||||
echo "Recovery script created at: $RECOVERY_SCRIPT"
|
||||
echo "✓ Recovery script created at: $RECOVERY_SCRIPT"
|
||||
}
|
||||
|
||||
# Validate MySQL connection
|
||||
@@ -188,6 +200,21 @@ migrate_content() {
|
||||
echo "✓ Content migration completed"
|
||||
}
|
||||
|
||||
# Test if we can dump database with given credentials
|
||||
test_mysql_dump() {
|
||||
local host=$1
|
||||
local database=$2
|
||||
local user=$3
|
||||
local password=$4
|
||||
|
||||
# Try a minimal dump to test permissions
|
||||
if mysqldump --no-tablespaces --no-data -h"$host" -u"$user" -p"$password" "$database" >/dev/null 2>&1; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Export and import database
|
||||
migrate_database() {
|
||||
local mysql_host
|
||||
@@ -197,9 +224,38 @@ migrate_database() {
|
||||
|
||||
echo "Exporting database from $mysql_host..."
|
||||
|
||||
# Export database
|
||||
if ! mysqldump -h"$mysql_host" -u"$mysql_user" -p"$mysql_password" "$mysql_database" > "$TEMP_SQL_FILE"; then
|
||||
# Export database with proper error handling
|
||||
local dump_output
|
||||
local dump_status
|
||||
dump_output=$(mysqldump --no-tablespaces -h"$mysql_host" -u"$mysql_user" -p"$mysql_password" "$mysql_database" 2>&1 > "$TEMP_SQL_FILE")
|
||||
dump_status=$?
|
||||
|
||||
# Check for errors in output (mysqldump may return 0 even with some errors)
|
||||
if [[ $dump_status -ne 0 ]] || [[ "$dump_output" =~ "Error:" ]]; then
|
||||
echo ""
|
||||
echo "ERROR: Failed to export database"
|
||||
if [[ "$dump_output" =~ "PROCESS privilege" ]]; then
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "The MySQL user '$mysql_user' needs the PROCESS privilege."
|
||||
echo ""
|
||||
echo "To fix this, connect to MySQL as a privileged user and run:"
|
||||
echo " GRANT PROCESS ON *.* TO '$mysql_user'@'%';"
|
||||
echo " FLUSH PRIVILEGES;"
|
||||
echo ""
|
||||
echo "Or retry with a user that has sufficient privileges (e.g., root)."
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
elif [[ -n "$dump_output" ]]; then
|
||||
echo "Error details: $dump_output"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify the dump file exists and has content
|
||||
if [[ ! -f "$TEMP_SQL_FILE" ]] || [[ ! -s "$TEMP_SQL_FILE" ]]; then
|
||||
echo ""
|
||||
echo "ERROR: Database dump file is empty or missing"
|
||||
echo "This might indicate insufficient disk space or permissions issues."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -286,8 +342,12 @@ main() {
|
||||
# Get database configuration
|
||||
local mysql_host
|
||||
local mysql_database
|
||||
local ghost_mysql_user
|
||||
local ghost_mysql_password
|
||||
mysql_host=$(jq -r < "${current_location}/config.production.json" '.database.connection.host')
|
||||
mysql_database=$(jq -r < "${current_location}/config.production.json" '.database.connection.database')
|
||||
ghost_mysql_user=$(jq -r < "${current_location}/config.production.json" '.database.connection.user')
|
||||
ghost_mysql_password=$(jq -r < "${current_location}/config.production.json" '.database.connection.password')
|
||||
|
||||
# Check disk space
|
||||
echo ""
|
||||
@@ -321,23 +381,52 @@ main() {
|
||||
echo "✓ Disk space check passed"
|
||||
echo ""
|
||||
|
||||
# Get MySQL credentials and validate
|
||||
read -rp "MySQL user for database export (default: root): " mysql_user
|
||||
mysql_user=${mysql_user:-root}
|
||||
# Try Ghost's own credentials first
|
||||
echo "Testing database export with Ghost's credentials..."
|
||||
if test_mysql_dump "$mysql_host" "$mysql_database" "$ghost_mysql_user" "$ghost_mysql_password"; then
|
||||
echo "✓ Ghost's credentials have sufficient privileges"
|
||||
mysql_user="$ghost_mysql_user"
|
||||
mysql_password="$ghost_mysql_password"
|
||||
else
|
||||
echo "Ghost's database user doesn't have sufficient privileges for export."
|
||||
echo "Please provide credentials for a MySQL user with dump privileges."
|
||||
echo ""
|
||||
|
||||
# Get password securely
|
||||
echo -n "MySQL password for ${mysql_user}: "
|
||||
read -rs mysql_password
|
||||
echo ""
|
||||
# Get MySQL credentials and validate
|
||||
read -rp "MySQL user for database export (default: root): " mysql_user
|
||||
mysql_user=${mysql_user:-root}
|
||||
|
||||
# Validate connection
|
||||
if ! validate_mysql_connection "$mysql_host" "$mysql_database" "$mysql_user" "$mysql_password"; then
|
||||
echo "Please check your MySQL credentials and try again."
|
||||
exit 1
|
||||
# Get password securely
|
||||
echo -n "MySQL password for ${mysql_user}: "
|
||||
read -rs mysql_password
|
||||
echo ""
|
||||
|
||||
# Validate connection
|
||||
if ! validate_mysql_connection "$mysql_host" "$mysql_database" "$mysql_user" "$mysql_password"; then
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Could not connect to MySQL database."
|
||||
echo ""
|
||||
echo "Please verify:"
|
||||
echo " • MySQL service is running"
|
||||
echo " • Credentials are correct"
|
||||
echo " • User has access from this host"
|
||||
echo " • Database name is correct"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test dump permissions
|
||||
if ! test_mysql_dump "$mysql_host" "$mysql_database" "$mysql_user" "$mysql_password"; then
|
||||
echo ""
|
||||
echo "ERROR: The provided user doesn't have sufficient privileges for database export."
|
||||
echo "Please ensure the user has the necessary privileges or try a different user."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create recovery script
|
||||
create_recovery_script
|
||||
# Create recovery script (with empty service name since we haven't stopped anything yet)
|
||||
create_recovery_script ""
|
||||
|
||||
# Final confirmation before stopping Ghost
|
||||
echo ""
|
||||
@@ -365,8 +454,17 @@ main() {
|
||||
# Stop Ghost service
|
||||
echo ""
|
||||
echo "Stopping Ghost service..."
|
||||
systemctl stop "$ghost_service_name"
|
||||
systemctl disable "$ghost_service_name"
|
||||
|
||||
# Update recovery script with actual service name before stopping
|
||||
create_recovery_script "$ghost_service_name"
|
||||
|
||||
if ! systemctl stop "$ghost_service_name"; then
|
||||
echo "ERROR: Failed to stop Ghost service"
|
||||
echo "Please check: systemctl status $ghost_service_name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
systemctl disable "$ghost_service_name" 2>/dev/null || true
|
||||
echo "✓ Ghost service stopped"
|
||||
|
||||
# Migrate content
|
||||
|
||||
Reference in New Issue
Block a user