Month: February 2024

  • Bluesky PDS Without Docker

    Here’s how I got a self-hosted PDS (personal data server) running without docker.

    This can be useful if you want to run the PDS on an existing machine or just don’t like docker. I came up with these steps by emulating what the installer script does.

    My setup uses nginx and a wildcard TLS cert for my PDS domain.

    Get the code

    Clone the PDS repo

    $ git clone https://github.com/bluesky-social/pds

    Set up nginx

    I use certbot to issue wildcard certs for my domains. See my wildcard cert script here. Note that you will need to set up credentials for your nameservers. I’m not aware of a way in nginx to issue certs on-demand like the example caddy config does.

    Here’s my nginx config for the PDS.

    server {
    listen 80;
    server_name hellthread.pro *.hellthread.pro;
    return 302 https://$host$request_uri;
    }

    server {
    listen 443 ssl http2;
    server_name hellthread.pro *.hellthread.pro;
    ssl_certificate /etc/letsencrypt/live/hellthread.pro/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hellthread.pro/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
    include proxy_params;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_pass http://127.0.0.1:3002;
    }
    }

    Configure your .env file

    Adjust the top 4 options, filling in your domain and generating keys with the following commands:

    Use this for the JWT_SECRET:

    $ openssl rand --hex 16

    Use this twice to generate the admin password and rotation key:

    $ openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32
    PDS_HOSTNAME="your domain here"
    PDS_JWT_SECRET="generated secret"
    PDS_ADMIN_PASSWORD="generated key"
    PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX="another generated key"

    PDS_DATA_DIRECTORY=./data
    PDS_BLOBSTORE_DISK_LOCATION=./data/blocks
    PDS_DID_PLC_URL=https://plc.directory
    PDS_BSKY_APP_VIEW_URL=https://api.bsky.app
    PDS_BSKY_APP_VIEW_DID=did:web:api.bsky.app
    PDS_REPORT_SERVICE_URL=https://mod.bsky.app
    PDS_REPORT_SERVICE_DID=did:plc:ar7c4by46qjdydhdevvrndac
    PDS_CRAWLERS=https://bsky.network
    LOG_ENABLED=true
    NODE_ENV=production
    PDS_PORT=3002

    Run the PDS

    Be sure to install the dependencies:

    $ cd service
    $ pnpm install --production --frozen-lockfile
    $ mkdir -p data/blocks

    This is the systemd setup I use to run the PDS. Add your own user unit with the following steps:

    $ mkdir -p ~/.config/systemd/user
    $ $EDITOR ~/.config/systemd/user/pds.service
    # copy in the example below and adjust as needed
    $ systemctl --user daemon-reload
    $ systemctl --user enable --now pds

    pds.service:

    [Unit]
    Description=atproto personal data server

    [Service]
    WorkingDirectory=/home/ben/workspace/pds/service
    ExecStart=/usr/bin/node --enable-source-maps index.js
    Restart=on-failure
    EnvironmentFile=/home/ben/workspace/pds/service/.env

    [Install]
    WantedBy=default.target

    View the logs from journalctl like this:

    $ journalctl --user --output=cat --follow --unit pds | jq

    You can run the pdsadmin commands by setting the PDS_ENV_FILE variable like this:

    ben@odin ~/w/p/pdsadmin (main)> PDS_ENV_FILE=../service/.env bash account.sh list
    Handle Email DID
    ben.hellthread.pro ben@hellthread.pro did:plc:g5isluhi3wkw557ucarjgtgy

    Update

    To update your PDS, use git pull in the directory you cloned it in. Then update dependencies in the service subdirectory and restart the unit:

    $ cd pds
    $ git pull
    $ cd service
    $ pnpm install --production --frozen-lockfile
    $ systemctl --user restart pds
  • Solar Ride Paint Restoration

    This is our pinball machine. We’ve owned it for about 3 years at this point.
    One of the previous owners covered the cabinet for some reason with this faux woodgrain paintjob. I’ve been meaning to do something with it since we got it and today happened to be that time.

    My buddy Joey sent me a text the other day after he saw it for the first time offering to help me get it restored so of course I took him up on it.

    It’s not done yet but we made a good amount of progress with some light sanding and latex paint remover.

    Bonus dog in this pic. It’s in pretty good condition under the 2 layers of paint and at least one layer of a clear coat. Looking forward to seeing the finished product!