Compare commits

..

No commits in common. "b336907cb3d317cb2c09dd93f34e6e7714fce33c" and "60cd32018833f4efc1a57ce20920f422cf73f80a" have entirely different histories.

7 changed files with 78 additions and 135 deletions

View file

@ -1,8 +0,0 @@
account.sh
.env
.git
.gitignore
config/
.vscode/
Makefile
README.md

1
.gitignore vendored
View file

@ -1,3 +1,2 @@
config/ config/
.vscode/ .vscode/
.env

View file

@ -2,8 +2,10 @@
# adapted from https://github.com/bluesky-social/pds/blob/v0.4.74/Dockerfile # adapted from https://github.com/bluesky-social/pds/blob/v0.4.74/Dockerfile
################################################################################ ################################################################################
FROM node:20.11-bookworm-slim AS pds-build FROM node:20.11-bookworm-slim AS pds-build
RUN npm install -g pnpm
RUN npm install -g pnpm && apt-get update && apt-get -y install unzip RUN apt-get update
RUN apt-get -y install unzip
# Download and extract the PDS archive # Download and extract the PDS archive
WORKDIR /app WORKDIR /app
@ -19,7 +21,8 @@ RUN pnpm install --prod=true --frozen-lockfile
################################################################################ ################################################################################
FROM node:20.11-bookworm-slim AS pds-runtime FROM node:20.11-bookworm-slim AS pds-runtime
RUN apt-get update && apt-get install -y \ RUN apt-get update
RUN apt-get install -y \
dumb-init \ dumb-init \
ca-certificates \ ca-certificates \
curl \ curl \
@ -28,9 +31,7 @@ RUN apt-get update && apt-get install -y \
lsb-release \ lsb-release \
openssl \ openssl \
sqlite3 \ sqlite3 \
bsdextrautils \
xxd xxd
# bsdextrautils for `column` command in the accounts script
WORKDIR /app WORKDIR /app
COPY --from=pds-build /app /app COPY --from=pds-build /app /app
@ -64,8 +65,9 @@ ENV PDS_CRAWLERS="https://bsky.network"
RUN mv pdsadmin.sh /usr/local/bin/pdsadmin && \ RUN mv pdsadmin.sh /usr/local/bin/pdsadmin && \
chmod +x /usr/local/bin/pdsadmin && \ chmod +x /usr/local/bin/pdsadmin && \
mkdir --mode=700 --parent ${PDS_DATADIR} && \ mkdir --mode=700 --parent ${PDS_DATADIR}
rm -rf pds-0.4.74 v0.4.74.zip && \
RUN rm -rf pds-0.4.74 v0.4.74.zip && \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*

View file

@ -2,33 +2,44 @@ REGISTRY=forgejo.gravityfargo.dev
OWNER=gravityfargo OWNER=gravityfargo
IMAGE=bluesky-pds IMAGE=bluesky-pds
TAG=0.4.74 TAG=0.4.74
DOMAIN=sheltersky.social CONFIG_FILE=config/pds.env
export DOCKER_BUILDKIT=1 export DOCKER_BUILDKIT=1
# export BUILDKIT_PROGRESS=plain # export BUILDKIT_PROGRESS=plain
.PHONY: build-tag
build-tag:
docker build --tag $(REGISTRY)/$(OWNER)/$(IMAGE):$(TAG) .
.PHONY: build .PHONY: build
build: build:
docker build --no-cache --tag $(REGISTRY)/$(OWNER)/$(IMAGE) . docker build --tag $(REGISTRY)/$(OWNER)/$(IMAGE):$(TAG) .
.PHONY: wsdump .PHONY: create-config
wsdump: create-config:
wsdump "wss://$(DOMAIN)/xrpc/com.atproto.sync.subscribeRepos?cursor=0" @if [ -f $(CONFIG_FILE) ]; then \
echo "Config already exists. Exiting."; \
exit 0; \
else \
mkdir -p config; \
echo "PDS_JWT_SECRET=" >> $(CONFIG_FILE); \
echo "PDS_ADMIN_PASSWORD=" >> $(CONFIG_FILE); \
echo "PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=" >> $(CONFIG_FILE); \
echo "PDS_HOSTNAME=" >> $(CONFIG_FILE); \
echo "Done."; \
echo "run 'make generate' to generate secrets"; \
fi
.PHONY: generate-env .PHONY: generate-secrets
generate-env: generate-secrets:
$(eval PDS_JWT_SECRET=$(shell openssl rand --hex 16)) @echo "Generating secrets..."
$(eval PDS_ADMIN_PASSWORD=$(shell openssl rand --hex 16)) $(eval GENERATE_SECURE_SECRET_CMD=openssl rand --hex 16)
$(eval PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=$(shell openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32)) $(eval GENERATE_K256_PRIVATE_KEY_CMD=openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32)
$(eval PDS_ADMIN_PASSWORD=$(shell ${GENERATE_SECURE_SECRET_CMD}))
$(eval PDS_JWT_SECRET=$(shell ${GENERATE_SECURE_SECRET_CMD}))
$(eval PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=$(shell ${GENERATE_K256_PRIVATE_KEY_CMD}))
@echo "PDS_JWT_SECRET=$(PDS_JWT_SECRET)" > .env @sed -i "s/^PDS_ADMIN_PASSWORD=.*/PDS_ADMIN_PASSWORD=${PDS_ADMIN_PASSWORD}/" $(CONFIG_FILE) || echo "PDS_ADMIN_PASSWORD=${PDS_ADMIN_PASSWORD}" >> $(CONFIG_FILE)
@echo "PDS_ADMIN_PASSWORD=$(PDS_ADMIN_PASSWORD)" >> .env @sed -i "s/^PDS_JWT_SECRET=.*/PDS_JWT_SECRET=${PDS_JWT_SECRET}/" $(CONFIG_FILE) || echo "PDS_JWT_SECRET=${PDS_JWT_SECRET}" >> $(CONFIG_FILE)
@echo "PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=$(PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX)" >> .env @sed -i "s/^PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=.*/PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX}/" $(CONFIG_FILE) || echo "PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX}" >> $(CONFIG_FILE)
@echo "PDS_HOSTNAME=$(DOMAIN)" >> .env
@echo "Done."
.PHONY: run .PHONY: run
run: run:

View file

@ -1,102 +1,39 @@
# bluesky-pds-docker # bluesky-pds-docker
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. It is required to set the hostname of the container to your FQDN or use host networking on a server whose hostname is the FQDN.
I can confirm it works behind Cloudflare's DNS proxy with Full (strict)
## Deployment ## Deployment
```bash ```bash
# Generate secret environment variables git clone https://forgejo.gravityfargo.dev/gravityfargo/bluesky-pds-docker.git && cd bluesky-pds-docker
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)
# pull and run the container make create-config
docker pull forgejo.gravityfargo.dev/gravityfargo/bluesky-pds make generate-secrets
# edit the config/pds.env file to set the FQDN
docker pull forgejo.gravityfargo.dev/gravityfargo/bluesky-pds:0.4.74
docker-compose up -d docker-compose up -d
# Create an account
docker exec -it bluesky-pds bash
pdsadmin account create
pdsadmin account list
# pdsadmin request-crawl bsky.network
``` ```
In your browser:
- Go to https://bsky-debug.app/handle and enter your new user, "HTTP Verification Method" needs to pass.
- [websocket-tester](https://piehost.com/websocket-tester) "wss://sheltersky.social/xrpc/com.atproto.sync.subscribeRepos?cursor=0" needs to display "Connection Established"
- https://boat.kelinci.net/ has a helpful tool to export your data.
- Log in with your new user and go to https://bsky.network/ to see your data.
### Example Docker Compose ### Example Docker Compose
Full list of additional Environment Variables can be found in the [packages/pds/src/config/env.ts](https://github.com/bluesky-social/atproto/blob/main/packages/pds/src/config/env.ts)
```yaml ```yaml
services: services:
bluesky-pds: bluesky-pds:
container_name: bluesky-pds container_name: bluesky-pds
image: forgejo.gravityfargo.dev/gravityfargo/bluesky-pds hostname: sheltersky.social
environment: image: bluesky-pds:0.4.74
PDS_JWT_SECRET: ... ports:
PDS_ADMIN_PASSWORD: ... - 3000:3000
PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX: ...
PDS_HOSTNAME: ...
volumes: volumes:
- ./config:/pds - ./config:/pds
``` ```
### Example Docker Compose with Traefik ## Contributing
```yaml - Fork and clone the repository
services: - `make build` to build the image
bluesky-pds:
container_name: bluesky-pds
image: forgejo.gravityfargo.dev/gravityfargo/bluesky-pds:latest
networks:
- proxy
env_file:
PDS_ADMIN_PASSWORD: ""
PDS_JWT_SECRET: ""
PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX: ""
PDS_HOSTNAME: example.com
PDS_EMAIL_SMTP_URL: smtps://smtp-relay.gmail.com:465/
PDS_EMAIL_FROM_ADDRESS: gravityfargo@gmail.com
volumes: ---
- /bluesky-pds:/pds
labels:
traefik.enable: "true"
traefik.http.**routers**.bluesky-pds-insecure.entrypoints: http
traefik.http.routers.bluesky-pds-insecure.rule: HostRegexp(`^.+\.example\.com$`) || Host(`example.social`)
traefik.http.routers.bluesky-pds-secure.entrypoints: https
traefik.http.routers.bluesky-pds-secure.rule: HostRegexp(`^.+\.example\.com$`) || Host(`example.social`)
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
traefik.http.routers.bluesky-pds-insecure.middlewares: BlueskyHeaders@file
```
#### Middleware
I think file configs are cleaner than having a billion labels.
```yaml
http:
middlewares:
BlueskyHeaders:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
- POST
- DELETE
accessControlAllowHeaders: "*"
accessControlAllowOriginList: "*"
addVaryHeader: true
stsSeconds: 63072000
```
## Development Notes
```bash It's my preference not to host any code on GitHub, but I've enabled signing in with Github because most people already have that, and I don't want the hassle of a new login to prevent contributors. You cannot create new repositories on this Forgejo instance, but forking is allowed. The upstream PDS repository is on Github.
pamac install jq
```

View file

@ -2,10 +2,8 @@ services:
bluesky-pds-dev: bluesky-pds-dev:
container_name: bluesky-pds-dev container_name: bluesky-pds-dev
hostname: sheltersky.social hostname: sheltersky.social
image: forgejo.gravityfargo.dev/gravityfargo/bluesky-pds:0.4.74 image: bluesky-pds:0.4.74
ports: ports:
- 3000:3000 - 3000:3000
volumes: volumes:
- ./config:/pds - ./config:/pds
env_file:
- .env

View file

@ -1,10 +1,24 @@
#!/bin/bash #!/bin/bash
LOCAL_IP=$(hostname --all-ip-addresses | awk '{ print $1 }')
PUBLIC_IP=$(curl https://ipinfo.io/ip --silent) PUBLIC_IP=$(curl https://ipinfo.io/ip --silent)
HOSTNAME=$(hostname) HOSTNAME=$(hostname)
CONFIG_FILE=/pds/pds.env
function main { function main {
# pds hostname must be the same as the hostname of the container
if [[ "${PDS_HOSTNAME}" != "${HOSTNAME}" ]]; then
echo "PDS_HOSTNAME must be the same as the hostname of the container"
echo "Set the hostname for the container before running."
echo "Current hostname: ${HOSTNAME}"
echo "PDS_HOSTNAME: ${PDS_HOSTNAME}"
exit 1
fi
if [[ -z "${PDS_HOSTNAME}" ]]; then
echo "No public DNS address specified"
exit 1
fi
if [[ -z "${PDS_JWT_SECRET}" ]]; then if [[ -z "${PDS_JWT_SECRET}" ]]; then
echo "PDS_JWT_SECRET not specified" echo "PDS_JWT_SECRET not specified"
exit 1 exit 1
@ -20,29 +34,19 @@ function main {
exit 1 exit 1
fi fi
# set PDS_HOSTNAME to hostname if not set
if [[ -z "${PDS_HOSTNAME}" ]]; then
echo "PDS_HOSTNAME not specified"
exit 1
fi
# create the config if it does not exist
if [[ ! -f ${CONFIG_FILE} ]]; then
echo "PDS_JWT_SECRET=${PDS_JWT_SECRET}" >${CONFIG_FILE}
echo "PDS_ADMIN_PASSWORD=${PDS_ADMIN_PASSWORD}" >>${CONFIG_FILE}
echo "PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX}" >>${CONFIG_FILE}
echo "PDS_HOSTNAME=${PDS_HOSTNAME}" >>${CONFIG_FILE}
echo "PDS_CRAWLERS=https://bsky.network" >>${CONFIG_FILE}
fi
cat <<STARTED_MESSAGE cat <<STARTED_MESSAGE
======================================================================== ========================================================================
PDS Started PDS Started
------------------------------------------------------------------------ ------------------------------------------------------------------------
HOSTNAME: ${HOSTNAME} Hostname : ${PDS_HOSTNAME}
PUBLIC_IP: ${PUBLIC_IP} : http://${PDS_HOSTNAME}:3000/xrpc/_health
PDS_HOSTNAME: ${PDS_HOSTNAME}
Local IP : ${LOCAL_IP}
: http://${LOCAL_IP}:3000/xrpc/_health
Public IP : ${PUBLIC_IP}
: http://${PUBLIC_IP}:3000/xrpc/_health
======================================================================== ========================================================================
STARTED_MESSAGE STARTED_MESSAGE