An atproto PDS written in Go
1# Cocoon 2 3> [!WARNING] 4I migrated and have been running my main account on this PDS for months now without issue, however, I am still not responsible if things go awry, particularly during account migration. Please use caution. 5 6Cocoon is a PDS implementation in Go. It is highly experimental, and is not ready for any production use. 7 8## Quick Start with Docker Compose 9 10### Prerequisites 11 12- Docker and Docker Compose installed 13- A domain name pointing to your server (for automatic HTTPS) 14- Ports 80 and 443 open in i.e. UFW 15 16### Installation 17 181. **Clone the repository** 19 ```bash 20 git clone https://github.com/haileyok/cocoon.git 21 cd cocoon 22 ``` 23 242. **Create your configuration file** 25 ```bash 26 cp .env.example .env 27 ``` 28 293. **Edit `.env` with your settings** 30 31 Required settings: 32 ```bash 33 COCOON_DID="did:web:your-domain.com" 34 COCOON_HOSTNAME="your-domain.com" 35 COCOON_CONTACT_EMAIL="you@example.com" 36 COCOON_RELAYS="https://bsky.network" 37 38 # Generate with: openssl rand -hex 16 39 COCOON_ADMIN_PASSWORD="your-secure-password" 40 41 # Generate with: openssl rand -hex 32 42 COCOON_SESSION_SECRET="your-session-secret" 43 ``` 44 454. **Start the services** 46 ```bash 47 # Pull pre-built image from GitHub Container Registry 48 docker-compose pull 49 docker-compose up -d 50 ``` 51 52 Or build locally: 53 ```bash 54 docker-compose build 55 docker-compose up -d 56 ``` 57 585. **Get your invite code** 59 60 On first run, an invite code is automatically created. View it with: 61 ```bash 62 docker-compose logs create-invite 63 ``` 64 65 Or check the saved file: 66 ```bash 67 cat keys/initial-invite-code.txt 68 ``` 69 70 **IMPORTANT**: Save this invite code! You'll need it to create your first account. 71 726. **Monitor the services** 73 ```bash 74 docker-compose logs -f 75 ``` 76 77### What Gets Set Up 78 79The Docker Compose setup includes: 80 81- **init-keys**: Automatically generates cryptographic keys (rotation key and JWK) on first run 82- **cocoon**: The main PDS service running on port 8080 83- **create-invite**: Automatically creates an initial invite code after Cocoon starts (first run only) 84- **caddy**: Reverse proxy with automatic HTTPS via Let's Encrypt 85 86### Data Persistence 87 88The following directories will be created automatically: 89 90- `./keys/` - Cryptographic keys (generated automatically) 91 - `rotation.key` - PDS rotation key 92 - `jwk.key` - JWK private key 93 - `initial-invite-code.txt` - Your first invite code (first run only) 94- `./data/` - SQLite database and blockstore 95- Docker volumes for Caddy configuration and certificates 96 97### Optional Configuration 98 99#### SMTP Email Settings 100```bash 101COCOON_SMTP_USER="your-smtp-username" 102COCOON_SMTP_PASS="your-smtp-password" 103COCOON_SMTP_HOST="smtp.example.com" 104COCOON_SMTP_PORT="587" 105COCOON_SMTP_EMAIL="noreply@example.com" 106COCOON_SMTP_NAME="Cocoon PDS" 107``` 108 109#### S3 Storage 110```bash 111COCOON_S3_BACKUPS_ENABLED=true 112COCOON_S3_BLOBSTORE_ENABLED=true 113COCOON_S3_REGION="us-east-1" 114COCOON_S3_BUCKET="your-bucket" 115COCOON_S3_ENDPOINT="https://s3.amazonaws.com" 116COCOON_S3_ACCESS_KEY="your-access-key" 117COCOON_S3_SECRET_KEY="your-secret-key" 118``` 119 120### Management Commands 121 122Create an invite code: 123```bash 124docker exec cocoon-pds /cocoon create-invite-code --uses 1 125``` 126 127Reset a user's password: 128```bash 129docker exec cocoon-pds /cocoon reset-password --did "did:plc:xxx" 130``` 131 132### Updating 133 134```bash 135docker-compose pull 136docker-compose up -d 137``` 138 139## Implemented Endpoints 140 141> [!NOTE] 142Just because something is implemented doesn't mean it is finished. Tons of these are returning bad errors, don't do validation properly, etc. I'll make a "second pass" checklist at some point to do all of that. 143 144### Identity 145 146- [x] `com.atproto.identity.getRecommendedDidCredentials` 147- [x] `com.atproto.identity.requestPlcOperationSignature` 148- [x] `com.atproto.identity.resolveHandle` 149- [x] `com.atproto.identity.signPlcOperation` 150- [x] `com.atproto.identity.submitPlcOperation` 151- [x] `com.atproto.identity.updateHandle` 152 153### Repo 154 155- [x] `com.atproto.repo.applyWrites` 156- [x] `com.atproto.repo.createRecord` 157- [x] `com.atproto.repo.putRecord` 158- [x] `com.atproto.repo.deleteRecord` 159- [x] `com.atproto.repo.describeRepo` 160- [x] `com.atproto.repo.getRecord` 161- [x] `com.atproto.repo.importRepo` (Works "okay". Use with extreme caution.) 162- [x] `com.atproto.repo.listRecords` 163- [ ] `com.atproto.repo.listMissingBlobs` 164 165### Server 166 167- [x] `com.atproto.server.activateAccount` 168- [x] `com.atproto.server.checkAccountStatus` 169- [x] `com.atproto.server.confirmEmail` 170- [x] `com.atproto.server.createAccount` 171- [x] `com.atproto.server.createInviteCode` 172- [x] `com.atproto.server.createInviteCodes` 173- [x] `com.atproto.server.deactivateAccount` 174- [ ] `com.atproto.server.deleteAccount` 175- [x] `com.atproto.server.deleteSession` 176- [x] `com.atproto.server.describeServer` 177- [ ] `com.atproto.server.getAccountInviteCodes` 178- [ ] `com.atproto.server.getServiceAuth` 179- ~~[ ] `com.atproto.server.listAppPasswords`~~ - not going to add app passwords 180- [x] `com.atproto.server.refreshSession` 181- [ ] `com.atproto.server.requestAccountDelete` 182- [x] `com.atproto.server.requestEmailConfirmation` 183- [x] `com.atproto.server.requestEmailUpdate` 184- [x] `com.atproto.server.requestPasswordReset` 185- [ ] `com.atproto.server.reserveSigningKey` 186- [x] `com.atproto.server.resetPassword` 187- ~~[] `com.atproto.server.revokeAppPassword`~~ - not going to add app passwords 188- [x] `com.atproto.server.updateEmail` 189 190### Sync 191 192- [x] `com.atproto.sync.getBlob` 193- [x] `com.atproto.sync.getBlocks` 194- [x] `com.atproto.sync.getLatestCommit` 195- [x] `com.atproto.sync.getRecord` 196- [x] `com.atproto.sync.getRepoStatus` 197- [x] `com.atproto.sync.getRepo` 198- [x] `com.atproto.sync.listBlobs` 199- [x] `com.atproto.sync.listRepos` 200- ~~[ ] `com.atproto.sync.notifyOfUpdate`~~ - BGS doesn't even have this implemented lol 201- [x] `com.atproto.sync.requestCrawl` 202- [x] `com.atproto.sync.subscribeRepos` 203 204### Other 205 206- [ ] `com.atproto.label.queryLabels` 207- [x] `com.atproto.moderation.createReport` (Note: this should be handled by proxying, not actually implemented in the PDS) 208- [x] `app.bsky.actor.getPreferences` 209- [x] `app.bsky.actor.putPreferences` 210 211## License 212 213This project is licensed under MIT license. `server/static/pico.css` is also licensed under MIT license, available at [https://github.com/picocss/pico/](https://github.com/picocss/pico/).