Compare commits
30 Commits
bd50feb484
...
main
Author | SHA1 | Date | |
---|---|---|---|
f088247ac0 | |||
e1b6d3132a | |||
f71ded1a01 | |||
a2ae9e5ff6 | |||
fb6651f1dc | |||
58a6be8da0 | |||
17c3077cf0 | |||
75fabb3523 | |||
336e197176 | |||
f0c4cb51b8 | |||
c95ca45a67 | |||
a287e50048 | |||
01d959d12c | |||
a4fc5f7608 | |||
e3f4eb4e95 | |||
a8350459ae | |||
eac67e269c | |||
85cfca08f5 | |||
2cc05a19e6 | |||
d54d04bcc9 | |||
5f76f69d8b | |||
ef5309363c | |||
ff89683038 | |||
a338186a77 | |||
8710ffc70d | |||
a98fae0b92 | |||
d05bac8651 | |||
c500790ea3 | |||
2e4c096bbe | |||
12582b352c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
||||
secrets.enc
|
||||
vault_pass
|
||||
DEPLOYMENT_LEARNINGS.md
|
||||
group_vars/all/vault.yml
|
83
CLAUDE.md
83
CLAUDE.md
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Overview
|
||||
|
||||
This is a personal infrastructure Ansible playbook that automates deployment and management of 22+ 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.
|
||||
|
||||
@@ -27,18 +27,19 @@ ansible-playbook dns.yml -i hosts.yml
|
||||
|
||||
### Service Management
|
||||
```bash
|
||||
# Deploy specific services using tags
|
||||
ansible-playbook site.yml -i hosts.yml --tags caddy --vault-password-file vault_pass --extra-vars "@secrets.enc"
|
||||
ansible-playbook site.yml -i hosts.yml --tags authentik,gitea --vault-password-file vault_pass --extra-vars "@secrets.enc"
|
||||
ansible-playbook site.yml -i hosts.yml --tags docker --vault-password-file vault_pass --extra-vars "@secrets.enc" # all docker services
|
||||
# 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 authentik --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 # all docker services
|
||||
|
||||
# Deploy services by category (new organized structure)
|
||||
ansible-playbook site.yml -i hosts.yml --tags infrastructure --vault-password-file vault_pass --extra-vars "@secrets.enc"
|
||||
ansible-playbook site.yml -i hosts.yml --tags media,productivity --vault-password-file vault_pass --extra-vars "@secrets.enc"
|
||||
ansible-playbook site.yml -i hosts.yml --tags development,monitoring --vault-password-file vault_pass --extra-vars "@secrets.enc"
|
||||
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 development,monitoring --vault-password-file vault_pass
|
||||
|
||||
# Deploy only infrastructure components
|
||||
ansible-playbook site.yml -i hosts.yml --tags common,cron --vault-password-file vault_pass --extra-vars "@secrets.enc"
|
||||
ansible-playbook site.yml -i hosts.yml --tags common,cron --vault-password-file vault_pass
|
||||
```
|
||||
|
||||
## Architecture
|
||||
@@ -50,7 +51,7 @@ ansible-playbook site.yml -i hosts.yml --tags common,cron --vault-password-file
|
||||
### Role Structure
|
||||
- **bootstrap**: Initial server hardening, user creation, Tailscale VPN setup
|
||||
- **common**: Basic system configuration, UFW firewall management
|
||||
- **docker**: Comprehensive service deployment (22+ containerized applications, organized by category)
|
||||
- **docker**: Comprehensive service deployment (24 containerized applications, organized by category)
|
||||
- **cron**: Scheduled task management (currently Warhammer RSS feed generation)
|
||||
|
||||
### Docker Role Organization (Reorganized into Logical Categories)
|
||||
@@ -59,20 +60,31 @@ The docker role is now organized into logical service groups under `roles/docker
|
||||
- **infrastructure/**: Core platform components
|
||||
- Caddy (reverse proxy), Authentik (SSO), Dockge (container management)
|
||||
- **development/**: Development and collaboration tools
|
||||
- Gitea, Code Server, Matrix (Conduit)
|
||||
- Gitea, Code Server, ByteStash
|
||||
- **media/**: Content creation and consumption
|
||||
- Audiobookshelf, Calibre, Ghost blog, Pinchflat, Pinry, Karakeep, Manyfold
|
||||
- Audiobookshelf, Calibre, Ghost blog, Pinchflat, Pinry, Karakeep (formerly Hoarder), Manyfold
|
||||
- **productivity/**: Personal organization and document management
|
||||
- Paperless-NGX, MMDL, Baikal (CalDAV/CardDAV), Syncthing, Heyform, Dawarich, Pingvin
|
||||
- Paperless-NGX, MMDL, Baikal (CalDAV/CardDAV), Syncthing, Heyform, Dawarich, Palmr, Obsidian LiveSync
|
||||
- **communication/**: Social media and external communication
|
||||
- GoToSocial (Fediverse), Postiz (social media management)
|
||||
- **monitoring/**: System monitoring and alerts
|
||||
- Changedetection, Glance dashboard, AppriseAPI
|
||||
- Changedetection, Glance dashboard, AppriseAPI, Gotify
|
||||
|
||||
### Variable Management
|
||||
**Critical**: This infrastructure uses a centralized variable hierarchy in `group_vars/all/`:
|
||||
|
||||
- **domains.yml**: Domain and subdomain mappings (use `{{ subdomains.service }}`)
|
||||
- **infrastructure.yml**: Network configuration, Docker settings (`{{ docker.network_name }}`, `{{ docker.hairpin_ip }}`)
|
||||
- **vault.yml**: Encrypted secrets with `vault_` prefix
|
||||
- **services.yml**: Service-specific configuration and feature flags
|
||||
|
||||
**Important**: All templates use variables instead of hardcoded values. Never hardcode domains, IPs, or secrets.
|
||||
|
||||
### Data Structure
|
||||
- All service data stored in `/opt/stacks/[service-name]/` on docker host
|
||||
- Docker Compose files generated from Jinja2 templates in `roles/docker/templates/`
|
||||
- Environment files templated for services requiring configuration
|
||||
- All configurations use centralized variables for consistency
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
@@ -104,14 +116,49 @@ Services inside Docker containers cannot reach external domains that resolve to
|
||||
|
||||
```yaml
|
||||
extra_hosts:
|
||||
- "auth.thesatelliteoflove.com:172.20.0.5"
|
||||
- "cal.thesatelliteoflove.com:172.20.0.5"
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
- "{{ subdomains.cal }}:{{ docker.hairpin_ip }}"
|
||||
```
|
||||
|
||||
Common domains requiring hairpinning fixes:
|
||||
- `auth.thesatelliteoflove.com` (Authentik SSO)
|
||||
- `cal.thesatelliteoflove.com` (Baikal CalDAV)
|
||||
- `{{ subdomains.auth }}` (Authentik SSO)
|
||||
- `{{ subdomains.cal }}` (Baikal CalDAV)
|
||||
- Any service domain the container needs to communicate with
|
||||
|
||||
**Note**: Use variables instead of hardcoded values for maintainability.
|
||||
|
||||
### Service-Specific Reference Configurations
|
||||
- **Dawarich**: Based on production compose file at https://github.com/Freika/dawarich/blob/master/docker/docker-compose.production.yml
|
||||
|
||||
## 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
|
||||
- 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
|
||||
- this is your reference for glance configuration https://github.com/glanceapp/glance/blob/main/docs/configuration.md#configuring-glance
|
||||
|
||||
## Variable Management Implementation Notes
|
||||
**Major Infrastructure Update**: Variable management system was implemented to replace all hardcoded values with centralized variables.
|
||||
|
||||
### Key Changes Made:
|
||||
- Created comprehensive `group_vars/all/` structure
|
||||
- Updated all Docker Compose templates to use variables
|
||||
- Fixed service tag isolation (individual service tags now deploy only that service)
|
||||
- Standardized domain and network configuration
|
||||
- Organized secrets by service with consistent `vault_` prefix
|
||||
|
||||
### Service Tag Fix:
|
||||
**Critical**: Service tags are now properly isolated. `--tags mmdl` deploys only MMDL (5 tasks), not the entire productivity category.
|
||||
|
||||
### Template Pattern:
|
||||
All templates now follow this pattern:
|
||||
```yaml
|
||||
# Use variables, not hardcoded values
|
||||
glance.url: "https://{{ subdomains.service }}/"
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: "{{ docker.network_name }}"
|
||||
extra_hosts:
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
```
|
12
README.md
12
README.md
@@ -10,7 +10,7 @@ The playbook manages two main environments:
|
||||
|
||||
## Services Deployed
|
||||
|
||||
The Docker role deploys and manages 22+ self-hosted services organized into logical categories:
|
||||
The Docker role deploys and manages 27 self-hosted services organized into logical categories:
|
||||
|
||||
### Infrastructure
|
||||
- **Caddy** (Reverse proxy with automatic HTTPS)
|
||||
@@ -20,7 +20,7 @@ The Docker role deploys and manages 22+ self-hosted services organized into logi
|
||||
### Development
|
||||
- **Gitea** (Git repository hosting)
|
||||
- **Code Server** (VS Code in browser)
|
||||
- **Matrix Conduit** (Communication/chat)
|
||||
- **ByteStash** (Code snippet management)
|
||||
|
||||
### Media
|
||||
- **Audiobookshelf** (Audiobook server)
|
||||
@@ -28,7 +28,7 @@ The Docker role deploys and manages 22+ self-hosted services organized into logi
|
||||
- **Ghost** (Blog platform)
|
||||
- **Pinchflat** (Media downloader)
|
||||
- **Pinry** (Pinterest-like board)
|
||||
- **Karakeep** (Bookmark manager)
|
||||
- **Hoarder** (Bookmark manager)
|
||||
- **Manyfold** (3D model organizer)
|
||||
|
||||
### Productivity
|
||||
@@ -38,7 +38,8 @@ The Docker role deploys and manages 22+ self-hosted services organized into logi
|
||||
- **Syncthing** (File synchronization)
|
||||
- **HeyForm** (Form builder)
|
||||
- **Dawarich** (Location tracking)
|
||||
- **Pingvin Share** (File sharing)
|
||||
- **Palmr** (File sharing)
|
||||
- **Obsidian LiveSync** (Note synchronization)
|
||||
|
||||
### Communication
|
||||
- **GoToSocial** (Fediverse/Mastodon)
|
||||
@@ -48,6 +49,7 @@ The Docker role deploys and manages 22+ self-hosted services organized into logi
|
||||
- **Changedetection** (Website change monitoring)
|
||||
- **Glance** (Dashboard)
|
||||
- **AppriseAPI** (Notification service)
|
||||
- **Gotify** (Push notifications)
|
||||
|
||||
## Structure
|
||||
|
||||
@@ -88,7 +90,7 @@ Manages scheduled tasks and automation:
|
||||
- Supports easy addition of new scheduled tasks
|
||||
|
||||
### [Docker Role](roles/docker/README.md)
|
||||
The most comprehensive role, deploying 22+ 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
|
||||
- **Development**: Gitea, Code Server, Matrix communication
|
||||
- **Media**: Audiobookshelf, Calibre, Ghost blog, Pinchflat, and more
|
||||
|
@@ -3,11 +3,8 @@
|
||||
become: true
|
||||
vars:
|
||||
created_username: phil
|
||||
vars_prompt:
|
||||
- name: tailscale_key
|
||||
prompt: Enter the tailscale key
|
||||
roles:
|
||||
- bootstrap
|
||||
- role: artis3n.tailscale
|
||||
vars:
|
||||
tailscale_authkey: "{{ tailscale_key }}"
|
||||
tailscale_authkey: "{{ vault_infrastructure.tailscale_key }}"
|
14
dns.yml
14
dns.yml
@@ -27,6 +27,8 @@
|
||||
ip: "152.53.36.98"
|
||||
- name: "code"
|
||||
ip: "152.53.36.98"
|
||||
- name: "snippets"
|
||||
ip: "152.53.36.98"
|
||||
- name: cal
|
||||
ip: "152.53.36.98"
|
||||
- name: phlog
|
||||
@@ -35,8 +37,6 @@
|
||||
ip: "152.53.36.98"
|
||||
- name: watcher
|
||||
ip: "152.53.36.98"
|
||||
- name: chat
|
||||
ip: "152.53.36.98"
|
||||
- name: models
|
||||
ip: "152.53.36.98"
|
||||
- name: tasks
|
||||
@@ -47,6 +47,16 @@
|
||||
ip: "152.53.36.98"
|
||||
- name: bookmarks
|
||||
ip: "152.53.36.98"
|
||||
- name: gotify
|
||||
ip: "152.53.36.98"
|
||||
- name: gotify-assistant
|
||||
ip: "152.53.36.98"
|
||||
- name: pdg
|
||||
ip: "152.53.36.98"
|
||||
- name: kanboard
|
||||
ip: "152.53.36.98"
|
||||
- name: grocy
|
||||
ip: "152.53.36.98"
|
||||
- name: nerder.land
|
||||
dns_records:
|
||||
- name: "forms"
|
||||
|
43
group_vars/all/domains.yml
Normal file
43
group_vars/all/domains.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
# Domain Configuration
|
||||
primary_domain: "thesatelliteoflove.com"
|
||||
secondary_domain: "nerder.land"
|
||||
|
||||
# Subdomain mappings
|
||||
subdomains:
|
||||
auth: "auth.{{ primary_domain }}"
|
||||
git: "git.{{ primary_domain }}"
|
||||
cal: "cal.{{ primary_domain }}"
|
||||
docs: "docs.{{ primary_domain }}"
|
||||
phlog: "phlog.{{ primary_domain }}" # Ghost blog
|
||||
bookmarks: "bookmarks.{{ primary_domain }}" # Hoarder/Karakeep
|
||||
heyform: "forms.{{ secondary_domain }}" # Heyform on nerder.land
|
||||
media: "media.{{ primary_domain }}"
|
||||
audio: "audio.{{ primary_domain }}" # Audiobookshelf
|
||||
books: "books.{{ primary_domain }}" # Calibre
|
||||
models: "models.{{ primary_domain }}" # Manyfold
|
||||
pinchflat: "pinchflat.{{ primary_domain }}"
|
||||
pin: "pin.{{ primary_domain }}" # Pinry
|
||||
paper: "paper.{{ primary_domain }}" # Paperless-NGX
|
||||
tasks: "tasks.{{ primary_domain }}" # MMDL
|
||||
syncthing: "syncthing.{{ primary_domain }}"
|
||||
loclog: "loclog.{{ primary_domain }}" # Dawarich
|
||||
files: "files.{{ primary_domain }}" # Palmr file sharing
|
||||
social: "social.{{ primary_domain }}" # GoToSocial
|
||||
post: "post.{{ primary_domain }}" # Postiz
|
||||
home: "home.{{ primary_domain }}" # Glance
|
||||
watcher: "watcher.{{ primary_domain }}" # Changedetection
|
||||
appriseapi: "appriseapi.{{ primary_domain }}"
|
||||
dockge: "dockge.{{ primary_domain }}"
|
||||
code: "code.{{ primary_domain }}" # Code Server
|
||||
bytestash: "snippets.{{ primary_domain }}" # ByteStash code snippets
|
||||
gotify: "gotify.{{ primary_domain }}" # Gotify notifications
|
||||
gotify_assistant: "gotify-assistant.{{ primary_domain }}" # iGotify iOS assistant
|
||||
kanboard: "kanboard.{{ primary_domain }}" # Kanboard project management
|
||||
grocy: "grocy.{{ primary_domain }}" # Grocy kitchen ERP
|
||||
|
||||
# Email domains for notifications
|
||||
email_domains:
|
||||
updates: "updates.{{ primary_domain }}"
|
||||
auth_email: "auth@updates.{{ primary_domain }}"
|
||||
git_email: "git@updates.{{ primary_domain }}"
|
||||
cal_email: "cal@updates.{{ primary_domain }}"
|
26
group_vars/all/infrastructure.yml
Normal file
26
group_vars/all/infrastructure.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
# Infrastructure Configuration
|
||||
|
||||
# Docker configuration
|
||||
docker:
|
||||
network_name: "lava"
|
||||
stacks_path: "/opt/stacks"
|
||||
hairpin_ip: "172.20.0.5"
|
||||
|
||||
# SMTP configuration
|
||||
smtp:
|
||||
host: "smtp.resend.com"
|
||||
username: "resend"
|
||||
from_domain: "{{ email_domains.updates }}"
|
||||
|
||||
# Network configuration
|
||||
network:
|
||||
netcup_ip: "152.53.36.98"
|
||||
docker_host_ip: "100.70.169.99"
|
||||
|
||||
# Paths
|
||||
paths:
|
||||
stacks: "{{ docker.stacks_path }}"
|
||||
|
||||
# Notification services
|
||||
notifications:
|
||||
appriseapi_endpoint: "http://apprise:8000/notify/apprise"
|
25
group_vars/docker/services.yml
Normal file
25
group_vars/docker/services.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
# Docker Services Configuration
|
||||
|
||||
# Service categories for organization
|
||||
service_categories:
|
||||
infrastructure: ["caddy", "authentik", "dockge"]
|
||||
development: ["gitea", "codeserver"]
|
||||
media: ["audiobookshelf", "calibre", "ghost", "pinchflat", "pinry", "hoarder", "manyfold"]
|
||||
productivity: ["paperlessngx", "baikal", "syncthing", "mmdl", "heyform", "dawarich", "pingvin"]
|
||||
communication: ["gotosocial", "postiz"]
|
||||
monitoring: ["glance", "changedetection", "appriseapi", "gotify"]
|
||||
|
||||
# Common service configuration
|
||||
services:
|
||||
common:
|
||||
restart_policy: "unless-stopped"
|
||||
network: "{{ docker.network_name }}"
|
||||
|
||||
# Service-specific configurations
|
||||
dawarich:
|
||||
db_name: "dawarich"
|
||||
db_user: "dawarich"
|
||||
|
||||
mmdl:
|
||||
db_name: "mmdl"
|
||||
db_user: "mmdl"
|
@@ -1,6 +1,8 @@
|
||||
- name: Install aptitude
|
||||
- name: Install common packages
|
||||
apt:
|
||||
name: aptitude
|
||||
name:
|
||||
- aptitude
|
||||
- jq
|
||||
state: latest
|
||||
update_cache: true
|
||||
|
||||
|
6
roles/cron/handlers/main.yml
Normal file
6
roles/cron/handlers/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# Handler to restart systemd-journald service
|
||||
- name: restart rsyslog
|
||||
systemd:
|
||||
name: systemd-journald
|
||||
state: restarted
|
@@ -1,4 +1,7 @@
|
||||
---
|
||||
# Enable cron logging in systemd-journald (already enabled by default)
|
||||
# We'll rely on journalctl for cron execution logs
|
||||
|
||||
# Ensure the script is copied to the target machine
|
||||
- name: Copy the warhammer feed update script
|
||||
copy:
|
||||
@@ -16,3 +19,97 @@
|
||||
hour: "9"
|
||||
user: root
|
||||
job: "/usr/local/bin/update_warhammer_feed.sh"
|
||||
|
||||
# Create .local/bin directory for phil user
|
||||
- name: Ensure .local/bin directory exists for phil
|
||||
file:
|
||||
path: /home/phil/.local/bin
|
||||
state: directory
|
||||
mode: '0755'
|
||||
owner: phil
|
||||
group: phil
|
||||
|
||||
# Install dockcheck script in phil's .local/bin
|
||||
- name: Download dockcheck.sh script
|
||||
get_url:
|
||||
url: https://raw.githubusercontent.com/mag37/dockcheck/main/dockcheck.sh
|
||||
dest: /home/phil/.local/bin/dockcheck.sh
|
||||
mode: '0755'
|
||||
owner: phil
|
||||
group: phil
|
||||
|
||||
# Create .config directory for phil user
|
||||
- name: Ensure .config directory exists for phil
|
||||
file:
|
||||
path: /home/phil/.config
|
||||
state: directory
|
||||
mode: '0755'
|
||||
owner: phil
|
||||
group: phil
|
||||
|
||||
# Create notify_templates directory alongside dockcheck.sh
|
||||
- name: Ensure notify_templates directory exists in .local/bin
|
||||
file:
|
||||
path: /home/phil/.local/bin/notify_templates
|
||||
state: directory
|
||||
mode: '0755'
|
||||
owner: phil
|
||||
group: phil
|
||||
|
||||
# Download notify_v2.sh script for dockcheck notifications
|
||||
- name: Download notify_v2.sh script
|
||||
get_url:
|
||||
url: https://raw.githubusercontent.com/mag37/dockcheck/main/notify_templates/notify_v2.sh
|
||||
dest: /home/phil/.local/bin/notify_templates/notify_v2.sh
|
||||
mode: '0755'
|
||||
owner: phil
|
||||
group: phil
|
||||
|
||||
# Download notify_gotify.sh script for dockcheck notifications
|
||||
- name: Download notify_gotify.sh script
|
||||
get_url:
|
||||
url: https://raw.githubusercontent.com/mag37/dockcheck/main/notify_templates/notify_gotify.sh
|
||||
dest: /home/phil/.local/bin/notify_templates/notify_gotify.sh
|
||||
mode: '0755'
|
||||
owner: phil
|
||||
group: phil
|
||||
|
||||
# Template dockcheck configuration file
|
||||
- name: Template dockcheck configuration
|
||||
template:
|
||||
src: dockcheck.config.j2
|
||||
dest: /home/phil/.config/dockcheck.config
|
||||
mode: '0644'
|
||||
owner: phil
|
||||
group: phil
|
||||
|
||||
# Create log directory for dockcheck
|
||||
- name: Create dockcheck log directory
|
||||
file:
|
||||
path: /var/log/dockcheck
|
||||
state: directory
|
||||
mode: '0755'
|
||||
owner: phil
|
||||
group: phil
|
||||
|
||||
# Create dockcheck wrapper script to avoid cron escaping issues
|
||||
- name: Create dockcheck wrapper script
|
||||
copy:
|
||||
dest: /home/phil/.local/bin/run_dockcheck.sh
|
||||
mode: '0755'
|
||||
owner: phil
|
||||
group: phil
|
||||
content: |
|
||||
#!/bin/bash
|
||||
cd /home/phil
|
||||
/home/phil/.local/bin/dockcheck.sh >> /var/log/dockcheck/dockcheck.log 2>&1
|
||||
echo "$(date "+%Y-%m-%d %H:%M:%S") - Dockcheck completed with exit code $?" >> /var/log/dockcheck/dockcheck.log
|
||||
|
||||
# Create cron job for dockcheck as phil user with logging
|
||||
- name: Create cron job for dockcheck container updates
|
||||
cron:
|
||||
name: "Check Docker container updates"
|
||||
minute: "0"
|
||||
hour: "8"
|
||||
user: phil
|
||||
job: "/home/phil/.local/bin/run_dockcheck.sh"
|
||||
|
18
roles/cron/templates/dockcheck.config.j2
Normal file
18
roles/cron/templates/dockcheck.config.j2
Normal file
@@ -0,0 +1,18 @@
|
||||
# Dockcheck Configuration - Check only, no updates
|
||||
# Don't update, just check for updates
|
||||
# DontUpdate=true
|
||||
OnlyLabel=true
|
||||
AutoMode=true
|
||||
|
||||
# Enable notifications
|
||||
Notify=true
|
||||
|
||||
# Exclude containers from checking
|
||||
Exclude="authentik-postgresql-1,dawarich_redis,dawarich_db"
|
||||
|
||||
# Notification channels
|
||||
NOTIFY_CHANNELS="gotify"
|
||||
|
||||
# Gotify notification configuration
|
||||
GOTIFY_DOMAIN="https://{{ subdomains.gotify }}"
|
||||
GOTIFY_TOKEN="{{ vault_dockcheck.gotify_token }}"
|
@@ -1,12 +1,12 @@
|
||||
# Docker Role
|
||||
|
||||
## Purpose
|
||||
Deploys and manages a comprehensive self-hosted infrastructure with 22+ containerized services organized into logical categories, transforming a server into a personal cloud platform with authentication, media management, productivity tools, and development services.
|
||||
Deploys and manages a comprehensive self-hosted infrastructure with 24 containerized services organized into logical categories, transforming a server into a personal cloud platform with authentication, media management, productivity tools, and development services.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Network Configuration
|
||||
- **External Network**: All services connect to shared `lava` network (172.20.0.0/24)
|
||||
- **External Network**: All services connect to shared Docker network (configurable)
|
||||
- **Reverse Proxy**: Caddy handles all ingress traffic with automatic HTTPS
|
||||
- **Service Discovery**: Container-to-container communication using service names
|
||||
- **Firewall Integration**: UFW-Docker script properly configures firewall rules
|
||||
@@ -16,6 +16,7 @@ Deploys and manages a comprehensive self-hosted infrastructure with 22+ containe
|
||||
- **Network Isolation**: Services restricted to appropriate network segments
|
||||
- **Container Hardening**: Non-root users, capability dropping, security options
|
||||
- **Secret Management**: Ansible vault for sensitive configuration
|
||||
- **Variable Management**: Centralized variable hierarchy using group_vars structure
|
||||
|
||||
## Services Deployed (Organized by Category)
|
||||
|
||||
@@ -27,7 +28,7 @@ Deploys and manages a comprehensive self-hosted infrastructure with 22+ containe
|
||||
### Development (`development/`)
|
||||
- **Gitea** - Self-hosted Git with CI/CD runners
|
||||
- **Code Server** - VS Code in the browser
|
||||
- **Conduit** - Matrix homeserver for communication
|
||||
- **ByteStash** - Code snippet management and organization
|
||||
|
||||
### Media (`media/`)
|
||||
- **Audiobookshelf** - Audiobook and podcast server
|
||||
@@ -45,7 +46,8 @@ Deploys and manages a comprehensive self-hosted infrastructure with 22+ containe
|
||||
- **Syncthing** - Decentralized file sync
|
||||
- **Heyform** - Form builder and surveys
|
||||
- **Dawarich** - Location tracking
|
||||
- **Pingvin Share** - File sharing service
|
||||
- **Palmr** - File sharing service
|
||||
- **Obsidian LiveSync** - CouchDB backend for note synchronization
|
||||
|
||||
### Communication (`communication/`)
|
||||
- **GoToSocial** - Lightweight ActivityPub server
|
||||
@@ -55,6 +57,7 @@ Deploys and manages a comprehensive self-hosted infrastructure with 22+ containe
|
||||
- **Glance** - Customizable dashboard with monitoring
|
||||
- **Change Detection** - Website monitoring
|
||||
- **Apprise API** - Unified notifications
|
||||
- **Gotify** - Self-hosted push notification service
|
||||
|
||||
## Deployment Patterns
|
||||
|
||||
@@ -68,7 +71,9 @@ Each service follows a consistent pattern:
|
||||
### Template System
|
||||
- **Compose Templates**: `.j2` files in `templates/` for dynamic configuration
|
||||
- **Environment Templates**: Separate `.env.j2` files for services requiring environment variables
|
||||
- **Variable Substitution**: Uses Ansible vault variables for secrets and configuration
|
||||
- **Variable Substitution**: Uses centralized variable hierarchy from group_vars structure
|
||||
- **Domain Management**: Centralized domain and subdomain configuration
|
||||
- **Network Configuration**: Standardized Docker network and IP address management
|
||||
|
||||
## Shell Environment Setup
|
||||
The role also configures the shell environment:
|
||||
@@ -89,8 +94,7 @@ roles/docker/
|
||||
│ ├── development/
|
||||
│ │ ├── main.yml # Development category orchestrator
|
||||
│ │ ├── gitea.yml # Git hosting
|
||||
│ │ ├── codeserver.yml # VS Code server
|
||||
│ │ └── conduit.yml # Matrix server
|
||||
│ │ └── codeserver.yml # VS Code server
|
||||
│ ├── media/ # Media services (7 services)
|
||||
│ ├── productivity/ # Productivity services (7 services)
|
||||
│ ├── communication/ # Communication services (2 services)
|
||||
@@ -161,11 +165,20 @@ ansible-playbook site.yml -i hosts.yml --tags mmdl
|
||||
|
||||
## Configuration
|
||||
|
||||
### Required Variables (in vault)
|
||||
- Authentication credentials for various services
|
||||
### Variable Structure
|
||||
The role uses a centralized variable hierarchy in `group_vars/all/`:
|
||||
|
||||
- **domains.yml**: Domain and subdomain mappings for all services
|
||||
- **infrastructure.yml**: Network configuration, Docker settings, and system parameters
|
||||
- **vault.yml**: Encrypted secrets including API keys, passwords, and OAuth credentials
|
||||
- **services.yml**: Service-specific configuration and feature flags
|
||||
|
||||
### Required Variables (in vault.yml)
|
||||
- Authentication credentials for various services (vault_*)
|
||||
- API keys for external integrations
|
||||
- OAuth client secrets for SSO integration
|
||||
- Database passwords and connection strings
|
||||
- SMTP credentials for notifications
|
||||
|
||||
### Network Configuration
|
||||
Services expect to be accessible via subdomains of configured domains:
|
||||
|
@@ -40,6 +40,30 @@ 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
|
||||
}
|
||||
@@ -49,8 +73,12 @@ code.thesatelliteoflove.com {
|
||||
reverse_proxy authentik-server-1:9000
|
||||
}
|
||||
|
||||
snippets.thesatelliteoflove.com {
|
||||
reverse_proxy bytestash:5000
|
||||
}
|
||||
|
||||
files.thesatelliteoflove.com {
|
||||
reverse_proxy pingvin-pingvin-share-1:3000
|
||||
reverse_proxy palmr-palmr-1:5487
|
||||
}
|
||||
|
||||
git.thesatelliteoflove.com {
|
||||
@@ -64,15 +92,6 @@ thesatelliteoflove.com {
|
||||
file_server
|
||||
}
|
||||
|
||||
chat.thesatelliteoflove.com, chat.thesatelliteoflove.com:8448 {
|
||||
handle /.well-known/* {
|
||||
root * /srv/matrix
|
||||
file_server
|
||||
}
|
||||
reverse_proxy /_matrix/* conduit-homeserver-1:6167
|
||||
}
|
||||
|
||||
|
||||
bookmarks.thesatelliteoflove.com {
|
||||
reverse_proxy hoarder-web-1:3000
|
||||
}
|
||||
@@ -90,6 +109,25 @@ home.thesatelliteoflove.com {
|
||||
reverse_proxy authentik-server-1:9000
|
||||
}
|
||||
|
||||
gotify.thesatelliteoflove.com {
|
||||
reverse_proxy gotify:80
|
||||
}
|
||||
|
||||
gotify-assistant.thesatelliteoflove.com {
|
||||
reverse_proxy igotify-assistant:8080
|
||||
}
|
||||
|
||||
pdg.thesatelliteoflove.com {
|
||||
root * /srv/pdg
|
||||
try_files {path} {path}.html {path}/ =404
|
||||
file_server
|
||||
encode gzip
|
||||
|
||||
handle_errors {
|
||||
rewrite * /{err.status_code}.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
|
||||
repair.nerder.land {
|
||||
root * /srv/repair
|
||||
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"m.homeserver": {
|
||||
"base_url": "https://chat.thesatelliteoflove.com"
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"m.server": "chat.thesatelliteoflove.com:443"
|
||||
}
|
@@ -12,3 +12,10 @@
|
||||
files:
|
||||
- compose.yml
|
||||
state: restarted
|
||||
|
||||
- name: restart obsidian-livesync
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /opt/stacks/obsidian-livesync
|
||||
files:
|
||||
- docker-compose.yml
|
||||
state: restarted
|
@@ -1,19 +1,19 @@
|
||||
- name: make pingvin directories
|
||||
- name: make bytestash directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item}}"
|
||||
state: directory
|
||||
loop:
|
||||
- /opt/stacks/pingvin
|
||||
- /opt/stacks/bytestash
|
||||
|
||||
- name: Template out the compose file
|
||||
ansible.builtin.template:
|
||||
src: pingvin-compose.yml.j2
|
||||
dest: /opt/stacks/pingvin/compose.yml
|
||||
src: bytestash-compose.yml.j2
|
||||
dest: /opt/stacks/bytestash/compose.yml
|
||||
owner: root
|
||||
mode: 644
|
||||
|
||||
- name: deploy pingvin stack
|
||||
- name: deploy bytestash stack
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /opt/stacks/pingvin
|
||||
project_src: /opt/stacks/bytestash
|
||||
files:
|
||||
- compose.yml
|
@@ -1,29 +0,0 @@
|
||||
- name: make conduit directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item}}"
|
||||
state: directory
|
||||
loop:
|
||||
- /opt/stacks/conduit
|
||||
|
||||
- name: copy well-known files
|
||||
ansible.builtin.copy:
|
||||
src: "{{item}}"
|
||||
dest: /opt/stacks/caddy/site/matrix/
|
||||
owner: root
|
||||
mode: 644
|
||||
loop:
|
||||
- client
|
||||
- server
|
||||
|
||||
- name: Template out the compose file
|
||||
ansible.builtin.template:
|
||||
src: conduit-compose.yml.j2
|
||||
dest: /opt/stacks/conduit/compose.yml
|
||||
owner: root
|
||||
mode: 644
|
||||
|
||||
- name: deploy conduit stack
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /opt/stacks/conduit
|
||||
files:
|
||||
- compose.yml
|
@@ -9,6 +9,7 @@
|
||||
import_tasks: codeserver.yml
|
||||
tags: codeserver
|
||||
|
||||
- name: Install conduit
|
||||
import_tasks: conduit.yml
|
||||
tags: conduit
|
||||
- name: Install bytestash
|
||||
import_tasks: bytestash.yml
|
||||
tags: bytestash
|
||||
|
||||
|
@@ -59,56 +59,24 @@
|
||||
# Deploy services by category for better organization and dependency management
|
||||
- name: Deploy infrastructure services
|
||||
import_tasks: infrastructure/main.yml
|
||||
tags:
|
||||
- infrastructure
|
||||
- caddy
|
||||
- authentik
|
||||
- dockge
|
||||
tags: infrastructure
|
||||
|
||||
- name: Deploy development services
|
||||
import_tasks: development/main.yml
|
||||
tags:
|
||||
- development
|
||||
- gitea
|
||||
- codeserver
|
||||
- conduit
|
||||
tags: development
|
||||
|
||||
- name: Deploy media services
|
||||
import_tasks: media/main.yml
|
||||
tags:
|
||||
- media
|
||||
- audiobookshelf
|
||||
- calibre
|
||||
- ghost-1
|
||||
- pinchflat
|
||||
- pinry
|
||||
- hoarder
|
||||
- karakeep
|
||||
- manyfold
|
||||
tags: media
|
||||
|
||||
- name: Deploy productivity services
|
||||
import_tasks: productivity/main.yml
|
||||
tags:
|
||||
- productivity
|
||||
- paperlessngx
|
||||
- baikal
|
||||
- syncthing
|
||||
- mmdl
|
||||
- heyform
|
||||
- dawarich
|
||||
- pingvin
|
||||
tags: productivity
|
||||
|
||||
- name: Deploy monitoring services
|
||||
import_tasks: monitoring/main.yml
|
||||
tags:
|
||||
- monitoring
|
||||
- glance
|
||||
- changedetection
|
||||
- appriseapi
|
||||
tags: monitoring
|
||||
|
||||
- name: Deploy communication services
|
||||
import_tasks: communication/main.yml
|
||||
tags:
|
||||
- communication
|
||||
- gotosocial
|
||||
- postiz
|
||||
tags: communication
|
19
roles/docker/tasks/monitoring/gotify.yml
Normal file
19
roles/docker/tasks/monitoring/gotify.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
- name: Create gotify directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
loop:
|
||||
- /opt/stacks/gotify
|
||||
|
||||
- name: Template out the gotify compose file
|
||||
ansible.builtin.template:
|
||||
src: gotify-compose.yml.j2
|
||||
dest: /opt/stacks/gotify/compose.yml
|
||||
owner: root
|
||||
mode: 644
|
||||
|
||||
- name: Deploy gotify stack
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /opt/stacks/gotify
|
||||
files:
|
||||
- compose.yml
|
@@ -12,3 +12,7 @@
|
||||
- name: Install appriseapi
|
||||
import_tasks: appriseapi.yml
|
||||
tags: appriseapi
|
||||
|
||||
- name: Install gotify
|
||||
import_tasks: gotify.yml
|
||||
tags: gotify
|
18
roles/docker/tasks/productivity/grocy.yml
Normal file
18
roles/docker/tasks/productivity/grocy.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
- 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:
|
||||
project_src: /opt/stacks/grocy
|
||||
files:
|
||||
- compose.yml
|
18
roles/docker/tasks/productivity/kanboard.yml
Normal file
18
roles/docker/tasks/productivity/kanboard.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
- 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:
|
||||
project_src: /opt/stacks/kanboard
|
||||
files:
|
||||
- compose.yml
|
@@ -25,6 +25,18 @@
|
||||
import_tasks: dawarich.yml
|
||||
tags: dawarich
|
||||
|
||||
- name: Install pingvin
|
||||
import_tasks: pingvin.yml
|
||||
tags: pingvin
|
||||
- name: Install palmr
|
||||
import_tasks: palmr.yml
|
||||
tags: palmr
|
||||
|
||||
- name: Install obsidian-livesync
|
||||
import_tasks: obsidian-livesync.yml
|
||||
tags: obsidian-livesync
|
||||
|
||||
- name: Install kanboard
|
||||
import_tasks: kanboard.yml
|
||||
tags: kanboard
|
||||
|
||||
- name: Install grocy
|
||||
import_tasks: grocy.yml
|
||||
tags: grocy
|
20
roles/docker/tasks/productivity/obsidian-livesync.yml
Normal file
20
roles/docker/tasks/productivity/obsidian-livesync.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: make obsidian-livesync directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ paths.stacks }}/obsidian-livesync"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Template out the compose file
|
||||
ansible.builtin.template:
|
||||
src: obsidian-livesync-compose.yml.j2
|
||||
dest: "{{ paths.stacks }}/obsidian-livesync/docker-compose.yml"
|
||||
mode: '0644'
|
||||
notify: restart obsidian-livesync
|
||||
|
||||
- name: deploy obsidian-livesync stack
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ paths.stacks }}/obsidian-livesync"
|
||||
state: present
|
||||
tags:
|
||||
- obsidian-livesync
|
19
roles/docker/tasks/productivity/palmr.yml
Normal file
19
roles/docker/tasks/productivity/palmr.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
- name: make palmr directories
|
||||
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:
|
||||
project_src: /opt/stacks/palmr
|
||||
files:
|
||||
- compose.yml
|
@@ -2,7 +2,7 @@ services:
|
||||
apprise:
|
||||
container_name: apprise
|
||||
ports:
|
||||
- 100.70.169.99:8000:8000
|
||||
- {{ network.docker_host_ip }}:8000:8000
|
||||
environment:
|
||||
- APPRISE_STATEFUL_MODE=simple
|
||||
- APPRISE_WORKER_COUNT=1
|
||||
@@ -11,13 +11,15 @@ services:
|
||||
- plugin:/plugin
|
||||
- attach:/attach
|
||||
image: caronc/apprise:latest
|
||||
extra_hosts:
|
||||
- "{{ subdomains.gotify }}:{{ docker.hairpin_ip }}"
|
||||
labels:
|
||||
glance.name: Apprise
|
||||
glance.icon: si:imessage
|
||||
glance.url: https://auth.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.appriseapi }}/
|
||||
glance.description: Apprise api server
|
||||
glance.id: apprise
|
||||
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
config:
|
||||
attach:
|
||||
@@ -25,4 +27,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -10,12 +10,13 @@ services:
|
||||
- TZ=America/Denver
|
||||
- DISABLE_SSRF_REQUEST_FILTER=1
|
||||
extra_hosts:
|
||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
||||
- '{{ subdomains.auth }}:172.20.0.5'
|
||||
labels:
|
||||
glance.name: Audiobookshelf
|
||||
glance.icon: si:audiobookshelf
|
||||
glance.url: https://audio.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.audio }}/
|
||||
glance.description: Audio book server
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
audiobooks:
|
||||
driver: local
|
||||
@@ -28,4 +29,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -37,7 +37,7 @@ services:
|
||||
glance.parent: authentik
|
||||
glance.name: Redis
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.1}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.4}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
@@ -64,7 +64,7 @@ services:
|
||||
glance.description: Authentication server
|
||||
glance.id: authentik
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.1}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.4}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
|
@@ -1,15 +1,15 @@
|
||||
PG_PASS={{ authentik_pg_pass }}
|
||||
AUTHENTIK_SECRET_KEY={{ authentik_secret_key }}
|
||||
PG_PASS={{ vault_authentik.postgres_password }}
|
||||
AUTHENTIK_SECRET_KEY={{ vault_authentik.secret_key }}
|
||||
# SMTP Host Emails are sent to
|
||||
AUTHENTIK_EMAIL__HOST=smtp.resend.com
|
||||
AUTHENTIK_EMAIL__HOST={{ smtp.host }}
|
||||
AUTHENTIK_EMAIL__PORT=25
|
||||
# Optionally authenticate (don't add quotation marks to your password)
|
||||
AUTHENTIK_EMAIL__USERNAME=resend
|
||||
AUTHENTIK_EMAIL__PASSWORD={{ resend_key }}
|
||||
AUTHENTIK_EMAIL__USERNAME={{ smtp.username }}
|
||||
AUTHENTIK_EMAIL__PASSWORD={{ vault_smtp.password }}
|
||||
# Use StartTLS
|
||||
AUTHENTIK_EMAIL__USE_TLS=true
|
||||
# Use SSL
|
||||
AUTHENTIK_EMAIL__USE_SSL=false
|
||||
AUTHENTIK_EMAIL__TIMEOUT=10
|
||||
# Email address authentik will send from, should have a correct @domain
|
||||
AUTHENTIK_EMAIL__FROM=auth@updates.thesatelliteoflove.com
|
||||
AUTHENTIK_EMAIL__FROM=auth@{{ email_domains.updates }}
|
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
baikal:
|
||||
image: ckulka/baikal:nginx
|
||||
image: ckulka/baikal:0.10.1-nginx
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- config:/var/www/baikal/config
|
||||
@@ -8,9 +8,9 @@ services:
|
||||
labels:
|
||||
glance.name: Baikal
|
||||
glance.icon: si:protoncalendar
|
||||
glance.url: https://cal.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.cal }}/
|
||||
glance.description: CalDav server
|
||||
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
config:
|
||||
data:
|
||||
@@ -18,4 +18,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
37
roles/docker/templates/bytestash-compose.yml.j2
Normal file
37
roles/docker/templates/bytestash-compose.yml.j2
Normal file
@@ -0,0 +1,37 @@
|
||||
services:
|
||||
bytestash:
|
||||
image: ghcr.io/jordan-dalby/bytestash:latest
|
||||
container_name: bytestash
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- bytestash_data:/data/snippets
|
||||
environment:
|
||||
JWT_SECRET: "{{ vault_bytestash.jwt_secret }}"
|
||||
TOKEN_EXPIRY: "24h"
|
||||
ALLOW_NEW_ACCOUNTS: "true"
|
||||
DEBUG: "false"
|
||||
DISABLE_ACCOUNTS: "false"
|
||||
DISABLE_INTERNAL_ACCOUNTS: "false"
|
||||
OIDC_ENABLED: "true"
|
||||
OIDC_DISPLAY_NAME: "Login with Authentik"
|
||||
OIDC_ISSUER_URL: "https://{{ subdomains.auth }}/application/o/bytestash/"
|
||||
OIDC_CLIENT_ID: "{{ vault_bytestash.oidc_client_id }}"
|
||||
OIDC_CLIENT_SECRET: "{{ vault_bytestash.oidc_client_secret }}"
|
||||
OIDC_SCOPES: "openid profile email"
|
||||
extra_hosts:
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
labels:
|
||||
glance.name: ByteStash
|
||||
glance.icon: si:code
|
||||
glance.url: https://{{ subdomains.bytestash }}/
|
||||
glance.description: Code snippet manager
|
||||
glance.id: bytestash
|
||||
|
||||
volumes:
|
||||
bytestash_data:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: {{ docker.network_name }}
|
@@ -16,11 +16,12 @@ services:
|
||||
labels:
|
||||
glance.name: Caddy
|
||||
glance.icon: si:caddy
|
||||
glance.url: https://thesatelliteoflove.com/
|
||||
glance.url: https://{{ primary_domain }}/
|
||||
glance.description: Reverse proxy
|
||||
mag37.dockcheck.update: true
|
||||
networks:
|
||||
default:
|
||||
ipv4_address: 172.20.0.5
|
||||
ipv4_address: {{ docker.hairpin_ip }}
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
@@ -28,4 +29,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -16,8 +16,9 @@ services:
|
||||
labels:
|
||||
glance.name: Calibre
|
||||
glance.icon: si:calibreweb
|
||||
glance.url: https://books.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.books }}/
|
||||
glance.description: Book server
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
config:
|
||||
driver: local
|
||||
@@ -26,4 +27,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -4,14 +4,13 @@ services:
|
||||
image: ghcr.io/dgtlmoon/changedetection.io
|
||||
container_name: changedetection
|
||||
hostname: changedetection
|
||||
extra_hosts:
|
||||
- 'chat.thesatelliteoflove.com:172.20.0.5'
|
||||
labels:
|
||||
glance.name: Changedetection
|
||||
glance.icon: si:watchtower
|
||||
glance.url: https://watcher.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.watcher }}/
|
||||
glance.description: Changedetection
|
||||
glance.id: changedetection
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
- changedetection-data:/datastore
|
||||
# Configurable proxy list support, see https://github.com/dgtlmoon/changedetection.io/wiki/Proxy-configuration#proxy-list-support
|
||||
@@ -50,7 +49,7 @@ services:
|
||||
# - NO_PROXY="localhost,192.168.0.0/24"
|
||||
#
|
||||
# Base URL of your changedetection.io install (Added to the notification alert)
|
||||
- BASE_URL=https://watcher.thesatelliteoflove.com
|
||||
- BASE_URL=https://{{ subdomains.watcher }}
|
||||
# Respect proxy_pass type settings, `proxy_set_header Host "localhost";` and `proxy_set_header X-Forwarded-Prefix /app;`
|
||||
# More here https://github.com/dgtlmoon/changedetection.io/wiki/Running-changedetection.io-behind-a-reverse-proxy-sub-directory
|
||||
# - USE_X_SETTINGS=1
|
||||
@@ -77,6 +76,8 @@ services:
|
||||
# ports:
|
||||
# - 5000:5000
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- "{{ subdomains.gotify }}:{{ docker.hairpin_ip }}"
|
||||
|
||||
# Used for fetching pages via WebDriver+Chrome where you need Javascript support.
|
||||
# Now working on arm64 (needs testing on rPi - tested on Oracle ARM instance)
|
||||
@@ -96,6 +97,7 @@ services:
|
||||
labels:
|
||||
glance.parent: changedetection
|
||||
glance.name: Browser
|
||||
mag37.dockcheck.update: true
|
||||
image: dgtlmoon/sockpuppetbrowser:latest
|
||||
cap_add:
|
||||
- SYS_ADMIN
|
||||
@@ -106,6 +108,8 @@ services:
|
||||
- SCREEN_HEIGHT=1024
|
||||
- SCREEN_DEPTH=16
|
||||
- MAX_CONCURRENT_CHROME_PROCESSES=10
|
||||
extra_hosts:
|
||||
- "{{ subdomains.gotify }}:{{ docker.hairpin_ip }}"
|
||||
|
||||
# Used for fetching pages via Playwright+Chrome where you need Javascript support.
|
||||
# Note: Works well but is deprecated, does not fetch full page screenshots (doesnt work with Visual Selector)
|
||||
@@ -130,4 +134,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
||||
|
@@ -5,8 +5,9 @@ services:
|
||||
labels:
|
||||
glance.name: Code Server
|
||||
glance.icon: si:vscodium
|
||||
glance.url: https://code.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.code }}/
|
||||
glance.description: Code Server
|
||||
mag37.dockcheck.update: true
|
||||
container_name: codeserver
|
||||
volumes:
|
||||
- home:/home
|
||||
@@ -19,4 +20,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -1,46 +0,0 @@
|
||||
services:
|
||||
homeserver:
|
||||
image: matrixconduit/matrix-conduit:next
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- db:/var/lib/matrix-conduit/
|
||||
labels:
|
||||
glance.name: Conduit
|
||||
glance.icon: si:matrix
|
||||
glance.url: https://chat.thesatelliteoflove.com/
|
||||
glance.description: Matrix server
|
||||
environment:
|
||||
CONDUIT_SERVER_NAME: chat.thesatelliteoflove.com # EDIT THIS
|
||||
CONDUIT_DATABASE_PATH: /var/lib/matrix-conduit/
|
||||
CONDUIT_DATABASE_BACKEND: rocksdb
|
||||
CONDUIT_PORT: 6167
|
||||
CONDUIT_MAX_REQUEST_SIZE: 20000000 # in bytes, ~20 MB
|
||||
CONDUIT_ALLOW_REGISTRATION: 'true'
|
||||
CONDUIT_ALLOW_FEDERATION: 'true'
|
||||
CONDUIT_ALLOW_CHECK_FOR_UPDATES: 'true'
|
||||
CONDUIT_TRUSTED_SERVERS: '["matrix.org"]'
|
||||
#CONDUIT_MAX_CONCURRENT_REQUESTS: 100
|
||||
CONDUIT_ADDRESS: 0.0.0.0
|
||||
CONDUIT_CONFIG: '' # Ignore this
|
||||
#
|
||||
### Uncomment if you want to use your own Element-Web App.
|
||||
### Note: You need to provide a config.json for Element and you also need a second
|
||||
### Domain or Subdomain for the communication between Element and Conduit
|
||||
### Config-Docs: https://github.com/vector-im/element-web/blob/develop/docs/config.md
|
||||
# element-web:
|
||||
# image: vectorim/element-web:latest
|
||||
# restart: unless-stopped
|
||||
# ports:
|
||||
# - 8009:80
|
||||
# volumes:
|
||||
# - ./element_config.json:/app/config.json
|
||||
# depends_on:
|
||||
# - homeserver
|
||||
|
||||
volumes:
|
||||
db:
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
@@ -1,4 +1,19 @@
|
||||
services:
|
||||
dawarich_redis:
|
||||
image: redis:7.4-alpine
|
||||
container_name: dawarich_redis
|
||||
labels:
|
||||
glance.parent: dawarich
|
||||
glance.name: Redis
|
||||
volumes:
|
||||
- dawarich_redis_data:/data
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
timeout: 10s
|
||||
dawarich_db:
|
||||
image: postgis/postgis:17-3.5-alpine
|
||||
shm_size: 1G
|
||||
@@ -10,7 +25,7 @@ services:
|
||||
- dawarich_db_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: {{ dawarich_db_password }}
|
||||
POSTGRES_PASSWORD: {{ vault_dawarich.postgres_password }}
|
||||
POSTGRES_DB: dawarich_production
|
||||
restart: always
|
||||
healthcheck:
|
||||
@@ -19,20 +34,20 @@ services:
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
timeout: 10s
|
||||
|
||||
dawarich_app:
|
||||
image: freikin/dawarich:0.27.3
|
||||
image: freikin/dawarich:latest
|
||||
container_name: dawarich_app
|
||||
labels:
|
||||
glance.name: Dawarich
|
||||
glance.icon: si:openstreetmap
|
||||
glance.url: https://loclog.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.loclog }}/
|
||||
glance.description: Dawarich
|
||||
glance.id: dawarich
|
||||
volumes:
|
||||
- dawarich_public:/var/app/public
|
||||
- dawarich_watched:/var/app/tmp/imports/watched
|
||||
- dawarich_storage:/var/app/storage
|
||||
- dawarich_db_data:/dawarich_db_data
|
||||
stdin_open: true
|
||||
tty: true
|
||||
entrypoint: web-entrypoint.sh
|
||||
@@ -40,22 +55,21 @@ services:
|
||||
restart: on-failure
|
||||
environment:
|
||||
RAILS_ENV: production
|
||||
QUEUE_DATABASE_PATH: /dawarich_db_data/dawarich_production_queue.sqlite3
|
||||
CACHE_DATABASE_PATH: /dawarich_db_data/dawarich_production_cache.sqlite3
|
||||
DATABASE_HOST: dawarich_db
|
||||
DATABASE_PORT: 5432
|
||||
DATABASE_USERNAME: postgres
|
||||
DATABASE_PASSWORD: {{ dawarich_db_password }}
|
||||
DATABASE_PASSWORD: {{ vault_dawarich.postgres_password }}
|
||||
DATABASE_NAME: dawarich_production
|
||||
REDIS_URL: redis://dawarich_redis:6379
|
||||
MIN_MINUTES_SPENT_IN_CITY: 60
|
||||
APPLICATION_HOSTS: loclog.thesatelliteoflove.com,localhost,::1,127.0.0.1
|
||||
APPLICATION_HOSTS: {{ subdomains.loclog }},localhost,::1,127.0.0.1
|
||||
TIME_ZONE: America/Denver
|
||||
APPLICATION_PROTOCOL: http
|
||||
DISTANCE_UNIT: mi
|
||||
PROMETHEUS_EXPORTER_ENABLED: false
|
||||
PROMETHEUS_EXPORTER_HOST: 0.0.0.0
|
||||
PROMETHEUS_EXPORTER_PORT: 9394
|
||||
SECRET_KEY_BASE: 1234567890
|
||||
SECRET_KEY_BASE: {{ vault_dawarich.secret_key_base }}
|
||||
RAILS_LOG_TO_STDOUT: "true"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
@@ -72,17 +86,73 @@ services:
|
||||
dawarich_db:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
dawarich_redis:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.50' # Limit CPU usage to 50% of one core
|
||||
memory: '2G' # Limit memory usage to 2GB
|
||||
cpus: '0.50'
|
||||
memory: '2G'
|
||||
dawarich_sidekiq:
|
||||
image: freikin/dawarich:latest
|
||||
container_name: dawarich_sidekiq
|
||||
labels:
|
||||
glance.parent: dawarich
|
||||
glance.name: Sidekiq
|
||||
volumes:
|
||||
- dawarich_public:/var/app/public
|
||||
- dawarich_watched:/var/app/tmp/imports/watched
|
||||
- dawarich_storage:/var/app/storage
|
||||
stdin_open: true
|
||||
tty: true
|
||||
entrypoint: sidekiq-entrypoint.sh
|
||||
command: ['sidekiq']
|
||||
restart: on-failure
|
||||
environment:
|
||||
RAILS_ENV: production
|
||||
DATABASE_HOST: dawarich_db
|
||||
DATABASE_PORT: 5432
|
||||
DATABASE_USERNAME: postgres
|
||||
DATABASE_PASSWORD: {{ vault_dawarich.postgres_password }}
|
||||
DATABASE_NAME: dawarich_production
|
||||
REDIS_URL: redis://dawarich_redis:6379
|
||||
MIN_MINUTES_SPENT_IN_CITY: 60
|
||||
APPLICATION_HOSTS: {{ subdomains.loclog }},localhost,::1,127.0.0.1
|
||||
TIME_ZONE: America/Denver
|
||||
APPLICATION_PROTOCOL: http
|
||||
DISTANCE_UNIT: mi
|
||||
PROMETHEUS_EXPORTER_ENABLED: false
|
||||
SECRET_KEY_BASE: {{ vault_dawarich.secret_key_base }}
|
||||
RAILS_LOG_TO_STDOUT: "true"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "100m"
|
||||
max-file: "5"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "ps aux | grep '[s]idekiq' || exit 1"]
|
||||
interval: 10s
|
||||
retries: 30
|
||||
start_period: 30s
|
||||
timeout: 10s
|
||||
depends_on:
|
||||
dawarich_app:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
dawarich_db:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
dawarich_redis:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
volumes:
|
||||
dawarich_db_data:
|
||||
dawarich_redis_data:
|
||||
dawarich_public:
|
||||
dawarich_watched:
|
||||
dawarich_storage:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -7,21 +7,21 @@ services:
|
||||
- database__client=sqlite3
|
||||
- database__connection__filename=/var/lib/ghost/content/data/ghost.db
|
||||
- database__useNullAsDefault=true
|
||||
- url=https://phlog.thesatelliteoflove.com
|
||||
- url=https://{{ subdomains.phlog }}
|
||||
volumes:
|
||||
- ghost:/var/lib/ghost/content
|
||||
extra_hosts:
|
||||
- 'phlog.thesatelliteoflove.com:172.20.0.5'
|
||||
- '{{ subdomains.phlog }}:172.20.0.5'
|
||||
labels:
|
||||
glance.name: Ghost
|
||||
glance.icon: si:ghost
|
||||
glance.url: https://phlog.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.phlog }}/
|
||||
glance.description: Photo Blog
|
||||
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
ghost:
|
||||
driver: local
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -7,19 +7,20 @@ services:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
- GITEA__mailer__ENABLED=true
|
||||
- GITEA__mailer__FROM=git@updates.thesatelliteoflove.com
|
||||
- GITEA__mailer__FROM=git@{{ email_domains.updates }}
|
||||
- GITEA__mailer__PROTOCOL=smtps
|
||||
- GITEA__mailer__SMTP_ADDR=smtp.resend.com
|
||||
- GITEA__mailer__SMTP_ADDR={{ smtp.host }}
|
||||
- GITEA__mailer__SMTP_PORT=465
|
||||
- GITEA__mailer__USER=resend
|
||||
- GITEA__mailer__PASSWD={{ resend_key }}
|
||||
- GITEA__mailer__USER={{ smtp.username }}
|
||||
- GITEA__mailer__PASSWD={{ vault_smtp.password }}
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
glance.name: Gitea
|
||||
glance.icon: si:gitea
|
||||
glance.url: https://git.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.git }}/
|
||||
glance.description: Code repo
|
||||
glance.id: gitea
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
- gitea:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
@@ -27,8 +28,8 @@ services:
|
||||
ports:
|
||||
- 222:22
|
||||
extra_hosts:
|
||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
||||
- 'git.thesatelliteoflove.com:172.20.0.5'
|
||||
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||
- '{{ subdomains.git }}:{{ docker.hairpin_ip }}'
|
||||
runner:
|
||||
image: gitea/act_runner:nightly
|
||||
restart: unless-stopped
|
||||
@@ -37,24 +38,25 @@ services:
|
||||
environment:
|
||||
- CONFIG_FILE=/config.yaml
|
||||
- GITEA_INSTANCE_URL=http://gitea:3000
|
||||
- GITEA_RUNNER_REGISTRATION_TOKEN={{ gitea_runner_key }}
|
||||
- GITEA_RUNNER_REGISTRATION_TOKEN={{ vault_infrastructure.gitea_runner_key }}
|
||||
- GITEA_RUNNER_NAME=runner_1
|
||||
- GITEA_RUNNER_LABELS=docker
|
||||
extra_hosts:
|
||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
||||
- 'git.thesatelliteoflove.com:172.20.0.5'
|
||||
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||
- '{{ subdomains.git }}:{{ docker.hairpin_ip }}'
|
||||
labels:
|
||||
glance.parent: gitea
|
||||
glance.name: Worker
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
- ./runner-config.yaml:/config.yaml
|
||||
- ./data:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /opt/stacks/caddy/site:/sites
|
||||
- {{ paths.stacks }}/caddy/site:/sites
|
||||
volumes:
|
||||
gitea:
|
||||
driver: local
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
glance:
|
||||
image: glanceapp/glance
|
||||
image: glanceapp/glance:latest
|
||||
volumes:
|
||||
- ./config:/app/config
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
@@ -8,16 +8,16 @@ services:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- 'thesatelliteoflove.com:172.20.0.5'
|
||||
- 'watcher.thesatelliteoflove.com:172.20.0.5'
|
||||
- '{{ primary_domain }}:172.20.0.5'
|
||||
- '{{ subdomains.watcher }}:172.20.0.5'
|
||||
labels:
|
||||
glance.name: Glance
|
||||
glance.icon: si:homepage
|
||||
glance.url: https://home.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.home }}/
|
||||
glance.description: Homepage app
|
||||
glance.id: glance
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -1,48 +1,8 @@
|
||||
pages:
|
||||
- name: Home
|
||||
columns:
|
||||
- size: small
|
||||
widgets:
|
||||
- type: calendar
|
||||
|
||||
- type: server-stats
|
||||
servers:
|
||||
- type: local
|
||||
name: Services
|
||||
|
||||
- size: full
|
||||
widgets:
|
||||
- type: group
|
||||
widgets:
|
||||
- type: hacker-news
|
||||
- type: rss
|
||||
limit: 10
|
||||
collapse-after: 3
|
||||
cache: 3h
|
||||
feeds:
|
||||
- url: https://kill-the-newsletter.com/feeds/ij4twrnzhrwvyic13qcm.xml
|
||||
- url: https://mrmoneymustache.ck.page/68f9e9826c
|
||||
- type: rss
|
||||
title: Gear
|
||||
limit: 10
|
||||
collapse-after: 3
|
||||
cache: 3h
|
||||
feeds:
|
||||
- url: https://9to5toys.com/steals/feed
|
||||
- url: https://hiro.report/rss/
|
||||
- type: change-detection
|
||||
instance-url: https://watcher.thesatelliteoflove.com
|
||||
token: ac69ae11570548549d6706eac6dbb6a9
|
||||
- type: docker-containers
|
||||
hide-by-default: false
|
||||
|
||||
- size: small
|
||||
widgets:
|
||||
- type: weather
|
||||
location: Nederland, Colorado, United States
|
||||
units: imperial
|
||||
|
||||
head-widgets:
|
||||
- type: markets
|
||||
hide-header: true
|
||||
markets:
|
||||
- symbol: SPY
|
||||
name: S&P 500
|
||||
@@ -54,12 +14,77 @@ pages:
|
||||
name: VanEck Uranium+Nuclear Energy
|
||||
- symbol: BITO
|
||||
name: Bitcoin ETF
|
||||
- symbol: GOOGL
|
||||
name: Google
|
||||
- symbol: AMD
|
||||
name: AMD
|
||||
- symbol: DJT
|
||||
name: Trump Media
|
||||
|
||||
columns:
|
||||
|
||||
- size: full
|
||||
widgets:
|
||||
- type: search
|
||||
search-engine: kagi
|
||||
new-tab: true
|
||||
|
||||
- size: small
|
||||
widgets:
|
||||
- type: weather
|
||||
location: Nederland, Colorado, United States
|
||||
units: imperial
|
||||
|
||||
- type: custom-api
|
||||
title: Air Quality
|
||||
cache: 10m
|
||||
url: https://api.waqi.info/feed/geo:39.9676367;-105.4037992/?token={{ vault_glance.air_quality_key }}
|
||||
template: |
|
||||
{% raw %}{{ $aqi := printf "%03s" (.JSON.String "data.aqi") }}
|
||||
{{ $aqiraw := .JSON.String "data.aqi" }}
|
||||
{{ $updated := .JSON.String "data.time.iso" }}
|
||||
{{ $humidity := .JSON.String "data.iaqi.h.v" }}
|
||||
{{ $ozone := .JSON.String "data.iaqi.o3.v" }}
|
||||
{{ $pm25 := .JSON.String "data.iaqi.pm25.v" }}
|
||||
{{ $pressure := .JSON.String "data.iaqi.p.v" }}
|
||||
|
||||
<div class="flex justify-between">
|
||||
<div class="size-h5">
|
||||
{{ if le $aqi "050" }}
|
||||
<div class="color-positive">Good air quality</div>
|
||||
{{ else if le $aqi "100" }}
|
||||
<div class="color-primary">Moderate air quality</div>
|
||||
{{ else }}
|
||||
<div class="color-negative">Bad air quality</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="color-highlight size-h2">AQI: {{ $aqiraw }}</div>
|
||||
<div style="border-bottom: 1px solid; margin-block: 10px;"></div>
|
||||
|
||||
<div class="margin-block-2">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
|
||||
|
||||
<div>
|
||||
<div class="size-h3 color-highlight">{{ $humidity }}%</div>
|
||||
<div class="size-h6">HUMIDITY</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="size-h3 color-highlight">{{ $ozone }} μg/m³</div>
|
||||
<div class="size-h6">OZONE</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="size-h3 color-highlight">{{ $pm25 }} μg/m³</div>
|
||||
<div class="size-h6">PM2.5</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="size-h3 color-highlight">{{ $pressure }} hPa</div>
|
||||
<div class="size-h6">PRESSURE</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="size-h6" style="margin-top: 10px;">Last Updated at {{ slice $updated 11 16 }}</div>
|
||||
</div>{% endraw %}
|
||||
|
||||
- name: Mini Painting
|
||||
columns:
|
||||
- size: small
|
||||
|
47
roles/docker/templates/gotify-compose.yml.j2
Normal file
47
roles/docker/templates/gotify-compose.yml.j2
Normal file
@@ -0,0 +1,47 @@
|
||||
services:
|
||||
gotify:
|
||||
image: gotify/server:latest
|
||||
container_name: gotify
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- gotify_data:/app/data
|
||||
environment:
|
||||
- GOTIFY_DEFAULTUSER_PASS={{ vault_gotify.admin_password }}
|
||||
- TZ=America/Denver
|
||||
labels:
|
||||
glance.name: Gotify
|
||||
glance.icon: si:gotify
|
||||
glance.url: "https://{{ subdomains.gotify }}/"
|
||||
glance.description: Push notification server
|
||||
extra_hosts:
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
- "{{ subdomains.gotify_assistant }}:{{ docker.hairpin_ip }}"
|
||||
|
||||
igotify-assistant:
|
||||
image: ghcr.io/androidseb25/igotify-notification-assist:latest
|
||||
restart: unless-stopped
|
||||
container_name: igotify-assistant
|
||||
volumes:
|
||||
- igotify_data:/app/data
|
||||
environment:
|
||||
TZ: America/Denver
|
||||
depends_on:
|
||||
- gotify
|
||||
labels:
|
||||
glance.name: iGotify Assistant
|
||||
glance.icon: si:apple
|
||||
glance.url: "https://{{ subdomains.gotify_assistant }}/"
|
||||
glance.description: iOS notification assistant
|
||||
mag37.dockcheck.update: true
|
||||
extra_hosts:
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
- "{{ subdomains.gotify }}:{{ docker.hairpin_ip }}"
|
||||
|
||||
volumes:
|
||||
gotify_data:
|
||||
igotify_data:
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: "{{ docker.network_name }}"
|
@@ -4,28 +4,28 @@ services:
|
||||
container_name: gotosocial
|
||||
user: 1000:1000
|
||||
extra_hosts:
|
||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
||||
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||
environment:
|
||||
GTS_HOST: social.thesatelliteoflove.com
|
||||
GTS_HOST: {{ subdomains.social }}
|
||||
GTS_DB_TYPE: sqlite
|
||||
GTS_DB_ADDRESS: /gotosocial/storage/sqlite.db
|
||||
GTS_WAZERO_COMPILATION_CACHE: /gotosocial/.cache
|
||||
GTS_LETSENCRYPT_ENABLED: "false"
|
||||
GTS_LETSENCRYPT_EMAIL_ADDRESS: ""
|
||||
GTS_TRUSTED_PROXIES: "172.20.0.5"
|
||||
GTS_ACCOUNT_DOMAIN: thesatelliteoflove.com
|
||||
GTS_TRUSTED_PROXIES: "{{ docker.hairpin_ip }}"
|
||||
GTS_ACCOUNT_DOMAIN: {{ primary_domain }}
|
||||
GTS_OIDC_ENABLED: "true"
|
||||
GTS_OIDC_IDP_NAME: "Authentik"
|
||||
GTS_OIDC_ISSUER: https://auth.thesatelliteoflove.com/application/o/gotosocial/
|
||||
GTS_OIDC_CLIENT_ID: {{ gts_oidc_client_id }}
|
||||
GTS_OIDC_CLIENT_SECRET: {{ gts_oidc_client_secret }}
|
||||
GTS_OIDC_ISSUER: https://{{ subdomains.auth }}/application/o/gotosocial/
|
||||
GTS_OIDC_CLIENT_ID: {{ vault_gotosocial.oidc.client_id }}
|
||||
GTS_OIDC_CLIENT_SECRET: {{ vault_gotosocial.oidc.client_secret }}
|
||||
GTS_OIDC_LINK_EXISTING: "true"
|
||||
GTS_HTTP_CLIENT: "20s"
|
||||
GTS_SMTP_HOST: "smtp.resend.com"
|
||||
GTS_SMTP_HOST: "{{ smtp.host }}"
|
||||
GTS_SMTP_PORT: "587"
|
||||
GTS_SMTP_USERNAME: "resend"
|
||||
GTS_SMTP_PASSWORD: {{ resend_key }}
|
||||
GTS_SMTP_FROM: "social@updates.thesatelliteoflove.com"
|
||||
GTS_SMTP_USERNAME: "{{ smtp.username }}"
|
||||
GTS_SMTP_PASSWORD: {{ vault_smtp.password }}
|
||||
GTS_SMTP_FROM: "social@{{ email_domains.updates }}"
|
||||
TZ: UTC
|
||||
volumes:
|
||||
- gotosocial:/gotosocial/storage
|
||||
@@ -34,7 +34,7 @@ services:
|
||||
docker-volume-backup.stop-during-backup: true
|
||||
glance.name: GoToSocial
|
||||
glance.icon: si:mastodon
|
||||
glance.url: https://social.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.social }}/
|
||||
glance.description: Fediverse server
|
||||
glance.id: gotosocial
|
||||
|
||||
@@ -44,23 +44,19 @@ services:
|
||||
labels:
|
||||
glance.parent: gotosocial
|
||||
glance.name: Backup
|
||||
mag37.dockcheck.update: true
|
||||
environment:
|
||||
BACKUP_FILENAME: backup-gts-%Y-%m-%dT%H-%M-%S.tar.gz
|
||||
BACKUP_LATEST_SYMLINK: backup-latest.tar.gz
|
||||
BACKUP_FILENAME: gts-backup-%Y-%m-%dT%H-%M-%S.tar.gz
|
||||
BACKUP_CRON_EXPRESSION: "0 9 * * *"
|
||||
BACKUP_PRUNING_PREFIX: backup-
|
||||
BACKUP_RETENTION_DAYS: 1
|
||||
BACKUP_PRUNING_PREFIX: gts-
|
||||
BACKUP_RETENTION_DAYS: 7
|
||||
AWS_S3_BUCKET_NAME: tsolbackups
|
||||
AWS_ENDPOINT: s3.us-west-004.backblazeb2.com
|
||||
AWS_ACCESS_KEY_ID: {{ backup_key_id }}
|
||||
AWS_SECRET_ACCESS_KEY: {{ backup_key }}
|
||||
BACKUP_SKIP_BACKENDS_FROM_PRUNE: s3
|
||||
|
||||
|
||||
AWS_ACCESS_KEY_ID: {{ vault_backup.access_key_id }}
|
||||
AWS_SECRET_ACCESS_KEY: {{ vault_backup.secret_access_key }}
|
||||
volumes:
|
||||
- gotosocial:/backup/my-app-backup:ro
|
||||
- gotosocial:/backup/gts-app-backup:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ./backup:/archive
|
||||
|
||||
volumes:
|
||||
gotosocial:
|
||||
@@ -69,4 +65,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
30
roles/docker/templates/grocy-compose.yml.j2
Normal file
30
roles/docker/templates/grocy-compose.yml.j2
Normal file
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
grocy:
|
||||
image: lscr.io/linuxserver/grocy:latest
|
||||
container_name: grocy
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=America/Denver
|
||||
volumes:
|
||||
- ./config:/config
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
labels:
|
||||
glance.name: Grocy
|
||||
glance.icon: si:grocyapp
|
||||
glance.url: https://{{ subdomains.grocy }}/
|
||||
glance.description: Kitchen ERP and inventory management
|
||||
glance.id: grocy
|
||||
mag37.dockcheck.update: true
|
||||
|
||||
volumes:
|
||||
grocy_config:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: {{ docker.network_name }}
|
@@ -11,21 +11,21 @@ services:
|
||||
labels:
|
||||
glance.name: Heyform
|
||||
glance.icon: si:googleforms
|
||||
glance.url: https://forms.nerder.land/
|
||||
glance.url: https://{{ subdomains.heyform }}/
|
||||
glance.description: Forms server
|
||||
glance.id: heyform
|
||||
environment:
|
||||
- APP_HOMEPAGE_URL=http://forms.nerder.land
|
||||
- SESSION_KEY={{ heyform_session_key }}
|
||||
- FORM_ENCRYPTION_KEY={{ heyform_encryption_key }}
|
||||
- APP_HOMEPAGE_URL=http://{{ subdomains.heyform }}
|
||||
- SESSION_KEY={{ vault_heyform.session_key }}
|
||||
- FORM_ENCRYPTION_KEY={{ vault_heyform.encryption_key }}
|
||||
- MONGO_URI='mongodb://mongo:27017/heyform'
|
||||
- REDIS_HOST=keydb
|
||||
- REDIS_PORT=6379
|
||||
- SMTP_FROM=nerderland@updates.thesatelliteoflove.com
|
||||
- SMTP_HOST=smtp.resend.com
|
||||
- SMTP_FROM=nerderland@{{ email_domains.updates }}
|
||||
- SMTP_HOST={{ smtp.host }}
|
||||
- SMTP_PORT=465
|
||||
- SMTP_USER=resend
|
||||
- SMTP_PASSWORD={{ resend_key }}
|
||||
- SMTP_USER={{ smtp.username }}
|
||||
- SMTP_PASSWORD={{ vault_smtp.password }}
|
||||
- SMTP_SECURE=true
|
||||
|
||||
mongo:
|
||||
@@ -60,4 +60,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -1,7 +1,7 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
web:
|
||||
image: ghcr.io/karakeep-app/karakeep:${KARAKEEP_VERSION:-release}
|
||||
image: ghcr.io/karakeep-app/karakeep:latest
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- data:/data
|
||||
@@ -10,8 +10,8 @@ services:
|
||||
env_file:
|
||||
- .env
|
||||
extra_hosts:
|
||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
||||
- bookmarks.thesatelliteoflove.com:172.20.0.5
|
||||
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||
- '{{ subdomains.bookmarks }}:{{ docker.hairpin_ip }}'
|
||||
environment:
|
||||
MEILI_ADDR: http://meilisearch:7700
|
||||
DATA_DIR: /data
|
||||
@@ -19,15 +19,17 @@ services:
|
||||
labels:
|
||||
glance.name: Karakeep
|
||||
glance.icon: si:wikibooks
|
||||
glance.url: https://bookmarks.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.bookmarks }}/
|
||||
glance.description: Bookmark manager
|
||||
glance.id: karakeep
|
||||
mag37.dockcheck.update: true
|
||||
chrome:
|
||||
image: gcr.io/zenika-hub/alpine-chrome:123
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
glance.name: Chrome
|
||||
glance.parent: karakeep
|
||||
mag37.dockcheck.update: true
|
||||
command:
|
||||
- --no-sandbox
|
||||
- --disable-gpu
|
||||
@@ -41,6 +43,7 @@ services:
|
||||
labels:
|
||||
glance.name: Meilisearch
|
||||
glance.parent: karakeep
|
||||
mag37.dockcheck.update: true
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
@@ -53,4 +56,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -1,10 +1,10 @@
|
||||
KARAKEEP_VERSION=release
|
||||
NEXTAUTH_SECRET={{ hoarder_nextauth_secret }}
|
||||
MEILI_MASTER_KEY={{ hoarder_meili_master_key }}
|
||||
NEXTAUTH_URL=https://bookmarks.thesatelliteoflove.com
|
||||
OPENAI_API_KEY={{ openai_api_key }}
|
||||
OAUTH_CLIENT_SECRET={{ hoarder_oidc_client_secret }}
|
||||
NEXTAUTH_SECRET={{ vault_hoarder.nextauth_secret }}
|
||||
MEILI_MASTER_KEY={{ vault_hoarder.meili_master_key }}
|
||||
NEXTAUTH_URL=https://{{ subdomains.bookmarks }}
|
||||
OPENAI_API_KEY={{ vault_infrastructure.openai_api_key }}
|
||||
OAUTH_CLIENT_SECRET={{ vault_hoarder.oidc.client_secret }}
|
||||
OAUTH_CLIENT_ID=GTi0QBRH5TiTqZfxfAkYSQVVFouGdlOFMc2sjivN
|
||||
OAUTH_PROVIDER_NAME=Authentik
|
||||
OAUTH_WELLKNOWN_URL=https://auth.thesatelliteoflove.com/application/o/hoarder/.well-known/openid-configuration
|
||||
OAUTH_WELLKNOWN_URL=https://{{ subdomains.auth }}/application/o/hoarder/.well-known/openid-configuration
|
||||
OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING=true
|
32
roles/docker/templates/kanboard-compose.yml.j2
Normal file
32
roles/docker/templates/kanboard-compose.yml.j2
Normal file
@@ -0,0 +1,32 @@
|
||||
services:
|
||||
kanboard:
|
||||
image: kanboard/kanboard:latest
|
||||
container_name: kanboard
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PLUGIN_INSTALLER=true
|
||||
- DB_DRIVER=sqlite
|
||||
volumes:
|
||||
- kanboard_data:/var/www/app/data
|
||||
- kanboard_plugins:/var/www/app/plugins
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
labels:
|
||||
glance.name: Kanboard
|
||||
glance.icon: si:kanboard
|
||||
glance.url: https://{{ subdomains.kanboard }}/
|
||||
glance.description: Project management and Kanban boards
|
||||
glance.id: kanboard
|
||||
mag37.dockcheck.update: true
|
||||
|
||||
volumes:
|
||||
kanboard_data:
|
||||
driver: local
|
||||
kanboard_plugins:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: {{ docker.network_name }}
|
@@ -12,23 +12,24 @@ services:
|
||||
# The container path can be anything; you will need to enter it in the "new library" form.
|
||||
- ./models:/models
|
||||
environment:
|
||||
SECRET_KEY_BASE: {{manyfold_key}}
|
||||
SECRET_KEY_BASE: {{ vault_manyfold.secret_key }}
|
||||
MULTIUSER: enabled
|
||||
OIDC_CLIENT_ID: {{ manyfold_oidc_client_id }}
|
||||
OIDC_CLIENT_SECRET: {{ manyfold_oidc_client_secret }}
|
||||
OIDC_ISSUER: https://auth.thesatelliteoflove.com/application/o/manyfold/
|
||||
OIDC_CLIENT_ID: {{ vault_manyfold.oidc.client_id }}
|
||||
OIDC_CLIENT_SECRET: {{ vault_manyfold.oidc.client_secret }}
|
||||
OIDC_ISSUER: https://{{ subdomains.auth }}/application/o/manyfold/
|
||||
OIDC_NAME: Authentik
|
||||
PUBLIC_HOSTNAME: models.thesatelliteoflove.com
|
||||
PUBLIC_HOSTNAME: {{ subdomains.models }}
|
||||
MAX_FILE_UPLOAD_SIZE: 5368709120
|
||||
PUID: 1000
|
||||
PGID: 1000
|
||||
extra_hosts:
|
||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
labels:
|
||||
glance.name: Manyfold
|
||||
glance.icon: si:open3d
|
||||
glance.url: https://models.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.models }}/
|
||||
glance.description: STL Storage
|
||||
mag37.dockcheck.update: true
|
||||
restart: unless-stopped
|
||||
# Optional, but recommended for better security
|
||||
security_opt:
|
||||
@@ -44,4 +45,4 @@ services:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: "{{ docker.network_name }}"
|
@@ -9,14 +9,15 @@ services:
|
||||
- .env.local
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
- "auth.thesatelliteoflove.com:172.20.0.5"
|
||||
- "cal.thesatelliteoflove.com:172.20.0.5"
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
- "{{ subdomains.cal }}:{{ docker.hairpin_ip }}"
|
||||
labels:
|
||||
glance.name: MMDL
|
||||
glance.icon: si:task
|
||||
glance.url: https://tasks.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.tasks }}/
|
||||
glance.description: Task and calendar management
|
||||
glance.id: mmdl
|
||||
mag37.dockcheck.update: true
|
||||
|
||||
mmdl_db:
|
||||
image: mysql:8.0
|
||||
@@ -26,8 +27,8 @@ services:
|
||||
environment:
|
||||
MYSQL_DATABASE: mmdl
|
||||
MYSQL_USER: mmdl
|
||||
MYSQL_PASSWORD: "{{ vault_mmdl_mysql_password }}"
|
||||
MYSQL_ROOT_PASSWORD: "{{ vault_mmdl_mysql_root_password }}"
|
||||
MYSQL_PASSWORD: "{{ vault_mmdl.mysql_password }}"
|
||||
MYSQL_ROOT_PASSWORD: "{{ vault_mmdl.mysql_root_password }}"
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_ROOT_HOST: "%"
|
||||
volumes:
|
||||
@@ -35,6 +36,7 @@ services:
|
||||
labels:
|
||||
glance.parent: mmdl
|
||||
glance.name: DB
|
||||
mag37.dockcheck.update: true
|
||||
|
||||
volumes:
|
||||
mmdl_db:
|
||||
@@ -43,4 +45,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -1,32 +1,32 @@
|
||||
# Database Configuration
|
||||
DB_HOST=mmdl_db
|
||||
DB_USER=mmdl
|
||||
DB_PASS={{ vault_mmdl_mysql_password }}
|
||||
DB_PASS={{ vault_mmdl.mysql_password }}
|
||||
DB_PORT=3306
|
||||
DB_DIALECT=mysql
|
||||
DB_CHARSET=utf8mb4
|
||||
DB_NAME=mmdl
|
||||
|
||||
# Encryption
|
||||
AES_PASSWORD={{ vault_mmdl_aes_password }}
|
||||
AES_PASSWORD={{ vault_mmdl.aes_password }}
|
||||
|
||||
# SMTP Settings
|
||||
SMTP_HOST=smtp.resend.com
|
||||
SMTP_USERNAME=resend
|
||||
SMTP_PASSWORD={{ resend_key }}
|
||||
SMTP_FROM=tasks@updates.thesatelliteoflove.com
|
||||
SMTP_HOST={{ smtp.host }}
|
||||
SMTP_USERNAME={{ smtp.username }}
|
||||
SMTP_PASSWORD={{ vault_smtp.password }}
|
||||
SMTP_FROM=tasks@{{ email_domains.updates }}
|
||||
SMTP_PORT=587
|
||||
SMTP_SECURE=true
|
||||
|
||||
# Authentication
|
||||
USE_NEXT_AUTH=true
|
||||
NEXTAUTH_URL=https://tasks.thesatelliteoflove.com
|
||||
NEXTAUTH_SECRET={{ vault_mmdl_nextauth_secret }}
|
||||
NEXTAUTH_URL=https://{{ subdomains.tasks }}
|
||||
NEXTAUTH_SECRET={{ vault_mmdl.nextauth_secret }}
|
||||
|
||||
# Authentik OIDC Configuration
|
||||
AUTHENTIK_ISSUER=https://auth.thesatelliteoflove.com/application/o/mmdl
|
||||
AUTHENTIK_CLIENT_ID={{ vault_mmdl_oidc_client_id }}
|
||||
AUTHENTIK_CLIENT_SECRET={{ vault_mmdl_oidc_client_secret }}
|
||||
AUTHENTIK_ISSUER=https://{{ subdomains.auth }}/application/o/mmdl
|
||||
AUTHENTIK_CLIENT_ID={{ vault_mmdl.oidc.client_id }}
|
||||
AUTHENTIK_CLIENT_SECRET={{ vault_mmdl.oidc.client_secret }}
|
||||
|
||||
# User and Session Management
|
||||
ALLOW_USER_REGISTRATION=false
|
||||
@@ -35,7 +35,8 @@ OTP_VALIDITY_PERIOD=300
|
||||
SESSION_VALIDITY_PERIOD=30
|
||||
|
||||
# Application Settings
|
||||
API_URL=https://tasks.thesatelliteoflove.com
|
||||
API_URL=https://{{ subdomains.tasks }}
|
||||
DEBUG_MODE=false
|
||||
TEST_MODE=false
|
||||
NEXT_API_DEBUG_MODE=false
|
||||
SUBTASK_RECURSION_DEPTH=5
|
30
roles/docker/templates/obsidian-livesync-compose.yml.j2
Normal file
30
roles/docker/templates/obsidian-livesync-compose.yml.j2
Normal file
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
obsidian-livesync:
|
||||
image: oleduc/docker-obsidian-livesync-couchdb:latest
|
||||
container_name: obsidian-livesync
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
glance.name: Obsidian LiveSync
|
||||
glance.icon: si:obsidian
|
||||
glance.url: http://{{ network.docker_host_ip }}:5984
|
||||
glance.description: Obsidian note synchronization
|
||||
glance.id: obsidian-livesync
|
||||
environment:
|
||||
- SERVER_DOMAIN={{ network.docker_host_ip }}
|
||||
- COUCHDB_USER={{ vault_obsidian.username }}
|
||||
- COUCHDB_PASSWORD={{ vault_obsidian.password }}
|
||||
- COUCHDB_DATABASE=obsidian
|
||||
ports:
|
||||
- "{{ network.docker_host_ip }}:5984:5984"
|
||||
volumes:
|
||||
- couchdb_data:/opt/couchdb/data
|
||||
networks:
|
||||
- default
|
||||
|
||||
volumes:
|
||||
couchdb_data:
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: "{{ docker.network_name }}"
|
30
roles/docker/templates/palmr-compose.yml.j2
Normal file
30
roles/docker/templates/palmr-compose.yml.j2
Normal file
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
palmr:
|
||||
image: kyantech/palmr:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DISABLE_FILESYSTEM_ENCRYPTION: "false"
|
||||
ENCRYPTION_KEY: "{{ vault_palmr.encryption_key }}"
|
||||
PALMR_UID: "1000"
|
||||
PALMR_GID: "1000"
|
||||
SECURE_SITE: "true"
|
||||
DEFAULT_LANGUAGE: "en-US"
|
||||
TRUST_PROXY: "true"
|
||||
extra_hosts:
|
||||
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||
labels:
|
||||
glance.name: Palmr
|
||||
glance.icon: si:files
|
||||
glance.url: "https://{{ subdomains.files }}/"
|
||||
glance.description: File sharing and storage
|
||||
glance.id: palmr
|
||||
mag37.dockcheck.update: true
|
||||
volumes:
|
||||
- palmr_data:/app/server
|
||||
volumes:
|
||||
palmr_data:
|
||||
driver: local
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: "{{ docker.network_name }}"
|
@@ -14,7 +14,7 @@ services:
|
||||
labels:
|
||||
glance.name: Paperless NGX
|
||||
glance.icon: si:paperlessngx
|
||||
glance.url: https://papers.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.paper }}/
|
||||
glance.description: Document server
|
||||
glance.id: paperlessngx
|
||||
depends_on:
|
||||
@@ -28,7 +28,7 @@ services:
|
||||
- ./consume:/usr/src/paperless/consume
|
||||
env_file: docker-compose.env
|
||||
extra_hosts:
|
||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
||||
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||
environment:
|
||||
PAPERLESS_REDIS: redis://broker:6379
|
||||
PAPERLESS_TIKA_ENABLED: 1
|
||||
@@ -57,6 +57,26 @@ services:
|
||||
glance.name: Tika
|
||||
restart: unless-stopped
|
||||
|
||||
backup:
|
||||
image: offen/docker-volume-backup:v2
|
||||
restart: always
|
||||
labels:
|
||||
glance.parent: paperlessngx
|
||||
glance.name: Backup
|
||||
mag37.dockcheck.update: true
|
||||
environment:
|
||||
BACKUP_FILENAME: pngx-backup-%Y-%m-%dT%H-%M-%S.tar.gz
|
||||
BACKUP_CRON_EXPRESSION: "10 9 * * *"
|
||||
BACKUP_PRUNING_PREFIX: pngx-
|
||||
BACKUP_RETENTION_DAYS: 7
|
||||
AWS_S3_BUCKET_NAME: tsolbackups
|
||||
AWS_ENDPOINT: s3.us-west-004.backblazeb2.com
|
||||
AWS_ACCESS_KEY_ID: {{ vault_backup.access_key_id }}
|
||||
AWS_SECRET_ACCESS_KEY: {{ vault_backup.secret_access_key }}
|
||||
volumes:
|
||||
- media:/backup/pngx-app-backup:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
|
||||
volumes:
|
||||
data:
|
||||
media:
|
||||
@@ -65,4 +85,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -24,11 +24,11 @@
|
||||
|
||||
# This is required if you will be exposing Paperless-ngx on a public domain
|
||||
# (if doing so please consider security measures such as reverse proxy)
|
||||
PAPERLESS_URL=https://paper.thesatelliteoflove.com
|
||||
PAPERLESS_URL=https://{{ subdomains.paper }}
|
||||
|
||||
# Adjust this key if you plan to make paperless available publicly. It should
|
||||
# be a very long sequence of random characters. You don't need to remember it.
|
||||
PAPERLESS_SECRET_KEY={{ paperlessngx_secret }}
|
||||
PAPERLESS_SECRET_KEY={{ vault_paperlessngx.secret_key }}
|
||||
|
||||
# Use this variable to set a timezone for the Paperless Docker containers. If not specified, defaults to UTC.
|
||||
PAPERLESS_TIME_ZONE=America/Denver
|
||||
@@ -43,4 +43,4 @@ PAPERLESS_TIME_ZONE=America/Denver
|
||||
|
||||
# authentik
|
||||
PAPERLESS_APPS: "allauth.socialaccount.providers.openid_connect"
|
||||
PAPERLESS_SOCIALACCOUNT_PROVIDERS: '{"openid_connect": {"APPS": [{"provider_id": "authentik","name": "Authentik SSO","client_id": "{{ paperless_oauth_client_id }}","secret": "{{ paperless_oauth_client_secret }}","settings": { "server_url": "https://auth.thesatelliteoflove.com/application/o/paperlessngx/.well-known/openid-configuration"}}]}}'
|
||||
PAPERLESS_SOCIALACCOUNT_PROVIDERS: '{"openid_connect": {"APPS": [{"provider_id": "authentik","name": "Authentik SSO","client_id": "{{ vault_paperlessngx.oidc.client_id }}","secret": "{{ vault_paperlessngx.oidc.client_secret }}","settings": { "server_url": "https://{{ subdomains.auth }}/application/o/paperlessngx/.well-known/openid-configuration"}}]}}'
|
@@ -1,24 +0,0 @@
|
||||
services:
|
||||
pingvin-share:
|
||||
image: stonith404/pingvin-share:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TRUST_PROXY=true
|
||||
extra_hosts:
|
||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
||||
labels:
|
||||
glance.name: Pingvin
|
||||
glance.icon: si:files
|
||||
glance.url: http://netcup.porgy-porgy.ts.net:8945
|
||||
glance.description: File sharing service
|
||||
glance.id: pingvin
|
||||
volumes:
|
||||
- data:/opt/app/backend/data
|
||||
- images:/opt/app/frontend/public/img
|
||||
volumes:
|
||||
images:
|
||||
data:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
@@ -5,7 +5,7 @@ services:
|
||||
labels:
|
||||
glance.name: Pinry
|
||||
glance.icon: si:pinterest
|
||||
glance.url: https://pin.thesatelliteoflove.com
|
||||
glance.url: https://{{ subdomains.pin }}
|
||||
glance.description: Pinterest clone
|
||||
glance.id: pinterest
|
||||
environment:
|
||||
@@ -18,4 +18,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
@@ -5,9 +5,9 @@ services:
|
||||
restart: always
|
||||
environment:
|
||||
# You must change these. Replace `postiz.your-server.com` with your DNS name - what your web browser sees.
|
||||
MAIN_URL: "https://post.thesatelliteoflove.com"
|
||||
FRONTEND_URL: "https://post.thesatelliteoflove.com"
|
||||
NEXT_PUBLIC_BACKEND_URL: "https://post.thesatelliteoflove.com/api"
|
||||
MAIN_URL: "https://{{ subdomains.post }}"
|
||||
FRONTEND_URL: "https://{{ subdomains.post }}"
|
||||
NEXT_PUBLIC_BACKEND_URL: "https://{{ subdomains.post }}/api"
|
||||
JWT_SECRET: "TShr6Fdcwf67wIhuUvg0gOsJbdcQmgMiJl5kUh6JCfY="
|
||||
|
||||
# These defaults are probably fine, but if you change your user/password, update it in the
|
||||
@@ -24,7 +24,7 @@ services:
|
||||
|
||||
# Social keys
|
||||
LINKEDIN_CLIENT_ID: "86q7ksc8q5pai3"
|
||||
LINKEDIN_CLIENT_SECRET: {{ linkedin_secret }}
|
||||
LINKEDIN_CLIENT_SECRET: {{ vault_postiz.linkedin_secret }}
|
||||
volumes:
|
||||
- postiz-config:/config/
|
||||
- postiz-uploads:/uploads/
|
||||
@@ -35,9 +35,10 @@ services:
|
||||
condition: service_healthy
|
||||
labels:
|
||||
glance.name: Postiz
|
||||
glance.url: https://post.thesatelliteoflove.com/
|
||||
glance.url: https://{{ subdomains.post }}/
|
||||
glance.description: Social media scheduler
|
||||
glance.id: postiz
|
||||
mag37.dockcheck.update: true
|
||||
|
||||
postiz-postgres:
|
||||
image: postgres:14.5
|
||||
@@ -57,6 +58,7 @@ services:
|
||||
labels:
|
||||
glance.parent: postiz
|
||||
glance.name: DB
|
||||
mag37.dockcheck.update: true
|
||||
postiz-redis:
|
||||
image: redis:7.2
|
||||
container_name: postiz-redis
|
||||
@@ -71,6 +73,7 @@ services:
|
||||
labels:
|
||||
glance.parent: postiz
|
||||
glance.name: Redis
|
||||
mag37.dockcheck.update: true
|
||||
|
||||
|
||||
|
||||
@@ -90,4 +93,4 @@ volumes:
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: lava
|
||||
name: {{ docker.network_name }}
|
28
todo.md
28
todo.md
@@ -9,26 +9,26 @@
|
||||
roles/docker/tasks/
|
||||
├── main.yml (orchestrator)
|
||||
├── infrastructure/ (caddy, authentik, dockge)
|
||||
├── development/ (gitea, codeserver, conduit)
|
||||
├── development/ (gitea, codeserver, bytestash)
|
||||
├── media/ (audiobookshelf, calibre, ghost, pinchflat, pinry, hoarder, manyfold)
|
||||
├── productivity/ (paperless, baikal, syncthing, mmdl, heyform, dawarich, pingvin)
|
||||
├── productivity/ (paperless, baikal, syncthing, mmdl, heyform, dawarich, palmr, obsidian-livesync)
|
||||
├── communication/ (gotosocial, postiz)
|
||||
└── monitoring/ (glance, changedetection, appriseapi)
|
||||
└── monitoring/ (glance, changedetection, appriseapi, gotify)
|
||||
```
|
||||
- **COMPLETED**: All services organized into logical categories with category-level tags
|
||||
|
||||
### 2. Standardize variable management
|
||||
### 2. Standardize variable management ✅ COMPLETED
|
||||
- **Current Issue**: Secrets in single encrypted file, no clear variable hierarchy
|
||||
- **Solution**: Create proper variable structure:
|
||||
```
|
||||
group_vars/
|
||||
├── all/
|
||||
│ ├── common.yml (shared config)
|
||||
│ └── secrets.yml (vault encrypted)
|
||||
├── docker/
|
||||
│ ├── services.yml (service configs)
|
||||
│ └── networking.yml (network settings)
|
||||
│ ├── domains.yml (domain and subdomain mappings)
|
||||
│ ├── infrastructure.yml (network config, Docker settings)
|
||||
│ ├── vault.yml (encrypted secrets with vault_ prefix)
|
||||
│ └── services.yml (service configuration flags)
|
||||
```
|
||||
- **COMPLETED**: Implemented comprehensive variable hierarchy, updated all templates to use centralized variables, fixed service tag isolation
|
||||
|
||||
### 3. Template consolidation ✅ PARTIALLY COMPLETED
|
||||
- **Current Issue**: Many compose templates repeat patterns, some services used static files
|
||||
@@ -43,7 +43,7 @@
|
||||
- **Solution**: Implement comprehensive health monitoring with standardized healthcheck patterns
|
||||
|
||||
### 5. Implement backup strategy
|
||||
- **Issue**: No automated backups for 25+ services and their data
|
||||
- **Issue**: No automated backups for 25 services and their data
|
||||
- **Solution**: Add backup role with:
|
||||
- Database dumps for PostgreSQL services
|
||||
- Volume backups for file-based services
|
||||
@@ -99,7 +99,7 @@
|
||||
- [x] Convert static compose files to templates
|
||||
- [x] Remove unused services (beaver, grist, stirlingpdf, tasksmd, redlib)
|
||||
- [x] Clean up templates and files directories
|
||||
- [ ] Implement variable hierarchy
|
||||
- [x] Implement variable hierarchy
|
||||
- [ ] Create reusable template patterns
|
||||
|
||||
### Week 2: Security & Monitoring
|
||||
@@ -124,10 +124,12 @@
|
||||
- **Template Standardization**: Converted all static compose files to Jinja2 templates
|
||||
- **Service Cleanup**: Removed 5 unused/broken services (beaver, grist, stirlingpdf, tasksmd, redlib)
|
||||
- **Category-Based Deployment**: Can now deploy services by category using tags (infrastructure, media, etc.)
|
||||
- **Documentation Updates**: Updated CLAUDE.md to reflect new architecture
|
||||
- **Variable Management**: Implemented comprehensive centralized variable hierarchy with proper secret organization
|
||||
- **Service Tag Isolation**: Fixed service tags to deploy individual services only (not entire categories)
|
||||
- **Documentation Updates**: Updated all README files and CLAUDE.md to reflect new architecture
|
||||
|
||||
### 📊 Current Stats
|
||||
- **22+ active services** organized into 6 categories
|
||||
- **25 active services** organized into 6 categories
|
||||
- **100% templated** compose files (no static files)
|
||||
- **6 service directories** for logical organization
|
||||
- **Clean file structure** with only essential static files
|
||||
|
Reference in New Issue
Block a user