···11+# pegasus
22+33+is an [atproto PDS](https://atproto.com/guides/glossary#pds-personal-data-server), along with an assortment of atproto-relevant libraries, written in OCaml.
44+55+## running it
66+77+After cloning this repo, start by running
88+99+```
1010+docker compose build
1111+```
1212+1313+Next, run
1414+1515+```
1616+docker compose run --rm --entrypoint gen-keys pds
1717+```
1818+1919+to generate some of the environment variables you'll need.
2020+2121+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.
2222+2323+After that, run
2424+```
2525+docker compose up -d
2626+```
2727+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.
2828+2929+## environment
3030+3131+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:
3232+3333+### SMTP
3434+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.
3535+3636+- `PDS_SMTP_AUTH_URI` — The URI to connect to the mail server. This should look like `smtp[s]://user:pass@host[:port]`.
3737+- `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.
3838+- `PDS_SMTP_SENDER` — The identity to send emails as. Can be an email address (`e@mail.com`) or a mailbox (`Name <e@mail.com>`).
3939+4040+### S3
4141+The PDS can be configured to back up server data to and/or store blobs in S3(-compatible storage).
4242+4343+- `PDS_S3_BLOBS_ENABLED=false` — Whether to store blobs in S3. By default, blobs are stored locally in `{PDS_DATA_DIR}/blobs/[did]/`.
4444+- `PDS_S3_BACKUPS_ENABLED=false` — Whether to back up data to S3.
4545+- `PDS_S3_BACKUP_INTERVAL_S=3600` — How often to back up to S3, in seconds.
4646+- `PDS_S3_ENDPOINT`, `PDS_S3_REGION`, `PDS_S3_BUCKET`, `PDS_S3_ACCESS_KEY`, `PDS_S3_SECRET_KEY` — S3 configuration.
4747+- `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`.
4848+4949+## development
5050+5151+This repo contains several libraries in addition to the `pegasus` PDS:
5252+5353+| library | description |
5454+|----------|-------------|
5555+| frontend | The PDS frontend, containing the admin dashboard and account page. |
5656+| 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). |
5757+| kleidos | An atproto-valid interface for secp256k1 and secp256r1 key management, signing/verifying, and encoding/decoding. |
5858+| mist | A [Merkle Search Tree](https://atproto.com/specs/repository#mst-structure) implementation for data repository purposes. |
5959+| pegasus | The PDS implementation. |
6060+6161+To start developing, you'll need:
6262+- [`opam`](https://opam.ocaml.org/doc/Install.html), the OCaml Package Manager
6363+- 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`
6464+6565+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.
6666+```
6767+opam switch create . 5.2.1
6868+opam install dune
6969+```
7070+7171+You may need to run `eval $(opam env)` for this to work. Next, run
7272+```
7373+dune pkg lock
7474+```
7575+to solve dependencies.
7676+7777+Finally, after setting the required environment variables (see [Environment](#environment)), either run
7878+```
7979+dune exec pegasus
8080+```
8181+to run the program directly, or
8282+```
8383+dune build
8484+```
8585+to produce an executable that you'll likely find in `_build/default/bin`.
8686+8787+For development, you'll also want to run
8888+```
8989+dune tools exec ocamlformat
9090+dune tools exec ocamllsp
9191+```
9292+to download the formatter and LSP services. You can run `dune fmt` to format the project.
9393+9494+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.
+87-2
docker-compose.yaml
···11services:
22- pegasus:
22+ pds:
33 build: .
44+ image: ghcr.io/futurgh/pegasus:latest
45 ports:
56 - "8008:8008"
66- restart: always
77+ volumes:
88+ - pds:/data
99+ environment:
1010+ # (optional) debug, info, warn, or error
1111+ # default: info
1212+ # - PDS_LOG_LEVEL=info
1313+1414+ # (optional) directory where databases and blobs will be stored
1515+ # default: ./data [relative to cwd]
1616+ - PDS_DATA_DIR=./data
1717+1818+ # (required) hostname where this PDS is running
1919+ # for handles to work, you should configure *.hostname and hostname to point to this server
2020+ # make sure to also set this env var for the caddy container below
2121+ - PDS_HOSTNAME=
2222+2323+ # (optional) the PDS's DID
2424+ # default: did:web:{hostname}
2525+ # - PDS_DID=
2626+2727+ # (optional) whether an invite code is needed to create an account
2828+ # default: true
2929+ # - PDS_INVITE_CODE_REQUIRED=true
3030+3131+ # (required) the rotation key the PDS will use, in multibase format
3232+ # tip: run the `gen-keys` binary to generate this
3333+ - PDS_ROTATION_KEY=
3434+3535+ # (required) the key used to sign JWKs
3636+ # tip: run the `gen-keys` binary to generate this
3737+ - PDS_JWK_MULTIBASE=
3838+3939+ # (required) the PDS admin password
4040+ # this can be used to access com.atproto.admin.* endpoints as well as the /admin dashboard
4141+ - PDS_ADMIN_PASSWORD=
4242+4343+ # (optional) relays/crawlers to inform to subscribe to this PDS, comma-separated
4444+ # default: https://bsky.network
4545+ # - PDS_CRAWLERS=https://bsky.network
4646+4747+ # (optional [but recommended]): a secret token used to generate DPoP nonces; 32 bytes, base64url
4848+ # tip: run the `gen-keys` binary to generate this
4949+ # - PDS_DPOP_NONCE_SECRET=
5050+5151+ # (optional) email config (see readme for details)
5252+ # auth uri should look like smtp[s]://user:pass@host[:port]
5353+ # sender should look like e@mail.com or Name <e@mail.com>
5454+ # without setting these, emails will be logged to stdout
5555+ # - PDS_SMTP_STARTTLS=false
5656+ # - PDS_SMTP_AUTH_URI=
5757+ # - PDS_SMTP_SENDER=
5858+5959+ # (optional) S3 config (see readme for details)
6060+ # set these to back up your databases and/or blobs to S3(-compatible storge)
6161+ # - PDS_S3_BLOBS_ENABLED=false
6262+ # - PDS_S3_BACKUPS_ENABLED=false
6363+ # - PDS_S3_BACKUP_INTERVAL_S=3600
6464+ # - PDS_S3_ENDPOINT=
6565+ # - PDS_S3_REGION=
6666+ # - PDS_S3_BUCKET=
6767+ # - PDS_S3_ACCESS_KEY=
6868+ # - PDS_S3_SECRET_KEY=
6969+ # - PDS_S3_CDN_URL=
7070+ restart: unless-stopped
7171+7272+ caddy:
7373+ image: caddy:2-alpine
7474+ ports:
7575+ - "80:80"
7676+ - "443:443"
7777+ volumes:
7878+ - ./Caddyfile:/etc/caddy/Caddyfile:ro
7979+ - caddy-data:/data
8080+ - caddy-config:/config
8181+ environment:
8282+ - PDS_HOSTNAME=
8383+ restart: unless-stopped
8484+8585+volumes:
8686+ pds:
8787+ driver: local
8888+ caddy-data:
8989+ driver: local
9090+ caddy-config:
9191+ driver: local