···1+# pegasus
2+3+is an [atproto PDS](https://atproto.com/guides/glossary#pds-personal-data-server), along with an assortment of atproto-relevant libraries, written in OCaml.
4+5+## running it
6+7+After cloning this repo, start by running
8+9+```
10+docker compose build
11+```
12+13+Next, run
14+15+```
16+docker compose run --rm --entrypoint gen-keys pds
17+```
18+19+to generate some of the environment variables you'll need.
20+21+Head to [`docker-compose.yaml`](docker-compose.yaml) and fill in the environment variables marked as required. See [Environment](#environment) for further details on configuration.
22+23+After that, run
24+```
25+docker compose up -d
26+```
27+to start the PDS, then navigate to `https://{PDS_HOSTNAME}/admin` to log in with the admin password you specified and create an invite code or a new account on the PDS.
28+29+## environment
30+31+Documentation for most environment variables can be found in [`docker-compose.yaml`](docker-compose.yaml). There are two optional categories of environment variables that add functionality:
32+33+### SMTP
34+The PDS can email users for password changes, identity updates, and account deletion. If these environment variables are not set, emails will instead be logged to the process' stdout.
35+36+- `PDS_SMTP_AUTH_URI` — The URI to connect to the mail server. This should look like `smtp[s]://user:pass@host[:port]`.
37+- `PDS_SMTP_STARTTLS=false` — Whether to use STARTTLS when connecting to the mail server. Defaults to false. If true, the connection will default to port 587. If false, the connection will default to port 465. Setting a port in `PDS_SMTP_AUTH_URI` will override either one.
38+- `PDS_SMTP_SENDER` — The identity to send emails as. Can be an email address (`e@mail.com`) or a mailbox (`Name <e@mail.com>`).
39+40+### S3
41+The PDS can be configured to back up server data to and/or store blobs in S3(-compatible storage).
42+43+- `PDS_S3_BLOBS_ENABLED=false` — Whether to store blobs in S3. By default, blobs are stored locally in `{PDS_DATA_DIR}/blobs/[did]/`.
44+- `PDS_S3_BACKUPS_ENABLED=false` — Whether to back up data to S3.
45+- `PDS_S3_BACKUP_INTERVAL_S=3600` — How often to back up to S3, in seconds.
46+- `PDS_S3_ENDPOINT`, `PDS_S3_REGION`, `PDS_S3_BUCKET`, `PDS_S3_ACCESS_KEY`, `PDS_S3_SECRET_KEY` — S3 configuration.
47+- `PDS_S3_CDN_URL` — You may optionally set this to redirect `getBlob` requests to `{PDS_S3_CDN_URL}/blobs/{did}/{cid}`. When unset, blobs will be fetched either from local storage or from S3, depending on `PDS_S3_BLOBS_ENABLED`.
48+49+## development
50+51+This repo contains several libraries in addition to the `pegasus` PDS:
52+53+| library | description |
54+|----------|-------------|
55+| frontend | The PDS frontend, containing the admin dashboard and account page. |
56+| ipld | A mostly [DASL-compliant](https://dasl.ing/) implementation of [CIDs](https://dasl.ing/cid.html), [CAR](https://dasl.ing/car.html), and [DAG-CBOR](https://dasl.ing/drisl.html). |
57+| kleidos | An atproto-valid interface for secp256k1 and secp256r1 key management, signing/verifying, and encoding/decoding. |
58+| mist | A [Merkle Search Tree](https://atproto.com/specs/repository#mst-structure) implementation for data repository purposes. |
59+| pegasus | The PDS implementation. |
60+61+To start developing, you'll need:
62+- [`opam`](https://opam.ocaml.org/doc/Install.html), the OCaml Package Manager
63+- and the following packages, or their equivalents on your operating system: `cmake git libev-dev libffi-dev libgmp-dev libssl-dev libsqlite3-dev libpcre3-dev pkg-config`
64+65+Start by creating an opam switch; similar to a Python virtual environment, storing the dependencies for this project and a specific compiler version. After that, install [`dune`](https://dune.build), the build system/package manager pegasus uses.
66+```
67+opam switch create . 5.2.1
68+opam install dune
69+```
70+71+You may need to run `eval $(opam env)` for this to work. Next, run
72+```
73+dune pkg lock
74+```
75+to solve dependencies.
76+77+Finally, after setting the required environment variables (see [Environment](#environment)), either run
78+```
79+dune exec pegasus
80+```
81+to run the program directly, or
82+```
83+dune build
84+```
85+to produce an executable that you'll likely find in `_build/default/bin`.
86+87+For development, you'll also want to run
88+```
89+dune tools exec ocamlformat
90+dune tools exec ocamllsp
91+```
92+to download the formatter and LSP services. You can run `dune fmt` to format the project.
93+94+The [frontend](frontend) is written in [MLX](https://github.com/ocaml-mlx/mlx), a JSX-ish OCaml dialect. To format it, you'll need to `opam install ocamlformat-mlx`, then `ocamlformat-mlx -i frontend/**/*.mlx`. You'll see a few errors on formatting files containing `[%browser_only]`; I'm waiting on the next release of `mlx` to fix those.
···1services:
2+ pds:
3 build: .
4+ image: ghcr.io/futurgh/pegasus:latest
5 ports:
6 - "8008:8008"
7+ volumes:
8+ - pds:/data
9+ environment:
10+ # (optional) debug, info, warn, or error
11+ # default: info
12+ # - PDS_LOG_LEVEL=info
13+14+ # (optional) directory where databases and blobs will be stored
15+ # default: ./data [relative to cwd]
16+ - PDS_DATA_DIR=./data
17+18+ # (required) hostname where this PDS is running
19+ # for handles to work, you should configure *.hostname and hostname to point to this server
20+ # make sure to also set this env var for the caddy container below
21+ - PDS_HOSTNAME=
22+23+ # (optional) the PDS's DID
24+ # default: did:web:{hostname}
25+ # - PDS_DID=
26+27+ # (optional) whether an invite code is needed to create an account
28+ # default: true
29+ # - PDS_INVITE_CODE_REQUIRED=true
30+31+ # (required) the rotation key the PDS will use, in multibase format
32+ # tip: run the `gen-keys` binary to generate this
33+ - PDS_ROTATION_KEY=
34+35+ # (required) the key used to sign JWKs
36+ # tip: run the `gen-keys` binary to generate this
37+ - PDS_JWK_MULTIBASE=
38+39+ # (required) the PDS admin password
40+ # this can be used to access com.atproto.admin.* endpoints as well as the /admin dashboard
41+ - PDS_ADMIN_PASSWORD=
42+43+ # (optional) relays/crawlers to inform to subscribe to this PDS, comma-separated
44+ # default: https://bsky.network
45+ # - PDS_CRAWLERS=https://bsky.network
46+47+ # (optional [but recommended]): a secret token used to generate DPoP nonces; 32 bytes, base64url
48+ # tip: run the `gen-keys` binary to generate this
49+ # - PDS_DPOP_NONCE_SECRET=
50+51+ # (optional) email config (see readme for details)
52+ # auth uri should look like smtp[s]://user:pass@host[:port]
53+ # sender should look like e@mail.com or Name <e@mail.com>
54+ # without setting these, emails will be logged to stdout
55+ # - PDS_SMTP_STARTTLS=false
56+ # - PDS_SMTP_AUTH_URI=
57+ # - PDS_SMTP_SENDER=
58+59+ # (optional) S3 config (see readme for details)
60+ # set these to back up your databases and/or blobs to S3(-compatible storge)
61+ # - PDS_S3_BLOBS_ENABLED=false
62+ # - PDS_S3_BACKUPS_ENABLED=false
63+ # - PDS_S3_BACKUP_INTERVAL_S=3600
64+ # - PDS_S3_ENDPOINT=
65+ # - PDS_S3_REGION=
66+ # - PDS_S3_BUCKET=
67+ # - PDS_S3_ACCESS_KEY=
68+ # - PDS_S3_SECRET_KEY=
69+ # - PDS_S3_CDN_URL=
70+ restart: unless-stopped
71+72+ caddy:
73+ image: caddy:2-alpine
74+ ports:
75+ - "80:80"
76+ - "443:443"
77+ volumes:
78+ - ./Caddyfile:/etc/caddy/Caddyfile:ro
79+ - caddy-data:/data
80+ - caddy-config:/config
81+ environment:
82+ - PDS_HOSTNAME=
83+ restart: unless-stopped
84+85+volumes:
86+ pds:
87+ driver: local
88+ caddy-data:
89+ driver: local
90+ caddy-config:
91+ driver: local