Manage Gondulf and StarPunk with Ansible

Both were hand-deployed to /opt/stacks. Templates match the live setup
and keep the same stack dirs and volume names, so data stays put.
Secrets come from the vault; .env and the StarPunk compose file are now
0640 root:docker instead of the broken 1204 mode. Adds their DNS
records to dns.yml and drops the dead godulf. Caddy route (no DNS).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Phil
2026-10-31 09:42:36 -06:00
co-authored by Claude Opus 5.5
parent 6f6a669cf3
commit be9523a0c4
11 changed files with 139 additions and 6 deletions
+4
View File
@@ -17,6 +17,10 @@
domains: domains:
- name: thesatelliteoflove.com - name: thesatelliteoflove.com
dns_records: dns_records:
- name: "gondulf"
ip: "{{ network.netcup_ip }}"
- name: "starpunk"
ip: "{{ network.netcup_ip }}"
- name: "git" - name: "git"
ip: "{{ network.netcup_ip }}" ip: "{{ network.netcup_ip }}"
- name: "social" - name: "social"
+2
View File
@@ -27,6 +27,8 @@ 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
# Email domains for notifications # Email domains for notifications
email_domains: email_domains:
+2 -2
View File
@@ -2,11 +2,11 @@
# Service categories for organization # Service categories for organization
service_categories: service_categories:
infrastructure: ["caddy", "authentik", "dockge"] infrastructure: ["caddy", "authentik", "dockge", "gondulf"]
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"]
communication: ["gotosocial", "listmonk"] communication: ["gotosocial", "listmonk", "starpunk"]
monitoring: ["changedetection", "appriseapi", "gotify", "cronmaster"] monitoring: ["changedetection", "appriseapi", "gotify", "cronmaster"]
# Common service configuration # Common service configuration
@@ -9,3 +9,7 @@
- name: Install listmonk - name: Install listmonk
import_tasks: listmonk.yml import_tasks: listmonk.yml
tags: listmonk tags: listmonk
- name: Install starpunk
import_tasks: starpunk.yml
tags: starpunk
@@ -0,0 +1,21 @@
- name: make starpunk directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- /opt/stacks/starpunk
- name: Template out the starpunk compose file
ansible.builtin.template:
src: starpunk-compose.yml.j2
dest: /opt/stacks/starpunk/compose.yml
owner: root
mode: '0640'
group: docker
diff: false # contains the session secret
- name: deploy starpunk stack
community.docker.docker_compose_v2:
project_src: /opt/stacks/starpunk
files:
- compose.yml
@@ -0,0 +1,28 @@
- 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
@@ -13,6 +13,10 @@
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
@@ -100,10 +100,6 @@ starpunk.thesatelliteoflove.com {
reverse_proxy starpunk:8000 reverse_proxy starpunk:8000
} }
godulf.thesatelliteoflove.com {
reverse_proxy gondulf:8000
}
repair.nerder.land { repair.nerder.land {
root * /srv/repair root * /srv/repair
file_server file_server
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,9 @@
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
@@ -0,0 +1,31 @@
services:
starpunk:
image: git.thesatelliteoflove.com/phil/starpunk:v1.6.0-rc.2
container_name: starpunk
restart: unless-stopped
extra_hosts:
- '{{ subdomains.gondulf }}:{{ docker.hairpin_ip }}'
- '{{ primary_domain }}:{{ docker.hairpin_ip }}'
volumes:
- starpunk-data:/data
environment:
# Site configuration
SITE_URL: https://{{ subdomains.starpunk }}
SITE_NAME: StarPunk
SITE_AUTHOR: Mr Whiskers
SITE_DESCRIPTION: Starpunk instance
# Authentication
ADMIN_ME: https://{{ primary_domain }}
SESSION_SECRET: {{ vault_starpunk.session_secret }}
# Production settings
FLASK_ENV: production
FLASK_DEBUG: 0
LOG_LEVEL: INFO
DEV_MODE: false
volumes:
# Existing volume (starpunk_starpunk-data) holds the posts and database
starpunk-data:
networks:
default:
external: true
name: {{ docker.network_name }}