This Docker compose.yml
will allow you to run your own AT Proto server that can interact with the BlueSky app and social network.
The installer from https://github.com/bluesky-social/pds is designed for a clean virtual host and will take over the entire machine to run the PDS. This compose.yml
file will allow you to run it on your own machine (eg: a Raspberry Pi) whilst running other services/applications.
Once the image is running following continue following the instructions linked above to create your first user and log in.
Note: You might need to touch /opt/pds/pds.env
and restart the stack if things don't seem to be working.
Setting up the PDS in this way will require you to manage your own SSL/TLS certificates for the domain (*.example.com). Your proxy of choice should be able to help with this. Acquiring and configuring certificates is not covered here. If you use a Cloudflare tunnel then the certificates are all handled by Cloudflare for you with zero ongoing admin overhead.
The PDS can be proxied behind something like Apache, Nginx, Traefik or a Cloudflare tunnel. You will need to proxy port 80 and 443 for all requests to *.example.com/*
.
For a Cloudflare tunnel in particular you would need two rules:
Public Hostname | Path | Service | Origin Configurations |
---|---|---|---|
pds.example.com | / | http://localhost:6000 | httpHostHeader: pds.example.com |
*.example.com | /.well-known/ | http://localhost:6000 | httpHostHeader: *.example.com |
The second rule ensures that @user.example.com can be looked up via https (rather than DNS) and will return the did
for the user. This means that you don't have to add _atprot.user
TXT records to your DNS zone for your domain.
Other proxies configurations are left to the reader to work out 🙂
If things don't seem to be working you can look at the container logs with:
docker logs pds -f | jq -r '
(.time / 1000 | strflocaltime("%d %b %y %T") ) + " - " + (.level | tostring) + " - " +
if .req then
(.res.statusCode | tostring) + " - " + ( .req.headers["x-forwarded-for"] ) + " " + .req.url
elif .err then
( .err["$metadata"].httpStatusCode? | tostring ) + " -" + " [" + .name + "] " + ( .err.message | tostring )
else
if .status then
(.status | tostring)
else
" "
end
+ " > " + " [" + .name + "] " + .msg + " " +
if .did then
.did
else
.uri.host
end
end'
Copy/paste into your favourite shell to see the logs from the container.
Note: this requires jq
to be installed to parse the JSON log format.