Retire Gondulf and move StarPunk to v2.0.0 with Pocket ID login

StarPunk 2.0.0 logs in with Pocket ID and issues its own Micropub tokens
(ADR-064 in the StarPunk repo), so the Gondulf IndieAuth server is no
longer used. Removes its task, templates, Caddy route, subdomain and
service entry, and moves its DNS record to removed_records.

The StarPunk template was still on v1.6.0-rc.2 with Gondulf hairpin
hosts; deploying it would have broken login. It now matches production:
v2.0.0, Pocket ID hairpin, OIDC client from vault_starpunk.pocketid and
the admin sub in starpunk_admin_sub.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Phil
2026-10-31 11:52:07 -06:00
co-authored by Claude Opus 5.5
parent a08402f0ac
commit 6dfb58d3f1
13 changed files with 27 additions and 99 deletions
+5 -5
View File
@@ -81,7 +81,7 @@ subdomain.
and the Warhammer RSS feed (09:10). and the Warhammer RSS feed (09:10).
### Docker role categories (`roles/docker/tasks/<category>/`) ### Docker role categories (`roles/docker/tasks/<category>/`)
- **infrastructure/**: Caddy, Pocket ID, Gondulf (IndieAuth), Dockge - **infrastructure/**: Caddy, Pocket ID, Dockge
- **development/**: Gitea (+ act_runner), ByteStash - **development/**: Gitea (+ act_runner), ByteStash
- **media/**: Audiobookshelf, Kavita, Karakeep (files named `hoarder`), Manyfold - **media/**: Audiobookshelf, Kavita, Karakeep (files named `hoarder`), Manyfold
- **productivity/**: Paperless-ngx, Baikal, Syncthing, HeyForm, Dawarich, Obsidian LiveSync, Gokapi - **productivity/**: Paperless-ngx, Baikal, Syncthing, HeyForm, Dawarich, Obsidian LiveSync, Gokapi
@@ -127,11 +127,11 @@ user (`vault_aws_dns`). It also deletes the records listed under
### SSO (Pocket ID) ### SSO (Pocket ID)
Pocket ID (`id.thesatelliteoflove.com`) replaced Authentik on 2026-10-31. Pocket ID (`id.thesatelliteoflove.com`) replaced Authentik on 2026-10-31.
Apps that log in with it: Gitea, ByteStash, Audiobookshelf, Kavita, Karakeep, Apps that log in with it: Gitea, ByteStash, Audiobookshelf, Kavita, Karakeep,
Manyfold, Paperless-ngx, Gokapi, GoToSocial. Some read the client from env Manyfold, Paperless-ngx, Gokapi, GoToSocial, StarPunk. Some read the client from env
vars; Gitea, Audiobookshelf and Kavita store it in their own database (set in vars; Gitea, Audiobookshelf and Kavita store it in their own database (set in
their admin UI). OIDC clients are created in Pocket ID's UI and their ID and their admin UI). OIDC clients are created in Pocket ID's UI and their ID and
secret go in the vault as `vault_<service>.pocketid`. StarPunk logs in with secret go in the vault as `vault_<service>.pocketid`. StarPunk (v2.0.0+) also
IndieAuth through Gondulf instead. runs its own IndieAuth server so Micropub apps can post; Gondulf was retired.
### Shared Docker Network (`lava`) ### Shared Docker Network (`lava`)
Created by the docker role as `{{ docker.subnet }}` with `ip_range: {{ docker.ip_range }}`. Docker only hands out dynamic addresses from that range, so `172.20.0.x` is reserved for fixed IPs: Caddy (`docker.hairpin_ip`, .5) and Gitea (`docker.gitea_ip`, .6). Both need fixed IPs because ufw-docker firewall rules point at container IPs. A network without the range (the 2024 original) is migrated once with `migrate-lava-network.yml`. Created by the docker role as `{{ docker.subnet }}` with `ip_range: {{ docker.ip_range }}`. Docker only hands out dynamic addresses from that range, so `172.20.0.x` is reserved for fixed IPs: Caddy (`docker.hairpin_ip`, .5) and Gitea (`docker.gitea_ip`, .6). Both need fixed IPs because ufw-docker firewall rules point at container IPs. A network without the range (the 2024 original) is migrated once with `migrate-lava-network.yml`.
@@ -146,7 +146,7 @@ extra_hosts:
``` ```
Most often needed for `subdomains.pocketid` (OIDC); also `subdomains.git` Most often needed for `subdomains.pocketid` (OIDC); also `subdomains.git`
(Gitea itself), `subdomains.gondulf` and `primary_domain` (StarPunk). (Gitea itself) and `primary_domain` (StarPunk).
### Template pattern ### Template pattern
```yaml ```yaml
+1 -2
View File
@@ -23,7 +23,6 @@ takes ports 80/443 and passes each subdomain to the right container.
|---|---|---|---| |---|---|---|---|
| Infrastructure | Caddy (reverse proxy, static sites) | — | — | | Infrastructure | Caddy (reverse proxy, static sites) | — | — |
| | Pocket ID (passkey OIDC provider) | id.thesatelliteoflove.com | passkeys | | | Pocket ID (passkey OIDC provider) | id.thesatelliteoflove.com | passkeys |
| | Gondulf (IndieAuth for the main site) | gondulf.thesatelliteoflove.com | email code |
| | Dockge (compose stack manager) | port 5001, no public route | local | | | Dockge (compose stack manager) | port 5001, no public route | local |
| Development | Gitea + Actions runner | git.thesatelliteoflove.com (SSH on port 222) | Pocket ID | | Development | Gitea + Actions runner | git.thesatelliteoflove.com (SSH on port 222) | Pocket ID |
| | ByteStash (code snippets) | snippets.thesatelliteoflove.com | Pocket ID | | | ByteStash (code snippets) | snippets.thesatelliteoflove.com | Pocket ID |
@@ -40,7 +39,7 @@ takes ports 80/443 and passes each subdomain to the right container.
| | Gokapi (file sharing) | gokapi.thesatelliteoflove.com | Pocket ID | | | Gokapi (file sharing) | gokapi.thesatelliteoflove.com | Pocket ID |
| Communication | GoToSocial (fediverse) | social.thesatelliteoflove.com | Pocket ID | | Communication | GoToSocial (fediverse) | social.thesatelliteoflove.com | Pocket ID |
| | Listmonk (mailing lists) | listmonk.nerder.land | local | | | Listmonk (mailing lists) | listmonk.nerder.land | local |
| | StarPunk (Micropub for the main site) | starpunk.thesatelliteoflove.com | IndieAuth | | | StarPunk (Micropub for the main site) | starpunk.thesatelliteoflove.com | Pocket ID |
| Monitoring | Changedetection | watcher.thesatelliteoflove.com | local | | Monitoring | Changedetection | watcher.thesatelliteoflove.com | local |
| | Apprise API (notifications) | Tailscale only, port 8000 | — | | | Apprise API (notifications) | Tailscale only, port 8000 | — |
| | Gotify + iGotify assistant | gotify.thesatelliteoflove.com, gotify-assistant.thesatelliteoflove.com | local | | | Gotify + iGotify assistant | gotify.thesatelliteoflove.com, gotify-assistant.thesatelliteoflove.com | local |
+2 -2
View File
@@ -17,8 +17,6 @@
domains: domains:
- name: thesatelliteoflove.com - name: thesatelliteoflove.com
dns_records: dns_records:
- name: "gondulf"
ip: "{{ network.netcup_ip }}"
- name: "starpunk" - name: "starpunk"
ip: "{{ network.netcup_ip }}" ip: "{{ network.netcup_ip }}"
- name: "git" - name: "git"
@@ -88,6 +86,8 @@
ip: "{{ network.netcup_ip }}" ip: "{{ network.netcup_ip }}"
- name: "auth" # Authentik, replaced by Pocket ID - name: "auth" # Authentik, replaced by Pocket ID
ip: "{{ network.netcup_ip }}" ip: "{{ network.netcup_ip }}"
- name: "gondulf" # IndieAuth, replaced by StarPunk v2 + Pocket ID
ip: "{{ network.netcup_ip }}"
- name: "files" - name: "files"
ip: "{{ network.netcup_ip }}" ip: "{{ network.netcup_ip }}"
- name: "kanboard" - name: "kanboard"
-1
View File
@@ -26,7 +26,6 @@ subdomains:
listmonk: "listmonk.{{ secondary_domain }}" # Listmonk mailing list listmonk: "listmonk.{{ secondary_domain }}" # Listmonk mailing list
gokapi: "gokapi.{{ primary_domain }}" # Gokapi file sharing gokapi: "gokapi.{{ primary_domain }}" # Gokapi file sharing
pocketid: "id.{{ primary_domain }}" # Pocket ID passkey OIDC pocketid: "id.{{ primary_domain }}" # Pocket ID passkey OIDC
gondulf: "gondulf.{{ primary_domain }}" # IndieAuth for the main site
starpunk: "starpunk.{{ primary_domain }}" # Micropub for the main site starpunk: "starpunk.{{ primary_domain }}" # Micropub for the main site
# Email domains for notifications # Email domains for notifications
+4 -1
View File
@@ -2,7 +2,7 @@
# Service categories for organization # Service categories for organization
service_categories: service_categories:
infrastructure: ["caddy", "dockge", "gondulf"] infrastructure: ["caddy", "dockge"]
development: ["gitea", "bytestash"] development: ["gitea", "bytestash"]
media: ["audiobookshelf", "kavita", "hoarder", "manyfold"] media: ["audiobookshelf", "kavita", "hoarder", "manyfold"]
productivity: ["paperlessngx", "baikal", "syncthing", "heyform", "dawarich", "obsidian-livesync", "gokapi"] productivity: ["paperlessngx", "baikal", "syncthing", "heyform", "dawarich", "obsidian-livesync", "gokapi"]
@@ -19,5 +19,8 @@ services:
dawarich: dawarich:
db_name: "dawarich" db_name: "dawarich"
db_user: "dawarich" db_user: "dawarich"
# StarPunk admin: Pocket ID user ID (sub) of phil
starpunk_admin_sub: "5754855f-0a30-4755-9609-7294209e40f4"
# Gokapi super admin: must match the Pocket ID account email # Gokapi super admin: must match the Pocket ID account email
gokapi_admin_email: "phil@{{ primary_domain }}" gokapi_admin_email: "phil@{{ primary_domain }}"
+4 -5
View File
@@ -26,7 +26,6 @@ Tags: each category file has a category tag, each service its own tag.
|---|---|---| |---|---|---|
| `caddy` | Caddy | Fixed IP 172.20.0.5. Ports 80/443 (+443/udp). `Caddyfile.j2` changes restart it via a handler; the stack itself is deployed with `recreate: never`. Static sites are served from `/opt/stacks/caddy/site/`. | | `caddy` | Caddy | Fixed IP 172.20.0.5. Ports 80/443 (+443/udp). `Caddyfile.j2` changes restart it via a handler; the stack itself is deployed with `recreate: never`. Static sites are served from `/opt/stacks/caddy/site/`. |
| `pocketid` | Pocket ID v2 | Passkey OIDC provider at `id.`. OIDC clients are created in its web UI; their IDs and secrets go in the vault. | | `pocketid` | Pocket ID v2 | Passkey OIDC provider at `id.`. OIDC clients are created in its web UI; their IDs and secrets go in the vault. |
| `gondulf` | Gondulf | IndieAuth server for the main site (own image from Gitea). Sends login codes by email through Resend. |
| `dockge` | Dockge | Compose UI on port 5001, managing `/opt/stacks`. | | `dockge` | Dockge | Compose UI on port 5001, managing `/opt/stacks`. |
### Development (`development`) ### Development (`development`)
@@ -59,7 +58,7 @@ Tags: each category file has a category tag, each service its own tag.
|---|---|---| |---|---|---|
| `gotosocial` | GoToSocial | Pocket ID through env vars. Account domain is the apex; Caddy serves WebFinger there. Daily S3 backup of its volume. | | `gotosocial` | GoToSocial | Pocket ID through env vars. Account domain is the apex; Caddy serves WebFinger there. Daily S3 backup of its volume. |
| `listmonk` | Listmonk | Postgres 17. On `listmonk.nerder.land`. | | `listmonk` | Listmonk | Postgres 17. On `listmonk.nerder.land`. |
| `starpunk` | StarPunk | Micropub server for the main site (own image from Gitea). Logs in through Gondulf. | | `starpunk` | StarPunk | Micropub server for the main site (own image from Gitea). Admin login via Pocket ID; issues its own Micropub tokens. |
### Monitoring (`monitoring`) ### Monitoring (`monitoring`)
| Tag | Service | Notes | | Tag | Service | Notes |
@@ -97,9 +96,9 @@ in from the internet; the Caddy and Gitea task files add those rules.
Containers labelled `mag37.dockcheck.update: true` are updated automatically Containers labelled `mag37.dockcheck.update: true` are updated automatically
each morning by dockcheck (set up in the cron role). Containers without the each morning by dockcheck (set up in the cron role). Containers without the
label (Gondulf, StarPunk, Listmonk, HeyForm, Dockge and most databases) only label (StarPunk, Listmonk, HeyForm, Dockge and most databases) only
get a Gotify notice. Dawarich's database and Redis are skipped entirely. get a Gotify notice. Dawarich's database and Redis are skipped entirely.
Gondulf and StarPunk use pinned version tags. StarPunk uses a pinned version tag.
## Adding a service ## Adding a service
@@ -121,7 +120,7 @@ roles/docker/
├── tasks/ ├── tasks/
│ ├── main.yml # System setup, network, category imports │ ├── main.yml # System setup, network, category imports
│ ├── shell.yml # zsh, Atuin, bat │ ├── shell.yml # zsh, Atuin, bat
│ ├── infrastructure/ # caddy, pocketid, gondulf (+ dockge in main.yml) │ ├── infrastructure/ # caddy, pocketid (+ dockge in main.yml)
│ ├── development/ # gitea, bytestash │ ├── development/ # gitea, bytestash
│ ├── media/ # audiobookshelf, kavita, hoarder (Karakeep), manyfold │ ├── media/ # audiobookshelf, kavita, hoarder (Karakeep), manyfold
│ ├── productivity/ # paperlessngx, baikal, syncthing, heyform, dawarich, obsidian-livesync, gokapi │ ├── productivity/ # paperlessngx, baikal, syncthing, heyform, dawarich, obsidian-livesync, gokapi
@@ -1,28 +0,0 @@
- name: make gondulf directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- /opt/stacks/gondulf
- name: Template out the gondulf compose file
ansible.builtin.template:
src: gondulf-compose.yml.j2
dest: /opt/stacks/gondulf/compose.yml
owner: root
mode: '0644'
- name: Template out the gondulf .env file
ansible.builtin.template:
src: gondulf-env.j2
dest: /opt/stacks/gondulf/.env
owner: root
mode: '0640'
group: docker
diff: false # contains the secret key and SMTP password
- name: deploy gondulf stack
community.docker.docker_compose_v2:
project_src: /opt/stacks/gondulf
files:
- compose.yml
@@ -9,10 +9,6 @@
import_tasks: pocketid.yml import_tasks: pocketid.yml
tags: pocketid tags: pocketid
- name: Install gondulf
import_tasks: gondulf.yml
tags: gondulf
- name: Template out the dockge compose file - name: Template out the dockge compose file
ansible.builtin.template: ansible.builtin.template:
src: dockge-compose.yml.j2 src: dockge-compose.yml.j2
-4
View File
@@ -88,10 +88,6 @@ pdg.thesatelliteoflove.com {
} }
} }
gondulf.thesatelliteoflove.com {
reverse_proxy gondulf:8000
}
starpunk.thesatelliteoflove.com { starpunk.thesatelliteoflove.com {
reverse_proxy starpunk:8000 reverse_proxy starpunk:8000
} }
@@ -1,34 +0,0 @@
services:
gondulf:
image: git.thesatelliteoflove.com/phil/gondulf:1.0.1
container_name: gondulf
restart: unless-stopped
extra_hosts:
- '{{ primary_domain }}:{{ docker.hairpin_ip }}'
volumes:
- gondulf_data:/data
env_file:
- .env
environment:
- GONDULF_HTTPS_REDIRECT=true
- GONDULF_SECURE_COOKIES=true
- GONDULF_TRUST_PROXY=true
- GONDULF_TOKEN_EXPIRY=3600
- GONDULF_CODE_EXPIRY=600
- GONDULF_TOKEN_CLEANUP_ENABLED=false
- GONDULF_TOKEN_CLEANUP_INTERVAL=3600
- GONDULF_LOG_LEVEL=INFO
- GONDULF_DEBUG=false
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes:
# Existing volume (gondulf_gondulf_data) holds the SQLite database
gondulf_data:
networks:
default:
external: true
name: {{ docker.network_name }}
-9
View File
@@ -1,9 +0,0 @@
GONDULF_SECRET_KEY={{ vault_gondulf.secret_key }}
GONDULF_BASE_URL=https://{{ subdomains.gondulf }}
GONDULF_DATABASE_URL=sqlite:////data/gondulf.db
GONDULF_SMTP_HOST={{ smtp.host }}
GONDULF_SMTP_PORT=587
GONDULF_SMTP_USERNAME={{ smtp.username }}
GONDULF_SMTP_PASSWORD={{ vault_smtp.password }}
GONDULF_SMTP_FROM=gondulf@{{ smtp.from_domain }}
GONDULF_SMTP_USE_TLS=true
+10 -3
View File
@@ -1,10 +1,10 @@
services: services:
starpunk: starpunk:
image: git.thesatelliteoflove.com/phil/starpunk:v1.6.0-rc.2 image: git.thesatelliteoflove.com/phil/starpunk:v2.0.0
container_name: starpunk container_name: starpunk
restart: unless-stopped restart: unless-stopped
extra_hosts: extra_hosts:
- '{{ subdomains.gondulf }}:{{ docker.hairpin_ip }}' - '{{ subdomains.pocketid }}:{{ docker.hairpin_ip }}'
- '{{ primary_domain }}:{{ docker.hairpin_ip }}' - '{{ primary_domain }}:{{ docker.hairpin_ip }}'
volumes: volumes:
- starpunk-data:/data - starpunk-data:/data
@@ -14,9 +14,16 @@ services:
SITE_NAME: StarPunk SITE_NAME: StarPunk
SITE_AUTHOR: Mr Whiskers SITE_AUTHOR: Mr Whiskers
SITE_DESCRIPTION: Starpunk instance SITE_DESCRIPTION: Starpunk instance
# Authentication # Site owner identity (h-card source, Micropub "me")
ADMIN_ME: https://{{ primary_domain }} ADMIN_ME: https://{{ primary_domain }}
SESSION_SECRET: {{ vault_starpunk.session_secret }} SESSION_SECRET: {{ vault_starpunk.session_secret }}
# Admin login via Pocket ID (client "StarPunk"); only this user may log in.
# StarPunk issues Micropub tokens itself (ADR-064).
OIDC_ISSUER: https://{{ subdomains.pocketid }}
OIDC_CLIENT_ID: {{ vault_starpunk.pocketid.client_id }}
OIDC_CLIENT_SECRET: {{ vault_starpunk.pocketid.client_secret }}
OIDC_ADMIN_SUB: {{ starpunk_admin_sub }}
OIDC_PROVIDER_NAME: Pocket ID
# Production settings # Production settings
FLASK_ENV: production FLASK_ENV: production
FLASK_DEBUG: 0 FLASK_DEBUG: 0
+1 -1
View File
@@ -21,7 +21,7 @@ Many compose templates repeat the same network, restart and label blocks.
Pull the shared parts into includes or macros. Pull the shared parts into includes or macros.
### Health checks ### Health checks
Only Pocket ID, Gondulf, Dawarich, Listmonk and Syncthing define health checks Only Pocket ID, Dawarich, Listmonk and Syncthing define health checks
in their templates. Add them to the rest where the image supports it. in their templates. Add them to the rest where the image supports it.
### Backups ### Backups