assets | ||
base | ||
.dockerignore | ||
.gitignore | ||
docker-compose.yaml | ||
Dockerfile | ||
entrypoint.sh | ||
example.env | ||
LICENSE | ||
Makefile | ||
README.md |
bluesky-pds-docker
A self-contained Docker image for the Bluesky PDS (Personal Data Server) for use with Traefik. This image is pinned to v0.4.74.
It is required to run the instance behind a proxy (like traefik) to generate SSL certificates. This will not work otherwise. The standard pds install includes caddy to handle this. A wildcard DNS assignment along with a wildcard SSL certificate is required. I use Cloudflare for this, see the screenshot below.
Cloudflare's DNS Proxy Service will not work for this setup because of the email verification requirement. You must use the DNS only service.
This is not intended for production, and I am not responsible for any data loss or security issues. This is a personal project, and I am not affiliated with Bluesky.
Deployment
Before changing images or upgrading, backup the files made in the volume.
Reqirements
I haven't verified these are the minimum requirements, but they are what I found to be necessary after starting this readme. I probably had some dependencies installed already.
Manjaro/Arch
sudo pacman -S jq
Debian/Ubunutu
sudo apt install make xxd
Setup
Generate secrets and add them to .env
file. See example.env as an example.
# Generate secret environment variables
echo PDS_ADMIN_PASSWORD: $(openssl rand --hex 16)
echo PDS_JWT_SECRET: $(openssl rand --hex 16)
echo PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX: $(openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32)
Docker Compose Setup
Full list of additional Environment Variables provided by bluesky upstream can be found in the packages/pds/src/config/env.ts
By default, the image uses 1000:1000 as the UID:GID for the user. This can be changed by setting the PUID
and PGID
environment variables.
The compose element hostname
must be the same value as PDS_HOSTNAME
.
Traefik
# Traefik Proxy
services:
bluesky-pds:
container_name: bluesky-pds
hostname: example.com
image: gravityfargo/bluesky-pds:0.4.74
networks:
- proxy
environment:
# Define variables here or in a .env file
PDS_JWT_SECRET: ...
PDS_ADMIN_PASSWORD: ...
PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX: ...
PDS_HOSTNAME: example.com
PDS_EMAIL_SMTP_URL: smtps://resend:<your api key here>@smtp.resend.com:465/
PDS_EMAIL_FROM_ADDRESS: admin@your.domain
PUID: 1005
PGID: 1005
volumes:
- ./bluesky-pds:/pds
labels:
traefik.enable: "true"
traefik.http.routers.bluesky-pds-insecure.entrypoints: http
traefik.http.routers.bluesky-pds-insecure.rule: HostRegexp(`^.+\.${URL_NAME}\.${URL_SUFFIX}$`) || Host(`${PDS_HOSTNAME}`)
# traefik.http.routers.bluesky-pds-insecure.middlewares: BlueskyHeaders@file
traefik.http.routers.bluesky-pds-secure.entrypoints: https
traefik.http.routers.bluesky-pds-secure.rule: HostRegexp(`^.+\.${URL_NAME}\.${URL_SUFFIX}$`) || Host(`${PDS_HOSTNAME}`)
traefik.http.routers.bluesky-pds-secure.tls: "true"
traefik.http.services.bluesky-pds.loadbalancer.server.scheme: http
traefik.http.services.bluesky-pds.loadbalancer.server.port: 3000
# traefik.http.routers.bluesky-pds-secure.middlewares: BlueskyHeaders@file
Standalone
I do not run this, but it should be possible.
# Standalone, you'll need to add a proxy in front of this with SSL.
services:
bluesky-pds:
container_name: bluesky-pds
hostname: example.com
image: gravityfargo/bluesky-pds:0.4.74
environment:
# Define variables here or in a .env file
PDS_JWT_SECRET: ...
PDS_ADMIN_PASSWORD: ...
PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX: ...
PDS_HOSTNAME: example.com
PDS_EMAIL_SMTP_URL: ""
PDS_EMAIL_FROM_ADDRESS: ""
PUID: 1005
PGID: 1005
volumes:
- ./bluesky-pds:/pds
Middleware
I think file configs are cleaner than having a billion labels. This is not required, but it's nice to have.
# middleware.yaml
http:
middlewares:
BlueskyHeaders:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
- POST
- DELETE
accessControlAllowHeaders: "*"
accessControlAllowOriginList: "*"
addVaryHeader: true
stsSeconds: 63072000
Optional Proxy Network
docker network create --subnet=192.168.1.0/24 --ipv6 --attachable proxy
# /etc/docker/daemon.json
# {
# "ipv6": true,
# "fixed-cidr-v6": "2001:db8:1::/64"
# }
Cloudflare DNS
Protonmail SMTP
PDS_EMAIL_SMTP_URL: smtp://user@example.com:TOKEN@smtp.protonmail.ch:587/
PDS_EMAIL_FROM_ADDRESS: user@example.com
Development
The development enviornment must be behind a proxy to generate SSL certificates. This will not work otherwise. In my case, I use Traefik installed on a VPS that's dedicated to development.
I suggest buying a domain name for testing. I have one I use that's for a seperate project, but getting a throwaway domain is also an option. Millage may vary.
make generate-env
Then set the variables
PDS_HOSTNAME=example.com
URL_NAME=example
URL_SUFFIX=com
Build the base image. This will take a while.
make build-base
Make edits as needed. Then build the dev image for testing.
make build-tag TAG=dev
Run the dev image.
make run
# or
docker-compose up