### Minimal ActivityPub Request Processing Example Source: https://go-activitypub.federated.id/lib/modules/processing/index.html This snippet demonstrates the basic setup and processing of an ActivityPub request using the Go ActivityPub library. It includes initializing the storage, client, and processor, then handling an incoming activity. ```go // The underlying storage backend, see go-ap/storage-* modules. repo := new(storage.FullStorage) // The client is used when it's required to dereference properties of the // incoming that are referred only by their IDs into full ActivityPub // objects. Some instances require that remote fetching is done using // requests containing valid HTTP-Signatures, so take that into // consideration. See the go-ap/client module for how to initialize it for // such cases. client := client.New() // Initializing the ActivityPub state machine, see the go-ap/processing // module for the relevant initializer options. processor := processing.New( processing.WithClient(client), processing.WithStorage(repo), ) if err != nil { return fmt.Errorf("unable to initialize processor: %w", err) } // The processor needs to know the the URL on which the current request has // been operated on. // If this is a Social API request, it needs to correspond // to an actor's /outbox. // If this is a Federated Protocol request, it needs // to correspond to its /inbox receivedIn := pub.IRI("https://" + filepath.Join(req.Host, req.URL.Path)) // Authorized is an actor extracted from the HTTP request auhtorization // headers. To extract it, see the go-ap/authorize module, which can extract // HTTP-Signatures, and OAuth2 bearer tokens. authorized := new(vocab.Actor) // The Activity extracted from the request body body, _ := io.ReadAll(r.Body) act, err = vocab.UnmarshalJSON(body) if err != nil { return fmt.Errorf("failed to unmarshal activity from request: %w", err) } // After processing the Activity, it will have been updated with any // information the specification mentions for the combination of Activity // and Object types. if it, err = processor.ProcessActivity(act, authorized, receivedIn); err != nil { return fmt.Errorf("error processing activity: %w", err) } // NOTE: the application's custom logic for handling the Activity/Object // pairs after successfully processing them. switch { case vocab.CreateType.Match(it.GetType()): case vocab.UndoType.Match(it.GetType()): case vocab.LikeType.Match(it.GetType()), vocab.DislikeType.Match(it.GetType()): } ``` -------------------------------- ### Install Dependencies and Build ONI Source: https://go-activitypub.federated.id/apps/oni/index.html Installs JavaScript dependencies and compiles the ONI application. Ensure you have Go installed and a writable path for storage. ```bash # We need to download the JavaScript dependencies, using yarn or npm # yarn install # or npm install $ go mod tidy $ go generate assets.go $ go build -trimpath -a -ldflags '-s -w -extldflags "-static"' -o ./bin/oni ./cmd/oni/main.go ``` -------------------------------- ### Compile ONI Application Source: https://go-activitypub.federated.id/apps/oni Steps to compile the ONI application, including dependency installation and building the executable. Ensure you have Go installed and run these commands in the project root. ```bash # We need to download the JavaScript dependencies, using yarn or npm # yarn install # or npm install $ go mod tidy $ go generate assets.go $ go build -trimpath -a -ldflags '-s -w -extldflags "-static"' -o ./bin/oni ./cmd/oni/main.go ``` -------------------------------- ### Run ONI Server and Create Root Actor Source: https://go-activitypub.federated.id/apps/oni Instructions for running the ONI server and the initial setup process. The root actor is created automatically upon the first request to the server's hostname. ```bash $ ./bin/oni --listen 127.0.0.1:8443 --path /storage --pw SuperS3cr3tSecretP4assw0rd 4:21PM DBG Using storage path=/storage 4:21PM WRN Storage does not contain any actors. 4:21PM INF Started hosts=[] socket=127.0.0.1:8443[TCP] version=HEAD # After performing something like: curl https://oni.local 4:22PM DBG saved IRI=https://oni.local/ type=Application 4:22PM INF Created root actor iri=https://oni.local/ 4:22PM INF Successfully set password secret=SuperS3cr3tSecretP4assw0rd 4:22PM INF Created OAuth2 Client ClientID=https://oni.local/ 4:22PM INF Authorization: Bearer buyK1A3XQqCt8nOK0LKecA 4:22PM DBG Successfully resolved hostname to a valid address addr=127.0.4.2:443 host=oni.local 4:22PM INF Created new root actor iri=https://oni.local/ 4:22PM INF OK accept="application/json, */*" elapsed="771.716µs" iri=https://oni.local/ method=GET size=1.21KiB st=200 ua=curl/8.15.0 ``` -------------------------------- ### Run FedBOX Authorize Server with Config File Source: https://go-activitypub.federated.id/apps/fedbox/authorize/index.html Starts the authorize server using a specified .env configuration file. Ensure common variables are prefixed if sharing the file with other services. ```bash $ authorize --config /storage/.env ``` -------------------------------- ### Implement Cancelable Load Operation in Store Source: https://go-activitypub.federated.id/lib/rfc/index.html Example implementation of a cancelable Load method for the Store interface using context.Context and a goroutine. ```go func (s *store) Load(ctx context.Context, iri vocab.IRI, f ...filters.Check) (vocab.Item, error) { ctx, cancel := context.WithCancel(ctx) defer cancel() c := make(chan vocab.Item) go s.asyncLoad(c, iri, f...) select { case <-ctx.Done(): return nil, ctx.Err() case it := <-c: return it, nil } return nil, errors.New() } ``` -------------------------------- ### Bootstrap FedBOX Storage Source: https://go-activitypub.federated.id/apps/fedbox/installation.html Initialize the storage method used by FedBOX. Refer to the fedbox commands page for advanced examples. ```bash $ ./bin/fedbox storage bootstrap ``` -------------------------------- ### Run ONI Server and Create Root Actor Source: https://go-activitypub.federated.id/apps/oni/index.html Starts the ONI server, specifying the listen address, storage path, and password. The root actor is created automatically upon the first request (e.g., using curl). ```bash $ ./bin/oni --listen 127.0.0.1:8443 --path /storage --pw SuperS3cr3tSecretP4assw0rd 4:21PM DBG Using storage path=/storage 4:21PM WRN Storage does not contain any actors. 4:21PM INF Started hosts=[] socket=127.0.0.1:8443[TCP] version=HEAD # After performing something like: curl https://oni.local 4:22PM DBG saved IRI=https://oni.local/ type=Application 4:22PM INF Created root actor iri=https://oni.local/ 4:22PM INF Successfully set password secret=SuperS3cr3tSecretP4assw0rd 4:22PM INF Created OAuth2 Client ClientID=https://oni.local/ 4:22PM INF Authorization: Bearer buyK1A3XQqCt8nOK0LKecA 4:22PM DBG Successfully resolved hostname to a valid address addr=127.0.4.2:443 host=oni.local 4:22PM INF Created new root actor iri=https://oni.local/ 4:22PM INF OK accept="application/json, */*" elapsed="771.716µs" iri=https://oni.local/ method=GET size=1.21KiB st=200 ua=curl/8.15.0 ``` -------------------------------- ### Authorize BOX CLI to ONI Instance Source: https://go-activitypub.federated.id/apps/oni/index.html Use this command to authorize the BOX CLI helper to interact with your ONI instance. Ensure you replace the example URL and secret with your actual instance details. ```bash $ box authorize --as https://social.example.com --secret AnotherSecretPassword 5:52PM INF OK ``` -------------------------------- ### Bootstrap FedBOX Storage Backend Source: https://go-activitypub.federated.id/apps/fedbox/fedbox-commands.html Initializes a new storage backend for FedBOX. This command creates the necessary database and service configurations. It is recommended to run this from the directory containing FedBOX configuration files or specify the path using the --path argument. ```bash $ fedbox --path /tmp/fedbox storage bootstrap {"level":"info","time":"2025-09-03T19:56:31+02:00","message":"Successfully created /tmp/fedbox db for storage fs"} {"level":"info","time":"2025-09-03T19:56:31+02:00","message":"Successfully created FedBOX service https://fedbox.git/ for storage fs"} ``` -------------------------------- ### Proxy OAuth Endpoints with Caddy Source: https://go-activitypub.federated.id/apps/fedbox/authorize/index.html Configures Caddy to proxy OAuth2 authorization requests to the authorize service. This setup handles both actor-specific and root service OAuth endpoints. ```caddy # actors oauth endpoints handle /actors/*/oauth/* { reverse_proxy http://authorize-service:1234 { transport http } } # root service oauth endpoints handle /oauth/* { reverse_proxy http://authorize-service:1234 { transport http } } ``` -------------------------------- ### Proxy .well-known Endpoints with Caddy Source: https://go-activitypub.federated.id/apps/fedbox/well-known/index.html Configure Caddy to proxy requests to the .well-known endpoints to a dedicated service. This setup is useful when running the well-known server alongside FedBOX. ```caddy # server .well-known endpoints handle /.well-known/* { reverse_proxy http://well-known-service:2345 { transport http } } ``` -------------------------------- ### Actor OAuth2 Endpoints Configuration Source: https://go-activitypub.federated.id/apps/fedbox/authorize Example JSON configuration for an actor's OAuth2 endpoints. This configuration is used by the authorize application to understand the actor's OAuth2 capabilities. ```json { // For actor https://social.example.com/actors/11111111-2222-3333-4444-555555555555 "endpoints": { "oauthAuthorizationEndpoint": "https://social.example.com/actors/11111111-2222-3333-4444-555555555555/oauth/authorize", "oauthTokenEndpoint": "https://social.example.com/actors/11111111-2222-3333-4444-555555555555/oauth/token", "proxyUrl": "https://social.example.com/proxyUrl" } } ``` -------------------------------- ### Run Well-Known Server with .env Configuration Source: https://go-activitypub.federated.id/apps/fedbox/well-known/index.html Execute the well-known server using a specified .env configuration file. Ensure common variables are prefixed if sharing the .env file with other services. ```bash $ point --config /storage/.env ``` -------------------------------- ### Run Well-Known Server with Direct Storage Path Source: https://go-activitypub.federated.id/apps/fedbox/well-known/index.html Configure the well-known server by directly specifying a custom storage Data Source Name (DSN). The DSN format is 'type:///actual/disk/path'. ```bash $ point --path fs:///storage/example.com/qa ``` -------------------------------- ### Compile FedBOX for Production Source: https://go-activitypub.federated.id/apps/fedbox/installation.html Compile FedBOX with settings optimized for a production environment. ```bash $ make ENV=prod all ``` -------------------------------- ### Using OnXXX Functions with Different ActivityPub Types in Go Source: https://go-activitypub.federated.id/lib/pitfalls.html Illustrates the correct usage of OnXXX functions for different ActivityStreams types like Object, IntransitiveActivity, and Question. Using the wrong function can lead to incorrect behavior or data loss, especially when dealing with types that don't conform to the expected memory model. ```go //import pub "github.com/go-ap/activitypub" var example pub.Item = new(pub.Question) err := pub.OnObject(example, func (ob *pub.Object) error { // works ob.ID = pub.IRI("https://example.com") ob.Type = pub.QuestionType return nil }) err := pub.OnIntransitiveActivity(example, func (act *pub.IntransitiveActivity) error { // still works act.Actor = pub.IRI("https://example.com/1") }) err := pub.OnActivity(example, func (act *pub.Activity) error { // should work, but it should be used from an OnInstransitiveActivity call // as above act.Actor = pub.IRI("https://example.com/2") // does not work, as the object property does not exist in the // Question type, which is an intransitive activity act.Object = pub.IRI("https://example.com/lorem-ipsum") return nil }) err := pub.OnQuestion(example, func(q *pub.Question) error { // and this also works, accessing the Question specific properties q.AnyOf = pub.ItemCollection{} q.Closed = true return nil }) ``` -------------------------------- ### Add User with ONI CLI Source: https://go-activitypub.federated.id/apps/oni/index.html Use this command to add a new user via the ONI CLI. Ensure your DNS is correctly configured for the actor's hostname. ```bash $ ./bin/oni --path /storage actor add --url https://social.example.com --pw AnotherSecretPassword --without-token 5:49PM DBG saved IRI=https://social.example.com path=/storage type=Application 5:49PM DBG Created root actor iri=https://social.example.com path=/storage 5:49PM INF Successfully set password secret=AnotherSecretPassword path=/storage 5:49PM DBG Created OAuth2 Client ClientID=https://social.example.com path=/storage 5:49PM WRN Unable to resolve actor's hostname to a valid address err="lookup social.example.com: no such host" path=/storage 5:49PM WRN Please make sure your DNS is configured correctly to point the hostname to the socket oni listens to host=social.example.com path=/storage ``` -------------------------------- ### Store Interface Source: https://go-activitypub.federated.id/lib/rfc/index.html Combined interface for retrieving and storing data from local storage. Implemented by individual storage backends. ```go type store interface { readStore writeStore } ``` -------------------------------- ### Compile FedBOX with Specific Storage Source: https://go-activitypub.federated.id/apps/fedbox/installation.html Compile FedBOX, specifying a particular storage backend like SQLite. ```bash $ make STORAGE=sqlite all ``` -------------------------------- ### Edit FedBOX Configuration Source: https://go-activitypub.federated.id/apps/fedbox/installation.html Copy the default environment file and open it for editing to customize settings. ```bash $ cp .env.dist .env $ $EDITOR .env ``` -------------------------------- ### Read Store Interface Source: https://go-activitypub.federated.id/lib/rfc/index.html Helper interface for retrieving objects and activities from local storage. Used by Processor or Validator. ```go type readStore interface { Load(iri vocab.IRI, ff ...filters.Check) (vocab.Item, error) } ``` -------------------------------- ### Clone Webfinger Repository Source: https://go-activitypub.federated.id/apps/fedbox/installation.html Clone the source code for the .well-known end-point server and navigate into its directory. ```bash $ git clone https://github.com/go-ap/webfinger $ cd webfinger ``` -------------------------------- ### Compile FedBOX (Default) Source: https://go-activitypub.federated.id/apps/fedbox/installation.html Compile the FedBOX application using the default build settings. ```bash $ make all ``` -------------------------------- ### Post a text entry Source: https://go-activitypub.federated.id/apps/box/examples.html The most basic operation is to post a simple text post using the 'box post' command. Content can be provided via a flag or by leaving content-related flags empty to use the default editor. ```bash $ box post --as https://social.example.com --name "First post!" --content "Hello Fediverse!" 5:56PM DBG OK IRI=https://social.example.com/ duration=12.234175ms log=client status="200 OK" 5:56PM INF success id=https://social.example.com/outbox/1755861965567 object=https://social.example.com/outbox/1755861965567/object op=Create ``` -------------------------------- ### Run FedBOX Authorize Server with Direct Storage Path Source: https://go-activitypub.federated.id/apps/fedbox/authorize/index.html Configures the authorize server to use a specific storage type and path directly. The format is 'type:///actual/disk/path'. ```bash $ authorize --path fs:///storage/example.com/qa ``` -------------------------------- ### Write Store Interface Source: https://go-activitypub.federated.id/lib/rfc/index.html Helper interface for saving and deleting objects and collections from local storage. Used by the Processor. ```go type writeStore interface { // Save saves the incoming ActivityStreams Object, and returns it together with any properties // populated by the method's side effects. (eg, Published property can point to the current time, etc.). Save(vocab.Item) (vocab.Item, error) // Delete deletes completely from storage the ActivityStreams Object, this is usually // a side effect of an Undo activity. Delete(vocab.Item) error // AddTo adds "it" elements to the "col" collection. AddTo(vocab.IRI, ...vocab.Item) error // RemoveFrom removes "it" item from "col" collection RemoveFrom(vocab.IRI, ...vocab.Item) error } ``` -------------------------------- ### Clone Authorize Repository Source: https://go-activitypub.federated.id/apps/fedbox/installation.html Clone the source code for the OAuth2 authorization server and navigate into its directory. ```bash $ git clone https://github.com/go-ap/authorize $ cd authorize ``` -------------------------------- ### Upload an image Source: https://go-activitypub.federated.id/apps/box/examples.html Upload an image using the 'box upload' command. The --optimize flag can be used for web-optimized variants. This command also supports other file types like audio, video, SVG, and PDF. ```bash $ box upload --as https://social.example.com --name "First image!" \ --summary "The summary works as 'alt' text for images" --path ./example.png 6:05PM DBG OK IRI=https://social.example.com/ duration=11.044419ms log=client status="200 OK" 6:05PM INF success id=https://social.example.com/outbox/1755864320719 object=https://social.example.com/outbox/1755864320719/object op=Create ``` -------------------------------- ### Author Text Post with BOX CLI Source: https://go-activitypub.federated.id/apps/oni/box-cli-examples.html Creates a new text post using the BOX CLI. This command opens a local text editor for input. The post content can be structured with title, summary, and body using empty lines as delimiters. ```bash $ box post --as https://social.example.com --id https://social.example.com/news/october-2025 ``` -------------------------------- ### Write Store Interface Source: https://go-activitypub.federated.id/lib/rfc The WriteStore interface provides methods for saving, deleting, adding to, and removing from collections in local storage. ```APIDOC ## Write Store Interface ### Description The `writeStore` interface is a helper interface that gets used by the `Processor` to save objects and collections to *local* storage. ### Methods - **Save(vocab.Item) (vocab.Item, error)**: Saves the incoming ActivityStreams Object, returning it with any side-effect populated properties. - **Delete(vocab.Item) error**: Deletes the ActivityStreams Object completely from storage, typically as a side effect of an Undo activity. - **AddTo(vocab.IRI, ...vocab.Item) error**: Adds specified items to the collection identified by the IRI. - **RemoveFrom(vocab.IRI, ...vocab.Item) error**: Removes specified items from the collection identified by the IRI. ``` -------------------------------- ### Clone FedBOX Repository Source: https://go-activitypub.federated.id/apps/fedbox/installation.html Clone the FedBOX source code from GitHub and navigate into the project directory. ```bash $ git clone https://github.com/go-ap/fedbox $ cd fedbox ``` -------------------------------- ### Store Interface Source: https://go-activitypub.federated.id/lib/rfc The Store interface unifies read and write operations for local storage, implemented by individual storage backends. ```APIDOC ## Store Interface ### Description The `store` interface is a helper interface that gets used by the `Processor` or `Validator` to retrieve and/or store objects and activities from *local* storage. It's implemented by individual storage backends. ### Methods This interface embeds both `readStore` and `writeStore` functionalities. ``` -------------------------------- ### Using OnObject for Type Assertions in GoActivityPub Source: https://go-activitypub.federated.id/lib/pitfalls.html Demonstrates safe usage of the OnObject convenience function for accessing properties of an object that implements the ObjectOrLink interface. Be aware of potential data loss if the underlying type has a different memory layout than pub.Object. ```go //import pub "github.com/go-ap/activitypub" // We load "example" from an external request, and it represents an object // that implements interface pub.ObjectOrLink. var example Item = new(pub.Tombstone) pub.OnObject(example, func(ob *pub.Object) error { // do something that requires access to specific properties of an pub.Object ob.AttributedTo = pub.IRI("https://example.com/test") return nil }) ``` -------------------------------- ### Recompile ONI with Custom Redirect URL Source: https://go-activitypub.federated.id/apps/oni/third-party-oauth-client.html To use a third-party OAuth2 client with a non-predefined return URL, recompile ONI using this build command, specifying your custom URL with the `oni.ExtraRedirectURL` linker flag. ```bash $ go build -ldflags '-s -w -extldflags "-static" -X oni.ExtraRedirectURL=https://example.com/oauthReturnUrl' \ -trimpath -a -o ./bin/oni ./cmd/oni/main.go ```