Publish with Ghost
Self-hosted Ghost
Ghost’s supported self-hosted stack puts Nginx in front of Ghost. Serve the declaration from Nginx before the request reaches Ghost.
A participant affirming Josh identity:
{
"version": 1,
"josh": true
}
josh may instead be false for Declined Josh Identity, or omitted for Undeclared Josh Identity. The implementation guide defines those three declarations. Do not invent other values.
Exact-path Nginx example:
location = /.well-known/josh {
default_type application/json;
return 200 '{"version":1,"josh":true}';
}
That block:
- responds only to the exact protocol path
- returns
200 OK - sets
Content-Type: application/json - needs no Ghost theme customization
- needs no client-side JavaScript
- leaves ordinary Ghost requests unchanged
Another reverse proxy can do the same exact-path behavior. This recipe does not include unverified snippets for other servers.
Why not routes.yaml
Ghost dynamic routing in routes.yaml maps URLs to Ghost templates and data. Trailing slashes are required for dynamic routing to function correctly, and Ghost automatically forces trailing slashes. RFC-JOSH-0002 defines /.well-known/josh with no trailing slash.
A custom route can set content_type (including JSON), but that route still follows Ghost’s trailing-slash rules. It cannot publish the exact extensionless, no-trailing-slash protocol path.
This recipe therefore handles the resource at the HTTP server or reverse-proxy layer, not through a Ghost theme or routes.yaml. Ghost can still participate in the Joshternet when the hosting layer exposes the protocol path.
Ghost(Pro)
Ordinary Ghost(Pro), without a controllable reverse proxy, is not documented here as a supported recipe today. Ghost Admin, themes, and routes.yaml are not a way to publish the exact /.well-known/josh resource on plain Ghost(Pro).
Ghost documents reverse-proxy setups for Ghost(Pro)—including Nginx, Apache, Cloudflare, CloudFront, Netlify, and Vercel—as subdirectory and proxy setups that are a paid add-on for the Business plan. See Using Ghost(Pro) with a subdirectory for Ghost’s proxy requirements.
A Ghost(Pro) publication already running behind a supported reverse proxy can participate when that proxy:
- responds directly to
/.well-known/josh - returns the version 1 JSON declaration with
Content-Type: application/json - proxies ordinary Ghost traffic according to Ghost’s documented proxy rules
Do not paste Ghost’s full reverse-proxy configuration here—follow Ghost’s current help for the Ghost-specific headers and path rules, and add the exact-path declaration response on the same proxy.
Check the deployed URL
Check the live origin with Check a declaration.
Or check the live URL directly:
curl -i https://example.invalid/.well-known/josh
Confirm all of the following:
200 OKContent-Type: application/json- a valid JSON body
- the expected version 1 declaration
- the extensionless path
/.well-known/josh - no redirect to a different origin
/.well-known/josh/is not treated as a substitute for the canonical resource