3 min read

Ghost GCP Installer and Updater Scripts Now Support Ghost v6

TL;DR: This lets technically savvy users self-host Ghost v6 on GCP for free, with straightforward backups and updates.

I’ve updated my Ghost updater script to fully support migrating from Ghost 5 to Ghost 6, for instances installed with the companion Ghost Google Cloud installer — which has also been updated for v6 compatibility.

The new release streamlines configuration, improves SSH handling, and ensures Node.js version selection matches Ghost’s requirements. It will backup and update your instance, and you can continue using it for future Ghost updates.

GitHub - danielraffel/gCloud-Ghost-Updater: A user-friendly script designed to reduce downtime while updating a Ghost instance hosted on Google Cloud.
A user-friendly script designed to reduce downtime while updating a Ghost instance hosted on Google Cloud. - danielraffel/gCloud-Ghost-Updater

While running my own upgrade, I also discovered a few changes were needed for both my nginx config and my Ghost config. I’ve documented these below. They require manual edits and are not included in the update script.

Note: I've only lightly tested this on macOS.


1. Script Enhancements

  • .env overrides file
    • Added support for .env overrides with sensible defaults.
    • Environment variables now control key parameters.
  • Node.js version selection
    • Prefers engines.node (major) from current/package.json if available.
    • Falls back to the Ghost-supported major from the helper script if not.
  • SSH improvements
    • SSH_KEY_PATH is optional — if it doesn’t exist, SSH falls back to your agent/default identities.
    • All SSH/SCP calls now consistently use ${SSH_USER} and $SSH_IDENTITY_OPTS.
  • New environment variables
    • SSH_USERSSH_KEY_PATHLOCAL_NODE_VERSION_SCRIPTRESOURCE_POLICY_NAME
    • SPEEDY_MACHINE_TYPENORMAL_MACHINE_TYPE
    • SSH_CONNECT_TIMEOUTSSH_MAX_ATTEMPTSSSH_RETRY_SLEEP

2. Nginx Configuration Changes

While upgrading, I could not access the new Network tab so I had to manually update my /etc/nginx/sites-available/ configs for ActivityPub and federation endpoints. These need to be applied in both SSL and non-SSL server blocks.

Non-SSL Example

# ActivityPub proxy (HTTP)
location ~ ^/\.ghost/activitypub/ {
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header Host              $host;
    add_header X-Content-Type-Options  nosniff;
    proxy_ssl_server_name on;
    proxy_pass https://ap.ghost.org;
}

# Well-known federation endpoints
location ~ ^/\.well-known/(webfinger|nodeinfo)$ {
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header Host              $host;
    add_header X-Content-Type-Options  nosniff;
    proxy_ssl_server_name on;
    proxy_pass https://ap.ghost.org;
}

SSL Example

# ActivityPub endpoints (proxy to Ghost AP service)
location ~ ^/\.ghost/activitypub/ {
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header Host              $host;
    add_header X-Content-Type-Options  nosniff;
    proxy_ssl_server_name on;
    proxy_pass https://ap.ghost.org;
}

# Well-known federation endpoints
location ~ ^/\.well-known/(webfinger|nodeinfo)$ {
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header Host              $host;
    add_header X-Content-Type-Options  nosniff;
    proxy_ssl_server_name on;
    proxy_pass https://ap.ghost.org;
}

3. Temporary Ghost Config Fix

During the upgrade, I discovered my install didn’t have an email service configured — which blocked staff login. As a temporary workaround, I disabled staff device verification in config.production.json:

"security": {
  "staffDeviceVerification": false
}

Note: This is not a long-term solution. The proper fix is to configure a working mail service.