feat: basic PDS playbook
This commit is contained in:
1 parent
0085300561
commit
7936661e00
8 files changed
+194
-1
No files matched your search
@@ -1,3 +1,7 @@
|
||||
# ---> Ansible
|
||||
*.retry
|
||||
.letta
|
||||
|
||||
# User-specific config
|
||||
inventory.yml
|
||||
vars/main.yml
|
||||
@@ -1,3 +1,84 @@
|
||||
# atproto-pds-ansible
|
||||
|
||||
Config for atproto PDS services using ansible
|
||||
Ansible playbook for deploying a self-hosted [Bluesky PDS](https://github.com/bluesky-social/pds) with Caddy (TLS) and Watchtower (auto-updates).
|
||||
|
||||
## What it deploys
|
||||
|
||||
- **PDS** — Bluesky Personal Data Server (`ghcr.io/bluesky-social/pds:0.4`)
|
||||
- **Caddy** — Reverse proxy with automatic TLS via Let's Encrypt
|
||||
- **Watchtower** — Pulls new PDS image versions hourly and recreates containers
|
||||
|
||||
## Requirements
|
||||
|
||||
- A server running Ubuntu 20.04/22.04/24.04 or Debian 11/12/13
|
||||
- SSH access as the `sysadmin` user (with sudo privileges)
|
||||
- A domain pointed at the server (A record for the hostname + wildcard `*.` subdomain for handles)
|
||||
- Ports 80 and 443 open to the internet
|
||||
- Ansible installed locally
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
cp inventory.yml.example inventory.yml # set your server IP
|
||||
cp vars/main.yml.example vars/main.yml # set your hostname and admin email
|
||||
```
|
||||
|
||||
Edit `inventory.yml`:
|
||||
|
||||
```yaml
|
||||
all:
|
||||
hosts:
|
||||
pds:
|
||||
ansible_host: 203.0.113.10
|
||||
```
|
||||
|
||||
Edit `vars/main.yml`:
|
||||
|
||||
```yaml
|
||||
pds_hostname: bsky.example.com
|
||||
pds_admin_email: you@example.com
|
||||
```
|
||||
|
||||
## Deploy
|
||||
|
||||
```bash
|
||||
ansible-playbook playbook.yml
|
||||
```
|
||||
|
||||
## What it does
|
||||
|
||||
**First run:** the official [PDS installer](https://github.com/bluesky-social/pds/blob/main/installer.sh) bootstraps Docker, generates secrets, and creates the initial database. Ansible then templates `compose.yaml` and `Caddyfile` over the installer's defaults and runs `docker compose up -d`.
|
||||
|
||||
**Subsequent runs:** the installer is skipped (guarded by `account.sqlite`). Ansible only applies changes if the templates have changed. `docker compose up -d` is a no-op when nothing changed.
|
||||
|
||||
## Variables
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `pds_hostname` | yes | — | Public DNS name for the PDS |
|
||||
| `pds_admin_email` | yes | — | Admin contact email (used by Caddy for Let's Encrypt) |
|
||||
| `pds_data_dir` | no | `/pds` | Data directory (must be `/pds` — the installer enforces this) |
|
||||
| `pds_image_tag` | no | `0.4` | PDS Docker image tag |
|
||||
|
||||
## Auto-updates
|
||||
|
||||
Watchtower checks every hour (`WATCHTOWER_POLL_INTERVAL=3600`) for new `0.4.x` images on `ghcr.io/bluesky-social/pds:0.4`. When a new image is found, it pulls it and recreates the container. Old images are cleaned up automatically.
|
||||
|
||||
## Post-deploy
|
||||
|
||||
Check that the PDS is healthy:
|
||||
|
||||
```bash
|
||||
curl https://your-hostname/xrpc/_health
|
||||
```
|
||||
|
||||
Create an account:
|
||||
|
||||
```bash
|
||||
pdsadmin account create
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- `pds.env` (containing JWT secret, admin password, PLC rotation key) is generated by the installer and not managed by Ansible. Edit it directly on the server to add SMTP or change settings.
|
||||
- The installer creates a `pds.service` systemd unit. It's left in place — it just runs `docker compose up -d` on boot. Docker's `restart: unless-stopped` policy also handles this independently.
|
||||
@@ -0,0 +1,3 @@
|
||||
[defaults]
|
||||
host_key_checking = False
|
||||
remote_user = sysadmin
|
||||
@@ -0,0 +1,4 @@
|
||||
all:
|
||||
hosts:
|
||||
pds:
|
||||
ansible_host: your.server.ip
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
- name: Deploy PDS
|
||||
hosts: pds
|
||||
vars_files:
|
||||
- vars/main.yml
|
||||
|
||||
tasks:
|
||||
- name: Run PDS installer (first time only)
|
||||
shell: >-
|
||||
echo "n" | bash <(curl -fsSL
|
||||
https://raw.githubusercontent.com/bluesky-social/pds/main/installer.sh)
|
||||
{{ pds_data_dir }} {{ pds_hostname }} {{ pds_admin_email }}
|
||||
args:
|
||||
creates: "{{ pds_data_dir }}/account.sqlite"
|
||||
|
||||
- name: Deploy compose.yaml
|
||||
template:
|
||||
src: templates/compose.yaml.j2
|
||||
dest: "{{ pds_data_dir }}/compose.yaml"
|
||||
mode: "0644"
|
||||
notify: apply changes
|
||||
|
||||
- name: Deploy Caddyfile
|
||||
template:
|
||||
src: templates/Caddyfile.j2
|
||||
dest: "{{ pds_data_dir }}/caddy/etc/caddy/Caddyfile"
|
||||
mode: "0644"
|
||||
notify: apply changes
|
||||
|
||||
- name: Download pdsadmin
|
||||
get_url:
|
||||
url: https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh
|
||||
dest: /usr/local/bin/pdsadmin
|
||||
mode: "0755"
|
||||
|
||||
handlers:
|
||||
- name: apply changes
|
||||
shell: cd {{ pds_data_dir }} && docker compose up -d && docker restart caddy
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
email {{ pds_admin_email }}
|
||||
on_demand_tls {
|
||||
ask http://localhost:3000/tls-check
|
||||
}
|
||||
}
|
||||
|
||||
*.{{ pds_hostname }}, {{ pds_hostname }} {
|
||||
tls {
|
||||
on_demand
|
||||
}
|
||||
log {
|
||||
output stdout
|
||||
format json
|
||||
}
|
||||
reverse_proxy http://localhost:3000
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
services:
|
||||
pds:
|
||||
container_name: pds
|
||||
image: ghcr.io/bluesky-social/pds:{{ pds_image_tag }}
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- type: bind
|
||||
source: {{ pds_data_dir }}
|
||||
target: {{ pds_data_dir }}
|
||||
env_file:
|
||||
- {{ pds_data_dir }}/pds.env
|
||||
|
||||
caddy:
|
||||
container_name: caddy
|
||||
image: caddy:2
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- type: bind
|
||||
source: {{ pds_data_dir }}/caddy/data
|
||||
target: /data
|
||||
- type: bind
|
||||
source: {{ pds_data_dir }}/caddy/etc/caddy
|
||||
target: /etc/caddy
|
||||
|
||||
watchtower:
|
||||
container_name: watchtower
|
||||
image: containrrr/watchtower:latest
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /var/run/docker.sock
|
||||
target: /var/run/docker.sock
|
||||
environment:
|
||||
- WATCHTOWER_CLEANUP=true
|
||||
- WATCHTOWER_POLL_INTERVAL=3600
|
||||
@@ -0,0 +1,8 @@
|
||||
# Required
|
||||
pds_hostname: pds.example.com
|
||||
pds_admin_email: admin@example.com
|
||||
|
||||
# Optional (defaults shown)
|
||||
# pds_data_dir must be /pds — the installer enforces this
|
||||
pds_data_dir: /pds
|
||||
pds_image_tag: "0.4"
|
||||
Reference in new issue
Block a user