ONI¶
ONI is a single user ActivityPub social media service.
What we mean by “single user” is that at the root of the service there is an ActivityPub actor which represents the user of the instance. Everything else will be content created by this user.
ONI offers support for text content - long and short - but also media posts as images, audio and video.
The service can function as a blog, image board, event calendar (soon ™) etc. It can be pretty versatile through its use of HTML web-components for the ActivityPub vocabulary.

Compiling the application¶
# 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
Running the server¶
To run ONI you only need to invoke it with an existing writable path to be used for its root storage.
Granted this initial run will not be of too much use, as it starts without a root actor, which is not what you most likely want.
As soon as you perform a request, the root actor will be created using that URL’s hostname. See example below:
$ ./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
As you can infer, due to this behaviour, the service is actually capable of supporting multiple users on the same running application but each of the actors representing them is on a separate host.
They share the same ActivityPub and OAuth2 storage but are separated through the host namespacing.
Using the CLI helper this actor can be moved to another domain. This is not yet available due to limitations with the ActivityPub specification. See this bug tracker issue for more details.
Creating a user from the command line¶
ONI comes with a CLI helper that can be used to perform some maintenance tasks. See below an example to add a user (which this time does not have a valid DNS entry set up)
$ ./bin/onictl --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
Using the BOX helper¶
Currently ONI doesn’t support a way to publish content directly from its web interface.
So we created the BOX CLI helper to facilitate the operation of an ONI instance.
As a short example of using it, here’s how to authorize it to the ONI instance we created above:
$ box authorize --as https://social.example.com --secret AnotherSecretPassword
5:52PM INF OK
For instructions about using other OAuth2 clients see the document about the default OAuth2 configuration.
You can see more examples, on this page.