Author SHA1 Message Date
phil 997cd4f944 added cronmaster 2025-09-17 23:42:02 -06:00
philandClaude ace5fc1d18 feat: update service versions - Authentik v2025.8.3 and GoToSocial latest
- Authentik: upgrade from v2025.6.4 to v2025.8.3 for latest security fixes and features
- GoToSocial: switch from pinned v0.19.1 to latest tag for ongoing updates

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-16 16:17:01 -06:00
35 changed files with 293 additions and 422 deletions
-7
View File
@@ -1,7 +0,0 @@
- the password for secrets.enc is in vault_pass
- do not use the ansible-vault edit command
- NEVER, EVER, EVER, USE, OPEN, OR TOUCH SECRETS.ENC
- Whenever I talk about cron jobs I am referring to cron jobs on the remote servers managed by ansible, never the local machine
- never use secrets.enc
- all secrets go in vault.yml, never secrets.enc, never some random file you want to create, only ever vault.yml. you decrypt vault.yml with vault_pass
- Never use ansible-vault edit. always decrypt, make the changes, then encrypt
+13 -13
View File
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Overview ## Overview
This is a personal infrastructure Ansible playbook that automates deployment and management of 21 self-hosted Docker services across two domains (`thesatelliteoflove.com` and `nerder.land`). The setup uses Tailscale VPN for secure networking and Caddy for reverse proxy with automated HTTPS. This is a personal infrastructure Ansible playbook that automates deployment and management of 27 self-hosted Docker services across two domains (`thesatelliteoflove.com` and `nerder.land`). The setup uses Tailscale VPN for secure networking and Caddy for reverse proxy with automated HTTPS.
**Important**: Always review `DEPLOYMENT_LEARNINGS.md` when working on this repository for lessons learned and troubleshooting guidance. **Important**: Always review `DEPLOYMENT_LEARNINGS.md` when working on this repository for lessons learned and troubleshooting guidance.
@@ -30,11 +30,10 @@ ansible-playbook dns.yml -i hosts.yml
# Deploy specific services using tags (now properly isolated) # Deploy specific services using tags (now properly isolated)
ansible-playbook site.yml -i hosts.yml --tags caddy --vault-password-file vault_pass ansible-playbook site.yml -i hosts.yml --tags caddy --vault-password-file vault_pass
ansible-playbook site.yml -i hosts.yml --tags authentik --vault-password-file vault_pass ansible-playbook site.yml -i hosts.yml --tags authentik --vault-password-file vault_pass
ansible-playbook site.yml -i hosts.yml --tags gitea --vault-password-file vault_pass ansible-playbook site.yml -i hosts.yml --tags mmdl --vault-password-file vault_pass
ansible-playbook site.yml -i hosts.yml --tags docker --vault-password-file vault_pass # entire docker role ansible-playbook site.yml -i hosts.yml --tags docker --vault-password-file vault_pass # all docker services
ansible-playbook site.yml -i hosts.yml --tags services --vault-password-file vault_pass # all services only
# Deploy services by category # Deploy services by category (new organized structure)
ansible-playbook site.yml -i hosts.yml --tags infrastructure --vault-password-file vault_pass ansible-playbook site.yml -i hosts.yml --tags infrastructure --vault-password-file vault_pass
ansible-playbook site.yml -i hosts.yml --tags media,productivity --vault-password-file vault_pass ansible-playbook site.yml -i hosts.yml --tags media,productivity --vault-password-file vault_pass
ansible-playbook site.yml -i hosts.yml --tags development,monitoring --vault-password-file vault_pass ansible-playbook site.yml -i hosts.yml --tags development,monitoring --vault-password-file vault_pass
@@ -52,7 +51,7 @@ ansible-playbook site.yml -i hosts.yml --tags common,cron --vault-password-file
### Role Structure ### Role Structure
- **bootstrap**: Initial server hardening, user creation, Tailscale VPN setup - **bootstrap**: Initial server hardening, user creation, Tailscale VPN setup
- **common**: Basic system configuration, UFW firewall management - **common**: Basic system configuration, UFW firewall management
- **docker**: Comprehensive service deployment (21 containerized applications, organized by category) - **docker**: Comprehensive service deployment (24 containerized applications, organized by category)
- **cron**: Scheduled task management (currently Warhammer RSS feed generation) - **cron**: Scheduled task management (currently Warhammer RSS feed generation)
### Docker Role Organization (Reorganized into Logical Categories) ### Docker Role Organization (Reorganized into Logical Categories)
@@ -61,15 +60,15 @@ The docker role is now organized into logical service groups under `roles/docker
- **infrastructure/**: Core platform components - **infrastructure/**: Core platform components
- Caddy (reverse proxy), Authentik (SSO), Dockge (container management) - Caddy (reverse proxy), Authentik (SSO), Dockge (container management)
- **development/**: Development and collaboration tools - **development/**: Development and collaboration tools
- Gitea, ByteStash - Gitea, Code Server, ByteStash
- **media/**: Content creation and consumption - **media/**: Content creation and consumption
- Audiobookshelf, Calibre, Karakeep (formerly Hoarder), Manyfold - Audiobookshelf, Calibre, Ghost blog, Pinchflat, Pinry, Karakeep (formerly Hoarder), Manyfold
- **productivity/**: Personal organization and document management - **productivity/**: Personal organization and document management
- Paperless-NGX, Baikal (CalDAV/CardDAV), Syncthing, Heyform, Dawarich, Obsidian LiveSync - Paperless-NGX, MMDL, Baikal (CalDAV/CardDAV), Syncthing, Heyform, Dawarich, Palmr, Obsidian LiveSync
- **communication/**: Social media - **communication/**: Social media and external communication
- GoToSocial (Fediverse) - GoToSocial (Fediverse), Postiz (social media management)
- **monitoring/**: System monitoring and alerts - **monitoring/**: System monitoring and alerts
- Changedetection, Glance dashboard, AppriseAPI, Gotify, Cronmaster - Changedetection, Glance dashboard, AppriseAPI, Gotify
### Variable Management ### Variable Management
**Critical**: This infrastructure uses a centralized variable hierarchy in `group_vars/all/`: **Critical**: This infrastructure uses a centralized variable hierarchy in `group_vars/all/`:
@@ -132,6 +131,7 @@ Common domains requiring hairpinning fixes:
- **Dawarich**: Based on production compose file at https://github.com/Freika/dawarich/blob/master/docker/docker-compose.production.yml - **Dawarich**: Based on production compose file at https://github.com/Freika/dawarich/blob/master/docker/docker-compose.production.yml
## Service Memories ## Service Memories
- palmr is the service that responds on files.thesatelliteoflove.com
- karakeep (formerly called hoarder) is deployed with both 'hoarder' and 'karakeep' tags for backward compatibility - karakeep (formerly called hoarder) is deployed with both 'hoarder' and 'karakeep' tags for backward compatibility
- whenever i ask you what containers need updates, run dockcheck and return a list of containers needing updates - whenever i ask you what containers need updates, run dockcheck and return a list of containers needing updates
- when i ask for the status container updates i want you to run dockcheck on the docker host https://github.com/mag37/dockcheck?ref=selfh.st - when i ask for the status container updates i want you to run dockcheck on the docker host https://github.com/mag37/dockcheck?ref=selfh.st
@@ -148,7 +148,7 @@ Common domains requiring hairpinning fixes:
- Organized secrets by service with consistent `vault_` prefix - Organized secrets by service with consistent `vault_` prefix
### Service Tag Fix: ### Service Tag Fix:
**Critical**: Service tags are properly isolated. Individual service tags deploy only that service. The `services` tag runs all service tasks across all categories. **Critical**: Service tags are now properly isolated. `--tags mmdl` deploys only MMDL (5 tasks), not the entire productivity category.
### Template Pattern: ### Template Pattern:
All templates now follow this pattern: All templates now follow this pattern:
+16 -12
View File
@@ -10,7 +10,7 @@ The playbook manages two main environments:
## Services Deployed ## Services Deployed
The Docker role deploys and manages 21 self-hosted services organized into logical categories: The Docker role deploys and manages 27 self-hosted services organized into logical categories:
### Infrastructure ### Infrastructure
- **Caddy** (Reverse proxy with automatic HTTPS) - **Caddy** (Reverse proxy with automatic HTTPS)
@@ -19,31 +19,37 @@ The Docker role deploys and manages 21 self-hosted services organized into logic
### Development ### Development
- **Gitea** (Git repository hosting) - **Gitea** (Git repository hosting)
- **Code Server** (VS Code in browser)
- **ByteStash** (Code snippet management) - **ByteStash** (Code snippet management)
### Media ### Media
- **Audiobookshelf** (Audiobook server) - **Audiobookshelf** (Audiobook server)
- **Calibre** (E-book management) - **Calibre** (E-book management)
- **Karakeep** (Bookmark manager, formerly Hoarder) - **Ghost** (Blog platform)
- **Pinchflat** (Media downloader)
- **Pinry** (Pinterest-like board)
- **Hoarder** (Bookmark manager)
- **Manyfold** (3D model organizer) - **Manyfold** (3D model organizer)
### Productivity ### Productivity
- **Paperless-NGX** (Document management) - **Paperless-NGX** (Document management)
- **MMDL** (Task management)
- **Baikal** (CalDAV/CardDAV server) - **Baikal** (CalDAV/CardDAV server)
- **Syncthing** (File synchronization) - **Syncthing** (File synchronization)
- **HeyForm** (Form builder) - **HeyForm** (Form builder)
- **Dawarich** (Location tracking) - **Dawarich** (Location tracking)
- **Palmr** (File sharing)
- **Obsidian LiveSync** (Note synchronization) - **Obsidian LiveSync** (Note synchronization)
### Communication ### Communication
- **GoToSocial** (Fediverse/Mastodon) - **GoToSocial** (Fediverse/Mastodon)
- **Postiz** (Social media management)
### Monitoring ### Monitoring
- **Changedetection** (Website change monitoring) - **Changedetection** (Website change monitoring)
- **Glance** (Dashboard) - **Glance** (Dashboard)
- **AppriseAPI** (Notification service) - **AppriseAPI** (Notification service)
- **Gotify** (Push notifications) - **Gotify** (Push notifications)
- **Cronmaster** (Scheduled container tasks)
## Structure ## Structure
@@ -84,13 +90,13 @@ Manages scheduled tasks and automation:
- Supports easy addition of new scheduled tasks - Supports easy addition of new scheduled tasks
### [Docker Role](roles/docker/README.md) ### [Docker Role](roles/docker/README.md)
The most comprehensive role, deploying 21 containerized services organized into logical categories: The most comprehensive role, deploying 25 containerized services organized into logical categories:
- **Infrastructure**: Caddy reverse proxy, Authentik SSO, Dockge management - **Infrastructure**: Caddy reverse proxy, Authentik SSO, Dockge management
- **Development**: Gitea, ByteStash - **Development**: Gitea, Code Server, Matrix communication
- **Media**: Audiobookshelf, Calibre, Karakeep, Manyfold - **Media**: Audiobookshelf, Calibre, Ghost blog, Pinchflat, and more
- **Productivity**: Paperless-NGX, Baikal, Syncthing, HeyForm, Dawarich, Obsidian LiveSync - **Productivity**: Paperless-NGX, MMDL task management, Baikal calendar
- **Communication**: GoToSocial - **Communication**: GoToSocial, Postiz social media management
- **Monitoring**: Glance dashboard, Changedetection, AppriseAPI, Gotify, Cronmaster - **Monitoring**: Glance dashboard, Changedetection, AppriseAPI notifications
- **Template-Driven**: All services use Jinja2 templates for consistent configuration - **Template-Driven**: All services use Jinja2 templates for consistent configuration
- **Category-Based Deployment**: Deploy services by category using Ansible tags - **Category-Based Deployment**: Deploy services by category using Ansible tags
@@ -128,12 +134,10 @@ Deploy specific services using tags:
ansible-playbook site.yml -i hosts.yml --tags infrastructure ansible-playbook site.yml -i hosts.yml --tags infrastructure
ansible-playbook site.yml -i hosts.yml --tags media,productivity ansible-playbook site.yml -i hosts.yml --tags media,productivity
# Deploy all services (skips system setup)
ansible-playbook site.yml -i hosts.yml --tags services
# Deploy individual services # Deploy individual services
ansible-playbook site.yml -i hosts.yml --tags caddy ansible-playbook site.yml -i hosts.yml --tags caddy
ansible-playbook site.yml -i hosts.yml --tags authentik ansible-playbook site.yml -i hosts.yml --tags authentik
ansible-playbook site.yml -i hosts.yml --tags mmdl
``` ```
### Manage DNS Records ### Manage DNS Records
+14 -39
View File
@@ -9,6 +9,8 @@
domains: domains:
- name: thesatelliteoflove.com - name: thesatelliteoflove.com
dns_records: dns_records:
- name: "pin"
ip: "152.53.36.98"
- name: "home" - name: "home"
ip: "152.53.36.98" ip: "152.53.36.98"
- name: "git" - name: "git"
@@ -23,16 +25,26 @@
ip: "152.53.36.98" ip: "152.53.36.98"
- name: "paper" - name: "paper"
ip: "152.53.36.98" ip: "152.53.36.98"
- name: "code"
ip: "152.53.36.98"
- name: "snippets" - name: "snippets"
ip: "152.53.36.98" ip: "152.53.36.98"
- name: cal - name: cal
ip: "152.53.36.98" ip: "152.53.36.98"
- name: phlog
ip: "152.53.36.98"
- name: loclog - name: loclog
ip: "152.53.36.98" ip: "152.53.36.98"
- name: watcher - name: watcher
ip: "152.53.36.98" ip: "152.53.36.98"
- name: models - name: models
ip: "152.53.36.98" ip: "152.53.36.98"
- name: tasks
ip: "152.53.36.98"
- name: post
ip: "152.53.36.98"
- name: files
ip: "152.53.36.98"
- name: bookmarks - name: bookmarks
ip: "152.53.36.98" ip: "152.53.36.98"
- name: gotify - name: gotify
@@ -41,55 +53,18 @@
ip: "152.53.36.98" ip: "152.53.36.98"
- name: pdg - name: pdg
ip: "152.53.36.98" ip: "152.53.36.98"
- name: opds - name: kanboard
ip: "152.53.36.98" ip: "152.53.36.98"
- name: sync - name: grocy
ip: "152.53.36.98" ip: "152.53.36.98"
- name: nerder.land - name: nerder.land
dns_records: dns_records:
- name: "forms" - name: "forms"
ip: "152.53.36.98" ip: "152.53.36.98"
- name: "listmonk"
ip: "152.53.36.98"
- name: "repaircafe"
ip: "152.53.36.98"
- name: "repair" - name: "repair"
ip: "152.53.36.98" ip: "152.53.36.98"
# DNS records to remove for decommissioned services
removed_records:
- name: thesatelliteoflove.com
dns_records:
- name: "pin"
ip: "152.53.36.98"
- name: "code"
ip: "152.53.36.98"
- name: "phlog"
ip: "152.53.36.98"
- name: "tasks"
ip: "152.53.36.98"
- name: "post"
ip: "152.53.36.98"
- name: "files"
ip: "152.53.36.98"
- name: "kanboard"
ip: "152.53.36.98"
- name: "grocy"
ip: "152.53.36.98"
tasks: tasks:
- name: Remove A records for decommissioned services
amazon.aws.route53:
state: absent
zone: "{{ item.0.name }}"
record: "{{ item.1.name + '.' + item.0.name }}"
type: A
ttl: 300
value: "{{ item.1.ip }}"
loop: "{{ query('subelements', removed_records, 'dns_records') }}"
loop_control:
loop_var: item
- name: Add A records for subdomains of each domain - name: Add A records for subdomains of each domain
amazon.aws.route53: amazon.aws.route53:
state: present state: present
+9 -3
View File
@@ -8,26 +8,32 @@ subdomains:
git: "git.{{ primary_domain }}" git: "git.{{ primary_domain }}"
cal: "cal.{{ primary_domain }}" cal: "cal.{{ primary_domain }}"
docs: "docs.{{ primary_domain }}" docs: "docs.{{ primary_domain }}"
phlog: "phlog.{{ primary_domain }}" # Ghost blog
bookmarks: "bookmarks.{{ primary_domain }}" # Hoarder/Karakeep bookmarks: "bookmarks.{{ primary_domain }}" # Hoarder/Karakeep
heyform: "forms.{{ secondary_domain }}" # Heyform on nerder.land heyform: "forms.{{ secondary_domain }}" # Heyform on nerder.land
media: "media.{{ primary_domain }}" media: "media.{{ primary_domain }}"
audio: "audio.{{ primary_domain }}" # Audiobookshelf audio: "audio.{{ primary_domain }}" # Audiobookshelf
books: "books.{{ primary_domain }}" # Calibre books: "books.{{ primary_domain }}" # Calibre
models: "models.{{ primary_domain }}" # Manyfold models: "models.{{ primary_domain }}" # Manyfold
pinchflat: "pinchflat.{{ primary_domain }}"
pin: "pin.{{ primary_domain }}" # Pinry
paper: "paper.{{ primary_domain }}" # Paperless-NGX paper: "paper.{{ primary_domain }}" # Paperless-NGX
tasks: "tasks.{{ primary_domain }}" # MMDL
syncthing: "syncthing.{{ primary_domain }}" syncthing: "syncthing.{{ primary_domain }}"
loclog: "loclog.{{ primary_domain }}" # Dawarich loclog: "loclog.{{ primary_domain }}" # Dawarich
files: "files.{{ primary_domain }}" # Palmr file sharing
social: "social.{{ primary_domain }}" # GoToSocial social: "social.{{ primary_domain }}" # GoToSocial
post: "post.{{ primary_domain }}" # Postiz
home: "home.{{ primary_domain }}" # Glance home: "home.{{ primary_domain }}" # Glance
watcher: "watcher.{{ primary_domain }}" # Changedetection watcher: "watcher.{{ primary_domain }}" # Changedetection
appriseapi: "appriseapi.{{ primary_domain }}" appriseapi: "appriseapi.{{ primary_domain }}"
dockge: "dockge.{{ primary_domain }}" dockge: "dockge.{{ primary_domain }}"
code: "code.{{ primary_domain }}" # Code Server
bytestash: "snippets.{{ primary_domain }}" # ByteStash code snippets bytestash: "snippets.{{ primary_domain }}" # ByteStash code snippets
gotify: "gotify.{{ primary_domain }}" # Gotify notifications gotify: "gotify.{{ primary_domain }}" # Gotify notifications
gotify_assistant: "gotify-assistant.{{ primary_domain }}" # iGotify iOS assistant gotify_assistant: "gotify-assistant.{{ primary_domain }}" # iGotify iOS assistant
listmonk: "listmonk.{{ secondary_domain }}" # Listmonk mailing list kanboard: "kanboard.{{ primary_domain }}" # Kanboard project management
dir2opds: "opds.{{ primary_domain }}" # dir2opds OPDS catalog grocy: "grocy.{{ primary_domain }}" # Grocy kitchen ERP
kosync: "sync.{{ primary_domain }}" # KOReader sync server
# Email domains for notifications # Email domains for notifications
email_domains: email_domains:
+9 -5
View File
@@ -3,11 +3,11 @@
# Service categories for organization # Service categories for organization
service_categories: service_categories:
infrastructure: ["caddy", "authentik", "dockge"] infrastructure: ["caddy", "authentik", "dockge"]
development: ["gitea", "bytestash"] development: ["gitea", "codeserver"]
media: ["audiobookshelf", "calibre", "dir2opds", "hoarder", "kosync", "manyfold"] media: ["audiobookshelf", "calibre", "ghost", "pinchflat", "pinry", "hoarder", "manyfold"]
productivity: ["paperlessngx", "baikal", "syncthing", "heyform", "dawarich", "obsidian-livesync"] productivity: ["paperlessngx", "baikal", "syncthing", "mmdl", "heyform", "dawarich", "pingvin"]
communication: ["gotosocial", "listmonk"] communication: ["gotosocial", "postiz"]
monitoring: ["glance", "changedetection", "appriseapi", "gotify", "cronmaster"] monitoring: ["glance", "changedetection", "appriseapi", "gotify"]
# Common service configuration # Common service configuration
services: services:
@@ -19,3 +19,7 @@ services:
dawarich: dawarich:
db_name: "dawarich" db_name: "dawarich"
db_user: "dawarich" db_user: "dawarich"
mmdl:
db_name: "mmdl"
db_user: "mmdl"
@@ -6,6 +6,10 @@ paper.thesatelliteoflove.com {
reverse_proxy paperlessngx-webserver-1:8000 reverse_proxy paperlessngx-webserver-1:8000
} }
pin.thesatelliteoflove.com {
reverse_proxy pinry-pinry-1:80
}
cal.thesatelliteoflove.com { cal.thesatelliteoflove.com {
redir /.well-known/caldav /dav.php 302 redir /.well-known/caldav /dav.php 302
redir /.well-known/carddav /dav.php 302 redir /.well-known/carddav /dav.php 302
@@ -20,6 +24,10 @@ audio.thesatelliteoflove.com {
reverse_proxy audiobookshelf-audiobookshelf-1:80 reverse_proxy audiobookshelf-audiobookshelf-1:80
} }
post.thesatelliteoflove.com {
reverse_proxy postiz:5000
}
loclog.thesatelliteoflove.com { loclog.thesatelliteoflove.com {
reverse_proxy dawarich_app:3000 reverse_proxy dawarich_app:3000
} }
@@ -28,10 +36,51 @@ watcher.thesatelliteoflove.com {
reverse_proxy changedetection:5000 reverse_proxy changedetection:5000
} }
tasks.thesatelliteoflove.com {
reverse_proxy mmdl:3000
}
kanboard.thesatelliteoflove.com {
reverse_proxy kanboard:80
}
grocy.thesatelliteoflove.com {
# API endpoints bypass forward auth for mobile apps
handle /api/* {
reverse_proxy grocy:80
}
# Web interface requires Authentik authentication
forward_auth authentik-server-1:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers {
X-authentik-username
X-authentik-groups
X-authentik-email
X-authentik-name
X-authentik-uid
}
}
reverse_proxy grocy:80
}
phlog.thesatelliteoflove.com {
reverse_proxy ghost-1-ghost-1:2368
}
code.thesatelliteoflove.com {
reverse_proxy authentik-server-1:9000
}
snippets.thesatelliteoflove.com { snippets.thesatelliteoflove.com {
reverse_proxy bytestash:5000 reverse_proxy bytestash:5000
} }
files.thesatelliteoflove.com {
reverse_proxy palmr-palmr-1:5487
}
git.thesatelliteoflove.com { git.thesatelliteoflove.com {
reverse_proxy gitea:3000 reverse_proxy gitea:3000
} }
@@ -80,14 +129,6 @@ pdg.thesatelliteoflove.com {
} }
} }
gondulf.thesatelliteoflove.com {
reverse_proxy gondulf:8000
}
starpunk.thesatelliteoflove.com {
reverse_proxy starpunk:8000
}
repair.nerder.land { repair.nerder.land {
root * /srv/repair root * /srv/repair
file_server file_server
@@ -101,24 +142,3 @@ nerder.land {
forms.nerder.land { forms.nerder.land {
reverse_proxy heyform-heyform-1:8000 reverse_proxy heyform-heyform-1:8000
} }
listmonk.nerder.land {
reverse_proxy listmonk:9000
}
repaircafe.nerder.land {
redir /volunteer-signup https://listmonk.nerder.land/subscription/form 301
}
{% if vault_dir2opds is defined %}
opds.thesatelliteoflove.com {
basicauth {
{{ dir2opds_basic_auth_hash_result.stdout }}
}
reverse_proxy dir2opds:8080
}
{% endif %}
sync.thesatelliteoflove.com {
reverse_proxy kosync:17200
}
@@ -1,19 +0,0 @@
- name: make listmonk directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- /opt/stacks/listmonk
- name: Template out the compose file
ansible.builtin.template:
src: listmonk-compose.yml.j2
dest: /opt/stacks/listmonk/compose.yml
owner: root
mode: 644
- name: deploy listmonk stack
community.docker.docker_compose_v2:
project_src: /opt/stacks/listmonk
files:
- compose.yml
@@ -8,7 +8,3 @@
- name: Install postiz - name: Install postiz
import_tasks: postiz.yml import_tasks: postiz.yml
tags: postiz tags: postiz
- name: Install listmonk
import_tasks: listmonk.yml
tags: listmonk
+17 -9
View File
@@ -1,11 +1,19 @@
--- - name: make postiz directories
- name: Stop and remove postiz stack ansible.builtin.file:
path: "{{ item}}"
state: directory
loop:
- /opt/stacks/postiz
- name: Template out the compose file
ansible.builtin.template:
src: postiz-compose.yml.j2
dest: /opt/stacks/postiz/compose.yml
owner: root
mode: 644
- name: deploy postiz stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/postiz project_src: /opt/stacks/postiz
state: absent files:
ignore_errors: true - compose.yml
- name: Remove postiz directory
ansible.builtin.file:
path: /opt/stacks/postiz
state: absent
+17 -9
View File
@@ -1,11 +1,19 @@
--- - name: make codeserver directories
- name: Stop and remove codeserver stack ansible.builtin.file:
path: "{{ item}}"
state: directory
loop:
- /opt/stacks/codeserver
- name: Template out the compose file
ansible.builtin.template:
src: codeserver-compose.yml.j2
dest: /opt/stacks/codeserver/compose.yml
owner: root
mode: 644
- name: deploy codeserver stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/codeserver project_src: /opt/stacks/codeserver
state: absent files:
ignore_errors: true - compose.yml
- name: Remove codeserver directory
ansible.builtin.file:
path: /opt/stacks/codeserver
state: absent
+3 -20
View File
@@ -5,26 +5,9 @@
loop: loop:
- /opt/stacks/caddy - /opt/stacks/caddy
- name: Install apache2-utils for htpasswd - name: copy Caddyfile
ansible.builtin.apt: ansible.builtin.copy:
name: apache2-utils src: Caddyfile
state: present
update_cache: true
cache_valid_time: 3600
become: true
when: vault_dir2opds is defined
- name: Generate bcrypt hash for dir2opds basic auth
ansible.builtin.shell: |
htpasswd -bnB "{{ vault_dir2opds.basic_auth_user }}" "{{ vault_dir2opds.basic_auth_password }}" | awk -F: '{print $1, $2}'
register: dir2opds_basic_auth_hash_result
changed_when: false
no_log: true
when: vault_dir2opds is defined
- name: template Caddyfile
ansible.builtin.template:
src: Caddyfile.j2
dest: /opt/stacks/caddy/Caddyfile dest: /opt/stacks/caddy/Caddyfile
owner: root owner: root
mode: 644 mode: 644
+6 -6
View File
@@ -59,24 +59,24 @@
# Deploy services by category for better organization and dependency management # Deploy services by category for better organization and dependency management
- name: Deploy infrastructure services - name: Deploy infrastructure services
import_tasks: infrastructure/main.yml import_tasks: infrastructure/main.yml
tags: [infrastructure, services] tags: infrastructure
- name: Deploy development services - name: Deploy development services
import_tasks: development/main.yml import_tasks: development/main.yml
tags: [development, services] tags: development
- name: Deploy media services - name: Deploy media services
import_tasks: media/main.yml import_tasks: media/main.yml
tags: [media, services] tags: media
- name: Deploy productivity services - name: Deploy productivity services
import_tasks: productivity/main.yml import_tasks: productivity/main.yml
tags: [productivity, services] tags: productivity
- name: Deploy monitoring services - name: Deploy monitoring services
import_tasks: monitoring/main.yml import_tasks: monitoring/main.yml
tags: [monitoring, services] tags: monitoring
- name: Deploy communication services - name: Deploy communication services
import_tasks: communication/main.yml import_tasks: communication/main.yml
tags: [communication, services] tags: communication
-26
View File
@@ -1,26 +0,0 @@
- name: make dir2opds directories
ansible.builtin.file:
path: "{{ item}}"
state: directory
loop:
- /opt/stacks/dir2opds
- name: make dir2opds book directories
ansible.builtin.file:
path: "{{ item}}"
state: directory
loop:
- /opt/stacks/dir2opds/books
- name: Template out the compose file
ansible.builtin.template:
src: dir2opds-compose.yml.j2
dest: /opt/stacks/dir2opds/compose.yml
owner: root
mode: 644
- name: deploy dir2opds stack
community.docker.docker_compose_v2:
project_src: /opt/stacks/dir2opds
files:
- compose.yml
+17 -9
View File
@@ -1,11 +1,19 @@
--- - name: make ghost-1 directories
- name: Stop and remove ghost stack ansible.builtin.file:
path: "{{ item}}"
state: directory
loop:
- /opt/stacks/ghost-1
- name: Template out the compose file
ansible.builtin.template:
src: ghost-1-compose.yml.j2
dest: /opt/stacks/ghost-1/compose.yml
owner: root
mode: 644
- name: deploy ghost-1 stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/ghost-1 project_src: /opt/stacks/ghost-1
state: absent files:
ignore_errors: true - compose.yml
- name: Remove ghost directory
ansible.builtin.file:
path: /opt/stacks/ghost-1
state: absent
-22
View File
@@ -1,22 +0,0 @@
- name: make kosync directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- /opt/stacks/kosync
- /opt/stacks/kosync/logs/app
- /opt/stacks/kosync/logs/redis
- /opt/stacks/kosync/data/redis
- name: Template out the compose file
ansible.builtin.template:
src: kosync-compose.yml.j2
dest: /opt/stacks/kosync/compose.yml
owner: root
mode: 644
- name: deploy kosync stack
community.docker.docker_compose_v2:
project_src: /opt/stacks/kosync
files:
- compose.yml
-8
View File
@@ -30,11 +30,3 @@
- name: Install manyfold - name: Install manyfold
import_tasks: manyfold.yml import_tasks: manyfold.yml
tags: manyfold tags: manyfold
- name: Install dir2opds
import_tasks: dir2opds.yml
tags: dir2opds
- name: Install koreader sync server
import_tasks: kosync.yml
tags: kosync
+17 -9
View File
@@ -1,11 +1,19 @@
--- - name: make pinchflat directories
- name: Stop and remove pinchflat stack ansible.builtin.file:
path: "{{ item}}"
state: directory
loop:
- /opt/stacks/pinchflat
- name: Template out the compose file
ansible.builtin.template:
src: pinchflat-compose.yml.j2
dest: /opt/stacks/pinchflat/compose.yml
owner: root
mode: 644
- name: deploy pinchflat stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/pinchflat project_src: /opt/stacks/pinchflat
state: absent files:
ignore_errors: true - compose.yml
- name: Remove pinchflat directory
ansible.builtin.file:
path: /opt/stacks/pinchflat
state: absent
+17 -9
View File
@@ -1,11 +1,19 @@
--- - name: make pinry directories
- name: Stop and remove pinry stack ansible.builtin.file:
path: "{{ item}}"
state: directory
loop:
- /opt/stacks/pinry
- name: Template out the compose file
ansible.builtin.template:
src: pinry-compose.yml.j2
dest: /opt/stacks/pinry/compose.yml
owner: root
mode: 644
- name: deploy pinry stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/pinry project_src: /opt/stacks/pinry
state: absent files:
ignore_errors: true - compose.yml
- name: Remove pinry directory
ansible.builtin.file:
path: /opt/stacks/pinry
state: absent
+15 -8
View File
@@ -1,11 +1,18 @@
--- ---
- name: Stop and remove grocy stack - name: Create grocy directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- /opt/stacks/grocy
- name: Template grocy compose file
ansible.builtin.template:
src: grocy-compose.yml.j2
dest: /opt/stacks/grocy/compose.yml
- name: Deploy grocy stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/grocy project_src: /opt/stacks/grocy
state: absent files:
ignore_errors: true - compose.yml
- name: Remove grocy directory
ansible.builtin.file:
path: /opt/stacks/grocy
state: absent
+15 -8
View File
@@ -1,11 +1,18 @@
--- ---
- name: Stop and remove kanboard stack - name: Create kanboard directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- /opt/stacks/kanboard
- name: Template kanboard compose file
ansible.builtin.template:
src: kanboard-compose.yml.j2
dest: /opt/stacks/kanboard/compose.yml
- name: Deploy kanboard stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/kanboard project_src: /opt/stacks/kanboard
state: absent files:
ignore_errors: true - compose.yml
- name: Remove kanboard directory
ansible.builtin.file:
path: /opt/stacks/kanboard
state: absent
+22 -8
View File
@@ -1,11 +1,25 @@
--- ---
- name: Stop and remove mmdl stack - name: Create mmdl directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- /opt/stacks/mmdl
- /opt/stacks/mmdl/data
- /opt/stacks/mmdl/mysql
- name: Template mmdl environment file
ansible.builtin.template:
src: mmdl-env.j2
dest: /opt/stacks/mmdl/.env.local
- name: Template mmdl compose file
ansible.builtin.template:
src: mmdl-compose.yml.j2
dest: /opt/stacks/mmdl/compose.yml
- name: Deploy mmdl stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/mmdl project_src: /opt/stacks/mmdl
state: absent files:
ignore_errors: true - compose.yml
- name: Remove mmdl directory
ansible.builtin.file:
path: /opt/stacks/mmdl
state: absent
+17 -9
View File
@@ -1,11 +1,19 @@
--- - name: make palmr directories
- name: Stop and remove palmr stack ansible.builtin.file:
path: "{{ item }}"
state: directory
loop:
- /opt/stacks/palmr
- name: Template out the compose file
ansible.builtin.template:
src: palmr-compose.yml.j2
dest: /opt/stacks/palmr/compose.yml
owner: root
mode: 644
- name: deploy palmr stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: /opt/stacks/palmr project_src: /opt/stacks/palmr
state: absent files:
ignore_errors: true - compose.yml
- name: Remove palmr directory
ansible.builtin.file:
path: /opt/stacks/palmr
state: absent
@@ -37,7 +37,7 @@ services:
glance.parent: authentik glance.parent: authentik
glance.name: Redis glance.name: Redis
server: server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.2} image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.8.3}
restart: unless-stopped restart: unless-stopped
command: server command: server
environment: environment:
@@ -64,7 +64,7 @@ services:
glance.description: Authentication server glance.description: Authentication server
glance.id: authentik glance.id: authentik
worker: worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.2} image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.8.3}
restart: unless-stopped restart: unless-stopped
command: worker command: worker
environment: environment:
@@ -26,7 +26,7 @@ services:
glance.url: https://{{ subdomains.bytestash }}/ glance.url: https://{{ subdomains.bytestash }}/
glance.description: Code snippet manager glance.description: Code snippet manager
glance.id: bytestash glance.id: bytestash
mag37.dockcheck.update: true
volumes: volumes:
bytestash_data: bytestash_data:
driver: local driver: local
@@ -25,7 +25,7 @@ services:
glance.group: Infrastructure glance.group: Infrastructure
glance.parent: infrastructure glance.parent: infrastructure
glance.name: CronMaster glance.name: CronMaster
mag37.dockcheck.update: true
networks: networks:
default: default:
external: true external: true
@@ -63,9 +63,6 @@ services:
REDIS_URL: redis://dawarich_redis:6379 REDIS_URL: redis://dawarich_redis:6379
MIN_MINUTES_SPENT_IN_CITY: 60 MIN_MINUTES_SPENT_IN_CITY: 60
APPLICATION_HOSTS: {{ subdomains.loclog }},localhost,::1,127.0.0.1 APPLICATION_HOSTS: {{ subdomains.loclog }},localhost,::1,127.0.0.1
PHOTON_API_USE_HTTPS: true
PHOTON_API_HOST: photon.dawarich.app
PHOTON_API_KEY: ca91825827603b39e4cdd6fe4de9063f4ec77e0617454857576dd62b424bb60b
TIME_ZONE: America/Denver TIME_ZONE: America/Denver
APPLICATION_PROTOCOL: http APPLICATION_PROTOCOL: http
DISTANCE_UNIT: mi DISTANCE_UNIT: mi
@@ -125,9 +122,6 @@ services:
TIME_ZONE: America/Denver TIME_ZONE: America/Denver
APPLICATION_PROTOCOL: http APPLICATION_PROTOCOL: http
DISTANCE_UNIT: mi DISTANCE_UNIT: mi
PHOTON_API_HOST: photon.dawarich.app
PHOTON_API_KEY: ca91825827603b39e4cdd6fe4de9063f4ec77e0617454857576dd62b424bb60b
PHOTON_API_USE_HTTPS: true
PROMETHEUS_EXPORTER_ENABLED: false PROMETHEUS_EXPORTER_ENABLED: false
SECRET_KEY_BASE: {{ vault_dawarich.secret_key_base }} SECRET_KEY_BASE: {{ vault_dawarich.secret_key_base }}
RAILS_LOG_TO_STDOUT: "true" RAILS_LOG_TO_STDOUT: "true"
@@ -1,27 +0,0 @@
---
services:
dir2opds:
image: ghcr.io/dubyte/dir2opds:v1.9.0
container_name: dir2opds
ports:
- "8080:8080"
volumes:
- ./books:/books
command:
- -dir=/books
- -extract-metadata
- -enable-cache
- -gzip
- -enable-html
- -url=https://{{ subdomains.dir2opds }}
restart: unless-stopped
labels:
glance.name: dir2opds
glance.icon: si:book
glance.url: https://{{ subdomains.dir2opds }}/
glance.description: OPDS book catalog
mag37.dockcheck.update: true
networks:
default:
external: true
name: {{ docker.network_name }}
+1 -1
View File
@@ -16,7 +16,7 @@ services:
glance.url: https://{{ subdomains.home }}/ glance.url: https://{{ subdomains.home }}/
glance.description: Homepage app glance.description: Homepage app
glance.id: glance glance.id: glance
mag37.dockcheck.update: true
networks: networks:
default: default:
external: true external: true
+5
View File
@@ -122,16 +122,21 @@ pages:
- hoarder-app/hoarder - hoarder-app/hoarder
- goauthentik/authentik - goauthentik/authentik
- superseriousbusiness/gotosocial - superseriousbusiness/gotosocial
- stonith404/pingvin-share
- caddyserver/caddy - caddyserver/caddy
- gitroomhq/postiz-app
- sabre-io/Baikal - sabre-io/Baikal
- janeczku/calibre-web - janeczku/calibre-web
- heyform/heyform - heyform/heyform
- paperless-ngx/paperless-ngx - paperless-ngx/paperless-ngx
- linuxserver/docker-calibre-web - linuxserver/docker-calibre-web
- coder/code-server
- dgtlmoon/changedetection.io - dgtlmoon/changedetection.io
- Freika/dawarich - Freika/dawarich
- manyfold3d/manyfold - manyfold3d/manyfold
- caronc/apprise-api - caronc/apprise-api
- kieraneglin/pinchflat
- pinry/pinry
- syncthing/syncthing - syncthing/syncthing
- size: full - size: full
@@ -13,7 +13,6 @@ services:
glance.icon: si:gotify glance.icon: si:gotify
glance.url: "https://{{ subdomains.gotify }}/" glance.url: "https://{{ subdomains.gotify }}/"
glance.description: Push notification server glance.description: Push notification server
mag37.dockcheck.update: true
extra_hosts: extra_hosts:
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}" - "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
- "{{ subdomains.gotify_assistant }}:{{ docker.hairpin_ip }}" - "{{ subdomains.gotify_assistant }}:{{ docker.hairpin_ip }}"
@@ -1,22 +0,0 @@
---
services:
kosync:
image: koreader/kosync:latest
container_name: kosync
environment:
- ENABLE_USER_REGISTRATION=true
volumes:
- ./logs/app:/app/koreader-sync-server/logs
- ./logs/redis:/var/log/redis
- ./data/redis:/var/lib/redis
restart: unless-stopped
labels:
glance.name: KOReader Sync
glance.icon: si:book
glance.url: https://{{ subdomains.kosync }}/
glance.description: KOReader reading progress sync
mag37.dockcheck.update: true
networks:
default:
external: true
name: {{ docker.network_name }}
@@ -1,58 +0,0 @@
services:
listmonk:
image: listmonk/listmonk:latest
container_name: listmonk
restart: unless-stopped
depends_on:
db:
condition: service_healthy
command: [sh, -c, "./listmonk --install --idempotent --yes --config '' && ./listmonk --upgrade --yes --config '' && ./listmonk --config ''"]
environment:
LISTMONK_app__address: 0.0.0.0:9000
LISTMONK_db__user: listmonk
LISTMONK_db__password: {{ vault_listmonk.postgres_password }}
LISTMONK_db__database: listmonk
LISTMONK_db__host: db
LISTMONK_db__port: 5432
LISTMONK_db__ssl_mode: disable
LISTMONK_db__max_open: 25
LISTMONK_db__max_idle: 25
LISTMONK_db__max_lifetime: 300s
TZ: Etc/UTC
LISTMONK_ADMIN_USER: {{ vault_listmonk.admin_user }}
LISTMONK_ADMIN_PASSWORD: {{ vault_listmonk.admin_password }}
volumes:
- uploads:/listmonk/uploads
labels:
glance.name: Listmonk
glance.url: https://{{ subdomains.listmonk }}/
glance.description: Mailing list manager
glance.id: listmonk
db:
image: postgres:17-alpine
container_name: listmonk_db
restart: unless-stopped
environment:
POSTGRES_USER: listmonk
POSTGRES_PASSWORD: {{ vault_listmonk.postgres_password }}
POSTGRES_DB: listmonk
healthcheck:
test: ["CMD-SHELL", "pg_isready -U listmonk"]
interval: 10s
timeout: 5s
retries: 6
volumes:
- listmonk-data:/var/lib/postgresql/data
labels:
glance.parent: listmonk
glance.name: DB
volumes:
uploads:
listmonk-data:
networks:
default:
external: true
name: {{ docker.network_name }}
@@ -9,7 +9,6 @@ services:
glance.url: http://{{ network.docker_host_ip }}:5984 glance.url: http://{{ network.docker_host_ip }}:5984
glance.description: Obsidian note synchronization glance.description: Obsidian note synchronization
glance.id: obsidian-livesync glance.id: obsidian-livesync
mag37.dockcheck.update: true
environment: environment:
- SERVER_DOMAIN={{ network.docker_host_ip }} - SERVER_DOMAIN={{ network.docker_host_ip }}
- COUCHDB_USER={{ vault_obsidian.username }} - COUCHDB_USER={{ vault_obsidian.username }}
@@ -9,7 +9,6 @@ services:
glance.url: https://netcup.porgy-porgy.ts.net:8384 glance.url: https://netcup.porgy-porgy.ts.net:8384
glance.description: Syncthing core glance.description: Syncthing core
glance.id: Syncthing glance.id: Syncthing
mag37.dockcheck.update: true
environment: environment:
- PUID=1000 - PUID=1000
- PGID=1000 - PGID=1000