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/).