This project tries to provide a hackable, open to as much federation as possible single user or small user group activitypub server.
Get started with the documentation to get an overview.
To run it locally, just clone the repository, install the go dependencies, cp config.example.yml config.yml.
To init or migrate the database, you can use the db cli tool:
go run cmd/cli/migrate/main.go db --config ./config.yml init
go run cmd/cli/migrate/main.go db --config ./config.yml migrateYou can create user by using the admin cli tool:
go run cmd/cli/admin/main.go register --email test@example.com --username testuser --password 'Str0ngP@ssword!' --config ./config.ymlTo run the server, run:
go run cmd/web/server.go ./config.yml- webfinger
- nodeinfo
- host-meta
- actor profile
-
GET /users/:username - ActivityPub JSON response
- public key in actor document
- compatibility-tested against GoToSocial
- compatibility-tested against Mastodon/Akkoma
-
- inbox
-
POST /users/:username/inbox - signed request requirement in server mode
- stores inbound activities
- handles
Follow - handles
Undo Follow - handles
CreateforNotes - handles
Delete/Updatefor storedNotes - handles
Accept/Rejectfor outbound follows - handles
Announce/Like
-
- outbox
-
GET /users/:username/outbox -
POST /users/:username/outbox - stores local activities
- persists local
Notes - delivers to accepted followers
- DB-backed pagination
- sanitizes note content
- generated stable ULID-based activity/object IDs
- persistent delivery queue
- auth/user-facing posting API
-
- followers/following
- followers collection
- inbound follow acceptance
- outbound follow flow
- following collection with accepted follows
Implemented ActivityPub endpoints:
GET /users/:usernamereturns an ActivityPub actor.POST /users/:username/inboxaccepts signed inbound activities and currently handlesFollow,Undo Follow,Create,Delete,Update,Accept, andReject.GET /users/:username/outboxreturns stored outbox activities.POST /users/:username/outboxcreates and stores localCreate/Noteactivities and delivers them to followers.GET /users/:username/followersreturns accepted followers.GET /users/:username/followingreturns accepted outbound follows.POST /users/:username/followingcreates and delivers an outboundFollow.
The server now has the basic pieces for federation: actor discovery, signed inbox requirement, follow acceptance, signed outbound delivery, stored notes, and outbox/followers collections.
Compatibility notes:
| Implementation | Discovery | Inbound Follow | Outbound Accept | Outbound Note | Inbound Mention Note | Unfollow |
|---|---|---|---|---|---|---|
| GoToSocial | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Mastodon | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ |
| Akkoma/Pleroma | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ |
See compat/README.md for the local GoToSocial compatibility setup and the validated flow checklist.
Mastodon-compatible browser UIs work best when served from the same origin as Gargoyle through a reverse proxy. If the UI is hosted on a separate origin, configure an explicit CORS allowlist:
web:
cors:
allowed_origins:
- http://localhost:5173
allowed_methods: [GET, POST, PUT, PATCH, DELETE, OPTIONS]
allowed_headers: [Authorization, Content-Type]
allow_credentials: falseWildcard CORS origins are rejected; only trusted UI origins should be listed.
For local Fediverse compatibility setups that resolve peers such as gts.test to loopback/private addresses, opt in with exact per-host exceptions:
activitypub:
remote_url_exceptions:
- host: gts.test
allow_http: true
allow_private_ip: trueDo not allow private remote fetching for untrusted production hosts.
Known gaps before claiming broad compatibility:
- Mastodon/Akkoma compatibility still needs real-world testing.
- Delivery is still in-process; there is no persistent delivery queue yet.
- Inbox side effects for
AnnounceandLikeare not implemented yet. - Outbound follow still needs broader real-server compatibility testing.
For more, see https://github.com/BasixKOR/awesome-activitypub