Alternative ATProto PDS implementation
1# ATProto PDS 2``` 3 __ __ 4 /\ \__ /\ \__ 5 __ \ \ ,_\ _____ _ __ ___\ \ ,_\ ___ 6 /'__'\ \ \ \/ /\ '__'\/\''__\/ __'\ \ \/ / __'\ 7 /\ \L\.\_\ \ \_\ \ \L\ \ \ \//\ \L\ \ \ \_/\ \L\ \ 8 \ \__/.\_\\ \__\\ \ ,__/\ \_\\ \____/\ \__\ \____/ 9 \/__/\/_/ \/__/ \ \ \/ \/_/ \/___/ \/__/\/___/ 10 \ \_\ 11 \/_/ 12``` 13 14This is an implementation of an ATProto PDS, built with [Axum](https://github.com/tokio-rs/axum), [rsky](https://github.com/blacksky-algorithms/rsky/) and [Atrium](https://github.com/sugyan/atrium). 15This PDS implementation uses a SQLite database and [diesel.rs](https://diesel.rs/) ORM to store canonical user data, and file system storage to store user blobs. 16 17Heavily inspired by David Buchanan's [millipds](https://github.com/DavidBuchanan314/millipds). 18This implementation forked from [DrChat/bluepds](https://github.com/DrChat/bluepds), and now makes heavy use of the [rsky-repo](https://github.com/blacksky-algorithms/rsky/tree/main/rsky-repo) repository implementation. 19The `actor_store` and `account_manager` modules have been reimplemented from [rsky-pds](https://github.com/blacksky-algorithms/rsky/tree/main/rsky-pds) to use a SQLite backend and file storage, which are themselves adapted from the [original Bluesky implementation](https://github.com/bluesky-social/atproto) using SQLite in Typescript. 20 21 22If you want to see this fork in action, there is a live account hosted by this PDS at [@teq.shatteredsky.net](https://bsky.app/profile/teq.shatteredsky.net)! 23 24> [!WARNING] 25> This PDS is undergoing heavy development, and this branch is not at an operable release. Do _NOT_ use this to host your primary account or any important data! 26 27## Quick Start 28``` 29cargo run 30``` 31 32## Cost breakdown (on Oracle Cloud Infrastructure) 33This is how much it costs to host the @teq.shatteredsky.net account: 34 35- $0/mo [Always Free Resources](https://docs.oracle.com/en-us/iaas/Content/FreeTier/freetier_topic-Always_Free_Resources.htm) 36 - $0/mo: VM.Standard.A1.Flex 37 - OCPU count: 2 38 - Network bandwidth: 2 Gbps 39 - Memory: 12 GB 40 - $0/mo: Virtual Cloud Network 41 - IPv4 address 42 - IPv6 address 43 - $0/mo: Boot volume 44 - Size: 47 GB 45 - VPUs/GB: 10 46 47This is about half of the 3,000 OCPU hours and 18,000 GB hours available per month for free on the VM.Standard.A1.Flex shape. This is _without_ optimizing for costs. The PDS can likely be made to run on much less resources. 48 49## To-do 50### APIs 51- [ ] [Service proxying](https://atproto.com/specs/xrpc#service-proxying) 52- [ ] UG /xrpc/_health (undocumented, but impl by reference PDS) 53<!-- - [ ] xx /xrpc/app.bsky.notification.registerPush 54- app.bsky.actor 55 - [ ] AG /xrpc/app.bsky.actor.getPreferences 56 - [ ] xx /xrpc/app.bsky.actor.getProfile 57 - [ ] xx /xrpc/app.bsky.actor.getProfiles 58 - [ ] AP /xrpc/app.bsky.actor.putPreferences 59- app.bsky.feed 60 - [ ] xx /xrpc/app.bsky.feed.getActorLikes 61 - [ ] xx /xrpc/app.bsky.feed.getAuthorFeed 62 - [ ] xx /xrpc/app.bsky.feed.getFeed 63 - [ ] xx /xrpc/app.bsky.feed.getPostThread 64 - [ ] xx /xrpc/app.bsky.feed.getTimeline --> 65- com.atproto.admin 66 - [ ] xx /xrpc/com.atproto.admin.deleteAccount 67 - [ ] xx /xrpc/com.atproto.admin.disableAccountInvites 68 - [ ] xx /xrpc/com.atproto.admin.disableInviteCodes 69 - [ ] xx /xrpc/com.atproto.admin.enableAccountInvites 70 - [ ] xx /xrpc/com.atproto.admin.getAccountInfo 71 - [ ] xx /xrpc/com.atproto.admin.getAccountInfos 72 - [ ] xx /xrpc/com.atproto.admin.getInviteCodes 73 - [ ] xx /xrpc/com.atproto.admin.getSubjectStatus 74 - [ ] xx /xrpc/com.atproto.admin.sendEmail 75 - [ ] xx /xrpc/com.atproto.admin.updateAccountEmail 76 - [ ] xx /xrpc/com.atproto.admin.updateAccountHandle 77 - [ ] xx /xrpc/com.atproto.admin.updateAccountPassword 78 - [ ] xx /xrpc/com.atproto.admin.updateSubjectStatus 79- com.atproto.identity 80 - [ ] xx /xrpc/com.atproto.identity.getRecommendedDidCredentials 81 - [ ] AP /xrpc/com.atproto.identity.requestPlcOperationSignature 82 - [ ] UG /xrpc/com.atproto.identity.resolveHandle 83 - [ ] AP /xrpc/com.atproto.identity.signPlcOperation 84 - [ ] xx /xrpc/com.atproto.identity.submitPlcOperation 85 - [ ] AP /xrpc/com.atproto.identity.updateHandle 86<!-- - com.atproto.moderation 87 - [ ] xx /xrpc/com.atproto.moderation.createReport --> 88- com.atproto.repo 89 - [X] AP /xrpc/com.atproto.repo.applyWrites 90 - [X] AP /xrpc/com.atproto.repo.createRecord 91 - [X] AP /xrpc/com.atproto.repo.deleteRecord 92 - [X] UG /xrpc/com.atproto.repo.describeRepo 93 - [X] UG /xrpc/com.atproto.repo.getRecord 94 - [X] xx /xrpc/com.atproto.repo.importRepo 95 - [X] xx /xrpc/com.atproto.repo.listMissingBlobs 96 - [X] UG /xrpc/com.atproto.repo.listRecords 97 - [X] AP /xrpc/com.atproto.repo.putRecord 98 - [X] AP /xrpc/com.atproto.repo.uploadBlob 99- com.atproto.server 100 - [ ] xx /xrpc/com.atproto.server.activateAccount 101 - [ ] xx /xrpc/com.atproto.server.checkAccountStatus 102 - [ ] xx /xrpc/com.atproto.server.confirmEmail 103 - [ ] UP /xrpc/com.atproto.server.createAccount 104 - [ ] xx /xrpc/com.atproto.server.createAppPassword 105 - [ ] AP /xrpc/com.atproto.server.createInviteCode 106 - [ ] xx /xrpc/com.atproto.server.createInviteCodes 107 - [ ] UP /xrpc/com.atproto.server.createSession 108 - [ ] xx /xrpc/com.atproto.server.deactivateAccount 109 - [ ] xx /xrpc/com.atproto.server.deleteAccount 110 - [ ] xx /xrpc/com.atproto.server.deleteSession 111 - [ ] UG /xrpc/com.atproto.server.describeServer 112 - [ ] xx /xrpc/com.atproto.server.getAccountInviteCodes 113 - [ ] AG /xrpc/com.atproto.server.getServiceAuth 114 - [ ] AG /xrpc/com.atproto.server.getSession 115 - [ ] xx /xrpc/com.atproto.server.listAppPasswords 116 - [ ] xx /xrpc/com.atproto.server.refreshSession 117 - [ ] xx /xrpc/com.atproto.server.requestAccountDelete 118 - [ ] xx /xrpc/com.atproto.server.requestEmailConfirmation 119 - [ ] xx /xrpc/com.atproto.server.requestEmailUpdate 120 - [ ] xx /xrpc/com.atproto.server.requestPasswordReset 121 - [ ] xx /xrpc/com.atproto.server.reserveSigningKey 122 - [ ] xx /xrpc/com.atproto.server.resetPassword 123 - [ ] xx /xrpc/com.atproto.server.revokeAppPassword 124 - [ ] xx /xrpc/com.atproto.server.updateEmail 125- com.atproto.sync 126 - [ ] UG /xrpc/com.atproto.sync.getBlob 127 - [ ] UG /xrpc/com.atproto.sync.getBlocks 128 - [ ] UG /xrpc/com.atproto.sync.getLatestCommit 129 - [ ] UG /xrpc/com.atproto.sync.getRecord 130 - [ ] UG /xrpc/com.atproto.sync.getRepo 131 - [ ] UG /xrpc/com.atproto.sync.getRepoStatus 132 - [ ] UG /xrpc/com.atproto.sync.listBlobs 133 - [ ] UG /xrpc/com.atproto.sync.listRepos 134 - [ ] UG /xrpc/com.atproto.sync.subscribeRepos 135 136## Deployment (NixOS) 137```nix 138{ 139 inputs = { 140 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 141 bluepds = { 142 url = "github:Teqed/bluesky-pds"; 143 }; 144 }; 145 outputs = { 146 nixpkgs, 147 bluepds, 148 ... 149 }: { 150 nixosConfigurations.mysystem = nixpkgs.lib.nixosSystem { 151 modules = [ 152 ({ pkgs, ... }: { 153 config.services.bluepds = { 154 enable = true; 155 host_name = "pds.example.com"; 156 listen_address = "0.0.0.0:8000"; 157 test = "true"; # Set to false for production 158 }; 159 }) 160 ]; 161 }; 162 }; 163} 164```