An OCaml Activitypub Server

Kiran Gopinathan d677ae6b20 Merge pull request #5 from hannesm/update-mirage-crypto-rng 1 month ago
bin 696f94dd99 works on postgres :gasp:? 2 months ago
lib 11dc1b662a update to mirage-crypto-rng 0.11.0 API changes 1 month ago
resources 8bc161602f updated logo 2 months ago
scripts 3fbd3647b9 fixed bug in service 2 months ago
static 1326fde672 typo with style 2 months ago
tests 11dc1b662a update to mirage-crypto-rng 0.11.0 API changes 1 month ago
.dockerignore d662dcb0a8 added support for mastodon in integration tests 2 months ago
.gitignore c80ad7e6e1 refactored configuration to be mutable 4 months ago
.ocamlformat 8359558c70 swapped to sihl 2 years ago
LICENSE e825bdf15a Add LICENSE 10 months ago f19d1beeee updated readme 2 months ago
dune-project 11dc1b662a update to mirage-crypto-rng 0.11.0 API changes 1 month ago 352cb0d6af added files 1 year ago 053f237775 added a history document 2 months ago 00c76c8942 completed major refactoring 8 months ago
ocamlot-failed-events.json 58b9f79fbd implemented undos and fixed bug in following 2 months ago
ocamlot.opam 11dc1b662a update to mirage-crypto-rng 0.11.0 API changes 1 month ago
screenshot.png 2fda3b9982 updated 2 months ago 9579db8620 posts with images now supported 2 months ago 00c76c8942 completed major refactoring 8 months ago

OCamlot - An OCaml Activitypub Server

OCamlot is an activitypub server written in OCaml!

As with most non-mainstream activitypub servers, it's currently in very experimental status!


  • Creating posts
  • Replying to posts
  • Custom profiles
  • Liking posts (we call them toasts)
  • Reboosting posts (we call them cheers)
  • Replying to posts



You can see a running instance of the server at!

Deploying OCamlot

The rest of this guide will be assuming that you have a server with OCaml installed, and nginx, setup with letsencrypt, such that an appropriate internal port is accessible via a public domain.

Your nginx config may look something like as follows (using PORT 7331 and DOMAIN

server {

    listen 443 ssl; # managed by Certbot

    location / {
        proxy_pass http://localhost:7331;
    ssl_certificate /etc/letsencrypt/live/; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

server {
    if ($host = {
        return 301 https://$host$request_uri;
   } # managed by Certbot

   listen 80 default_server;
   listen [::]:80 default_server;

   return 404; # managed by Certbot

To deploy the server, do the following:

  1. Create a new user to run the ocamlot process

    $ sudo useradd -r -s /bin/false -m -d /var/lib/ocamlot -U ocamlot
  2. Create a new postgres user and database:

$ sudo -Hu postgres psql

postgres=# CREATE ROLE ocamlot WITH password = '<password>';

postgres=# ALTER ROLE ocamlot WITH login;

postgres=# CREATE DATABASE ocamlot WITH OWNER ocamlot;
  1. Clone the development repository:

    $ sudo mkdir -p /opt/ocamlot
    $ sudo chown -R ocamlot:ocamlot /opt/ocamlot
    $ sudo -Hu ocamlot git clone /opt/ocamlot
  2. Switch user to the ocamlot user:

    $ sudo -Hu ocamlot bash
  3. Setup opam:

    $ opam init
    $ eval $(opam env)
    $ opam update
  4. Install dev dependencies:

    $ cd /var/lib/ocamlot
    $ git clone
    $ cd ./petrol
    $ opam pin .
  5. Build the project

    $ cd /opt/ocamlot
    $ opam update && opam install --deps-only .
    $ dune build
  6. Modify ./scripts/ with domain and port:

    # file: ./scripts/
    /opt/ocamlot/_build/default/bin/main.exe -u 'ocamlot:<password>@localhost:5432' -d "" -p 7331 -D
  7. Create an account via the web UI, with username <username>

  8. Promote user <username> to admin

    /opt/ocamlot/_build/default/bin/main.exe -u 'ocamlot:<password>@localhost:5432' -d "" --promote-to-admin=<username>
  9. Copy over ./scripts/ocamlot.service to etc/systemd/system/ocamlot.service:

    sudo cp /opt/ocamlot/scripts/ocamlot.service /etc/systemd/system/ocamlot.service
  10. Enable and start ocamlot.service:

    sudo systemctl enable --now ocamlot.service

Development Setup

To develop OCamlot locally, we provide a docker-compose file for setting up a network with a running OCamlot (port 7331) and pleroma (port 4000) instance. The two containers are connected through a network in which the OCamlot server can be found under the domain name and the Pleroma server can be found under the domain name (Note: because there is no easy way of updating the CA store that elixir uses, you will need to patch your local copy of pleroma to disable certification verification for interaction between the two containers to work).

You will need docker-compose and docker

  1. Clone a copy of pleroma to the tests/integration_test/ directory:
git clone -b  v2.5.0 --single-branch ./tests/integration_tests/pleroma
  1. Apply patch to pleroma to disable TLS validation (required for local testing)
(cd ./tests/integration_tests/pleroma && git apply ../pleroma.patch)
  1. Change directory into the tests/integration_test/ directory:
cd ./tests/integration_tests/
  1. Run docker-compose build with the local docker-compose file:
docker-compose -f ./docker-compose.local.yml build
  1. Run docker-compose up with the local docker-compose file:
docker-compose -f ./docker-compose.local.yml up

Now pleroma will be available at https://localhost:4000 and ocamlot at https://localhost:7331

  1. (optional), if you want to update the OCamlot server after making some changes locally, do the following:

    • 6.1. Find out the name of the OCamlot server container using docker container list
    • 6.2. Attach to the OCamlot container using docker container exec -it <container-id> bash
    • 6.3. Kill the running OCamlot process using pkill -9 main.exe
    • 6.4. Run eval $(opam env), then dune build then dune exec -- ./bin/main.exe -d -D