This bash script helps automate the update process for Ghost running on a VM in Google Cloud. It was inspired by Amazon rolling deployment and designed because the author is running a micro instance which is very resource limited. It creates a machine image backup, starts a new VM, updates Ghost to the latest version, and offers to reassign your external IP. The script includes native macOS notifications to keep you informed of progress and important decisions so you can run in the background without forgetting about it.
This release is built for Ghost v6 and supports updating from a v5 installation previously set up with an earlier version of this script. If you’re still using Ghost v5 and prefer not to upgrade v6, use the v5-compatible version instead.
Although not required, this script is compatible with httpPing and RestartVMService to facilitate restarting your VM if the URL it's hosting appears to be offline.
- Client side:
- Google Cloud CLI
- jq
- curl
- expect
- ssh-keygen
- ssh-keyscan
- macOS (for notifications)
- Server side:
- Ghost v5 or v6 with Ghost CLI
- Ubuntu 22.04 on Google Cloud
- Setup an SSH key for your service account (with access to the private key on your client machine running the script)
- Added your service account SSH key to your VM
- Checks for client side pre-requisites
- Lists your Google Cloud VMs if you have more than one
- Precheck (default): SSH to the current VM, compare its Ghost version to the latest release, and exit early if already up-to-date (configurable via
AUTO_PRECHECK
) - Creates a machine image backup
- Starts a new VM named after the latest Ghost release
- Temporarily stops Ghost to free up RAM, updates packages, and reboots
- Determines and sets the correct Node.js major version:
- Prefers the
engines.node
incurrent/package.json
- Falls back to the latest Node major supported by the latest Ghost release
- Safely handles cross-major upgrade path (v5 → v6)
- Prefers the
- Updates Ghost and restarts it
- Offers to reassign your static IP to the new VM
- Provides notifications throughout the process


- Standard update:
./update.sh
- Shows progress notifications
- Interactive prompts for key decisions
- Final notification with VM IPs
- Fast update:
./update.sh speedy
- Temporarily upgrades VM for faster updates
- Auto-downgrades after completion
- Test notifications:
./update.sh test-notification
- Verifies notification system works
- Debug mode:
./update.sh debug
- For troubleshooting version checks
- Precheck only:
./update.sh precheck
- Exits 0 if up-to-date, 1 if update available, 2 if check skipped/failed
- Force update:
./update.sh force
- Skips the default precheck and proceeds
- Backup only:
./update.sh backup
(alias:image-backup
)- Creates a machine image of the current VM and exits (does not create a new VM, no updater run)
- Shows a confirmation dialog on success/failure
Note: Only a single positional mode argument is supported at a time. To combine behaviors, use environment flags. Example to run speedy without precheck:
AUTO_PRECHECK=false ./update.sh speedy
Copy .env.example
to .env
and personalize the values. All variables are optional; sensible defaults are used if omitted.
SSH_USER
: SSH username (default:service_account
)SSH_KEY_PATH
: Path to SSH private key. If missing, SSH falls back to your agent/default identities (default:$HOME/.ssh/gcp
)LOCAL_NODE_VERSION_SCRIPT
: Path toget_latest_node_version.js
(default: repo path)RESOURCE_POLICY_NAME
: Disk snapshot policy attached to new VM (default:daily-backup-schedule
)SPEEDY_MACHINE_TYPE
: Temporary machine type for fast updates (default:e2-medium
)NORMAL_MACHINE_TYPE
: Machine type to downgrade back to (default:e2-micro
)SSH_CONNECT_TIMEOUT
: Seconds per SSH probe (default:10
)SSH_MAX_ATTEMPTS
: Max SSH readiness attempts (default:36
)SSH_RETRY_SLEEP
: Seconds between SSH attempts (default:5
)AUTO_PRECHECK
: Run the version precheck at script start (default:true
)IGNORE_DOTENV
: Iftrue
, ignore.env
and use only shell environment variables
Precedence: the script loads .env
first (unless IGNORE_DOTENV=true
), then any environment variables already set in the shell will override .env
values. Finally, built-in defaults apply for anything unset.
- When up-to-date, precheck shows an OK dialog with the current/latest version and exits:
- Example: “Current: 6.0.1, Latest: 6.0.1. Already up-to-date. Nothing to update.”
- Backup-only mode shows an OK dialog indicating success or failure with the created machine image name.
- Run Ghost backup (instead, this creates a machine image)
- Delete old VMs or Machine Images
- Support multi-server setups with load balancers
- Make it easy to run only certain commands with parameters
- Enable running without interactive prompts
- Cron for auto-update checks
- Offer to cleanup machine image backups and terminated VMs
- Offer to setup service_account SSH keys
The script was written quickly and has not been tested by anyone else or on a non macOS device. While I took precautions to generalize the script and avoid data loss I'd advise that you still use it at your own risk.