objective categorical abstract machine language personal data server

Documentation

futur.blue 738d1445 08dc2f23

verified
+206 -7
+3
Caddyfile
··· 1 + {$PDS_HOSTNAME} { 2 + reverse_proxy pds:8008 3 + }
+11 -2
Dockerfile
··· 1 - FROM --platform=linux/amd64 ocaml/opam:debian-12-ocaml-5.2 AS build 1 + FROM ocaml/opam:debian-12-ocaml-5.2 AS build 2 2 3 3 ARG NODE_VERSION=v24.11.1 4 4 ARG OPAM_VERSION=2.5.0 5 5 ARG DUNE_VERSION=3.20.2 6 + 7 + ARG GIT_REV 8 + ENV GIT_REV=$GIT_REV 6 9 7 10 RUN sudo apt-get install -y cmake git libev-dev libffi-dev libgmp-dev libssl-dev libsqlite3-dev libpcre3-dev pkg-config 8 11 ··· 26 29 RUN opam exec dune pkg lock 27 30 RUN bash -c "source $NVM_DIR/nvm.sh && opam exec dune build -- --release --stop-on-first-error" 28 31 29 - FROM --platform=linux/amd64 debian:12 AS run 32 + FROM debian:12 AS run 30 33 31 34 RUN apt-get update && apt-get install -y ca-certificates libev-dev libffi-dev libgmp-dev libssl-dev libsqlite3-dev libpcre3-dev netbase pkg-config 35 + 36 + RUN mkdir /data 32 37 33 38 COPY --from=build /home/opam/pegasus/_build/default/bin/main.exe /bin/pegasus 34 39 COPY --from=build /home/opam/pegasus/_build/default/bin/gen_keys.exe /bin/gen-keys 35 40 36 41 ENTRYPOINT ["/bin/pegasus"] 42 + 43 + LABEL org.opencontainers.image.source=https://tangled.org/futur.blue/pegasus 44 + LABEL org.opencontainers.image.description="pegasus, an atproto pds" 45 + LABEL org.opencontainers.image.licenses=MPL-2.0
+94
README.md
··· 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.
+87 -2
docker-compose.yaml
··· 1 1 services: 2 - pegasus: 2 + pds: 3 3 build: . 4 + image: ghcr.io/futurgh/pegasus:latest 4 5 ports: 5 6 - "8008:8008" 6 - restart: always 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
+10
dune
··· 85 85 (with-stdout-to 86 86 %{null} 87 87 (run ocaml-crunch -e sql -m plain ./user_store -o %{target}))))) 88 + 89 + (subdir 90 + pegasus/lib 91 + (rule 92 + (target version.ml) 93 + (deps (universe)) 94 + (action 95 + (with-stdout-to 96 + %{target} 97 + (bash "echo 'let commit_hash = \"'${GIT_REV:=$(git rev-parse --short HEAD 2>/dev/null || echo 'dev')}'\"'")))))
+1 -3
pegasus/lib/api/health.ml
··· 1 - let version = "dev" 2 - 3 1 let handler = 4 2 Xrpc.handler (fun _ -> 5 3 Dream.json @@ Yojson.Safe.to_string 6 - @@ `Assoc [("version", `String version)] ) 4 + @@ `Assoc [("version", `String Version.commit_hash)] )