# Docker Deployment and ActivityPub

**URL:** <https://forum.ghost.org/t/docker-deployment-and-activitypub/59581>\
**Category:** Self-hosting\
**Created:** [August 14, 2025, 11:58am UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581 "2025-08-14T11:58:47Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![lorenzo](https://avatars.discourse-cdn.com/v4/letter/l/4da419/32.png) [@lorenzo](https://forum.ghost.org/u/lorenzo)\
**Post date:** [August 14, 2025, 11:58am UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/1 "2025-08-14T11:58:47Z")

</div>

Hi,

I recently migrated from an old docker set-up to your [official docker deployment](https://docs.ghost.org/install/docker).

So far everything has been fine-ish, and I absolutely applaud you guys for your work on Ghost, it’s simply amazing.

However, I have run into a few issues using your official docker deployment (caddy) when using an admin domain ([dashboard.mywebsite.com](http://dashboard.mywebsite.com)).

1. When previewing a post, I get an error saying connection refused (iframe related)

This is an easy fix as I just added a rule to Caddy that allows this for my admin domain.

1. **ActivityPub in general refuses to work (self hosted or not)**

This is the log:

```auto
ghost-1 | [2025-08-14 11:15:09] ERROR Could not get webhook secret for ActivityPub FetchError: invalid json response body at https://mywebsite.com/.ghost/activitypub/v1/site reason: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
ghost-1 | [2025-08-14 11:15:09] ERROR No webhook secret found - cannot initialise

```

Is the problem that it’s not reaching the admin domain? Or am I mistaken in how this setup works?

I’ve read some of the suggestions on here (editing nginx config file,… not really doable since it’s Caddy).  
Should I edit the caddy ActivityPub snippet to make this work? If so, I’m quite unfamiliar with Caddy, what should it look like?

```Caddyfile
# ActivityPub
# Proxy activitypub requests /.ghost/activitypub/
handle /.ghost/activitypub/* {
        reverse_proxy {$ACTIVITYPUB_TARGET}
}

handle /.well-known/webfinger {
        reverse_proxy {$ACTIVITYPUB_TARGET}
}

handle /.well-known/nodeinfo {
        reverse_proxy {$ACTIVITYPUB_TARGET}
}

```

I have pulled the last docker images, pulled the git repo,.. recreated the necessary containers (caddy and ghost),.. but to no avail.

Has anyone had a similar issue or resolved this themselves?

---

<div class="post-metadata">

**Author:** ![Cathy\_Sarisky](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/cathy_sarisky/32/25750_2.png) [@Cathy\_Sarisky](https://forum.ghost.org/u/Cathy_Sarisky)\
**Post date:** [August 14, 2025, 12:25pm UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/2 "2025-08-14T12:25:22Z")

</div>

1 - This is a security settings problem. In the security headers snippet (in caddy), remove the X-frame options setting, or set a more permissive value. (I’ve reported it, and the team has an issue open internally. [Preview post and visit site do not work (Ghost 6.0 container)](https://forum.ghost.org/t/preview-post-and-visit-site-do-not-work-ghost-6-0-container/59451) )

2 - If you haven’t already, can you bump Ghost to 6.0.3 (hopefully a fresh pull of the container will get you that). There was a missing redirect that was impacting specifically sites with separate admin domains, and it is fixed at 6.0.3.

Check your browser’s network console for errors also - any 401s?

I had very similar behavior (without docker) and fixed it with a redirect not-admin-site.tld/ghost/\* over to actual-admin-site.tld/ghost/, but that should be fixed and working in 6.0.3.

Another possibility is that your containers aren’t talking to each other correctly

---

<div class="post-metadata">

**Author:** ![Cathy\_Sarisky](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/cathy_sarisky/32/25750_2.png) [@Cathy\_Sarisky](https://forum.ghost.org/u/Cathy_Sarisky)\
**Post date:** [August 14, 2025, 2:01pm UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/3 "2025-08-14T14:01:59Z")

</div>

Split this topic on August 14, 2025, 2:01pm UTC

5 posts were split to a new topic: [ActivityPub: {“error”:“Forbidden”,“code”:“SITE\_MISSING”}](https://forum.ghost.org/t/activitypub-error-forbidden-code-site-missing/59584)

---

<div class="post-metadata">

**Author:** ![lorenzo](https://avatars.discourse-cdn.com/v4/letter/l/4da419/32.png) [@lorenzo](https://forum.ghost.org/u/lorenzo)\
**Post date:** [August 14, 2025, 1:47pm UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/8 "2025-08-14T13:47:07Z")

</div>

Hi, thank you for your reply.

I did update to 6.03 and double checked in the container itself with the CLI that I am indeed running that.  
I do see a few CORS errors in my network tab, which are probably the problem.

```auto
Access to XMLHttpRequest at 'https://mywebsite.com/.ghost/activitypub/v1/notifications/unread/count' from origin 'https://dashboard.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

```

Will probably need to update something in one of the Caddy files

---

<div class="post-metadata">

**Author:** ![Cathy\_Sarisky](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/cathy_sarisky/32/25750_2.png) [@Cathy\_Sarisky](https://forum.ghost.org/u/Cathy_Sarisky)\
**Post date:** [August 14, 2025, 2:00pm UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/9 "2025-08-14T14:00:07Z")

</div>

Yep. Check your securityHeaders snippet.

---

<div class="post-metadata">

**Author:** ![lorenzo](https://avatars.discourse-cdn.com/v4/letter/l/4da419/32.png) [@lorenzo](https://forum.ghost.org/u/lorenzo)\
**Post date:** [August 14, 2025, 2:45pm UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/10 "2025-08-14T14:45:20Z")

</div>

Aside from the X-Frame, my config is pretty much the same as the default

```auto
header {
        # Enable HSTS
        Strict-Transport-Security max-age=31536000;
        # Prevent embedding in frames
        X-Frame-Options "allow-from {$ADMIN_DOMAIN}"
        # Enable XSS protection
        X-XSS-Protection "1; mode=block"
        # Prevent MIME sniffing
        X-Content-Type-Options nosniff
        # Referrer policy
        Referrer-Policy strict-origin-when-cross-origin
}

```

I’m not quite familiar with Caddy, I tried adding `Access-Control-Allow-Origin "{$ADMIN_DOMAIN}"` but the issue remains the same (I also recreated the containers with each change).. am I doing something wrong or overlooking something?

---

<div class="post-metadata">

**Author:** ![lorenzo](https://avatars.discourse-cdn.com/v4/letter/l/4da419/32.png) [@lorenzo](https://forum.ghost.org/u/lorenzo)\
**Post date:** [August 14, 2025, 9:52pm UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/11 "2025-08-14T21:52:09Z")

</div>

After a lot of messing around (turns out it was cached,…), I am now getting:

`{"error":"Forbidden","code":"SITE_MISSING"}`  
Similar to @ppittman in his [thread](https://forum.ghost.org/t/activitypub-error-forbidden-code-site-missing/59584)

Despite CORS not being an issue anymore, I do still encounter:

```auto
[2025-08-14 21:57:56] ERROR Could not get webhook secret for ActivityPub FetchError: invalid json response body at https://mywebsite.com/.ghost/activitypub/v1/site reason: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
[2025-08-14 21:57:56] ERROR No webhook secret found - cannot initialise

```

---

<div class="post-metadata">

**Author:** ![jannis](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/jannis/32/39718_2.png) [@jannis](https://forum.ghost.org/u/jannis)\
**Post date:** [August 15, 2025, 7:33am UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/12 "2025-08-15T07:33:32Z")

</div>

What’s happening on your ActivityPub container? Does it receive the requests properly?

The AP server has a concept of “sites” and should generally add a new site when it connects properly for the first time.

I have also seen cases where previous attempts failed, and a malformed site was put into the database, though this only happened in migrations from one server to another (with the webhook secrets getting lost on the way).

---

<div class="post-metadata">

**Author:** ![lorenzo](https://avatars.discourse-cdn.com/v4/letter/l/4da419/32.png) [@lorenzo](https://forum.ghost.org/u/lorenzo)\
**Post date:** [August 15, 2025, 8:22am UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/13 "2025-08-15T08:22:09Z")

</div>

So if I check my AP docker logs, this is what’s inside:

```auto
21:57:54.534 INF activitypub: Message queue is disabled
21:57:54.794 INF activitypub: listening on :::8080, booted in 2885ms
21:58:15.323 INF activitypub: 'GET' 'mywebsite.com' 'https://mywebsite.com/.ghost/activitypub/v1/notifications/unread/count' 'e4f14fe6-911d-4f31-8a5c-42eef46eda98'
21:58:15.325 INF activitypub: KnexKvStore: Get key cachedJwks,mywebsite.com
21:58:15.416 INF activitypub: No site found for 'mywebsite.com'
21:58:15.417 INF activitypub: 'GET' 'mywebsite.com' 'https://mywebsite.com/.ghost/activitypub/v1/notifications/unread/count' 'e4f14fe6-911d-4f31-8a5c-42eef46eda98' 403 95ms
21:58:18.835 INF activitypub: 'GET' 'mywebsite.com' 'https://mywebsite.com/.ghost/activitypub/v1/notifications/unread/count' 'f1ba31a2-3462-428e-9715-02bddb8b0482'

```

So it does seem to get requests  
I do also seem to see the admin dashboard occur in there at times:

```auto
22:13:12.419 INF activitypub: KnexKvStore: Get key cachedJwks,dashboard.mywebsite.com
22:13:12.673 INF activitypub: KnexKvStore: Set key cachedJwks,dashboard.mywebsite.com

```

I’ve just restarted the containers and I do notice that there’s no signs of AP getting any requests at startup (when the webhook secret can’t be initialised):

```auto
08:13:26.032 INF activitypub: Message queue is disabled
08:13:26.271 INF activitypub: listening on :::8080, booted in 3382ms

```

If I then go to the dashboard and look at the Network tab I do see some requests coming through:

```auto
08:13:26.032 INF activitypub: Message queue is disabled
08:13:26.271 INF activitypub: listening on :::8080, booted in 3382ms
08:14:47.773 INF activitypub: 'GET' 'mywebsite.com' 'https://mywebsite.com/.ghost/activitypub/v1/notifications/unread/count' 'fafa474c-7753-4d33-83f0-63f2976fa0f0'
08:14:47.774 INF activitypub: KnexKvStore: Get key cachedJwks,mywebsite.com
08:14:47.835 INF activitypub: No site found for 'mywebsite.com'
08:14:47.836 INF activitypub: 'GET' 'mywebsite.com' 'https://mywebsite.com/.ghost/activitypub/v1/notifications/unread/count' 'fafa474c-7753-4d33-83f0-63f2976fa0f0' 403 63ms

```

I did notice the request to AP happens at around the same time AP initialises, however when turning off Network in the dashboard, and back on, I get the same error (no secret found), implying it’s not a timing issue either.

---

<div class="post-metadata">

**Author:** ![jannis](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/jannis/32/39718_2.png) [@jannis](https://forum.ghost.org/u/jannis)\
**Post date:** [August 15, 2025, 1:08pm UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/14 "2025-08-15T13:08:14Z")

</div>

What I see based on the logs is that AP receives the request, yeah.

But the site doesn’t exist. Toggling AP in the settings should re-initialise the webhook. Is there any sign of that?

If not, it might be worth checking the database to see if there is an entry in the `sites` table of the ActivityPub database.

If that’s the only site relying on your AP server, deleting and re-creating the database might also be worth a try to force a restart.

---

<div class="post-metadata">

**Author:** ![lorenzo](https://avatars.discourse-cdn.com/v4/letter/l/4da419/32.png) [@lorenzo](https://forum.ghost.org/u/lorenzo)\
**Post date:** [August 15, 2025, 6:22pm UTC](https://forum.ghost.org/t/docker-deployment-and-activitypub/59581/15 "2025-08-15T18:22:59Z")

</div>

Thank you @jannis (and @Cathy_Sarisky) for your help it led me in the right direction.

I saw the AP database existed but that all the tables were empty. This led me to check the error once again and I started doing some thinking. It mentioned an HTML response instead of JSON (that’s why it failed, it couldn’t parse it) – but when I visited the URL I did get JSON. So maybe it was cached?

Since this is the 2nd time a caching related issue came up I started looking at Cloudflare.

I removed them as a proxy, and miraculously it started working! I then turned back on the proxy and it’s still working..

Mess of a roller coaster but thank you all for your help!
