Compare commits
55 Commits
27564a35e4
...
main
Author | SHA1 | Date | |
---|---|---|---|
01d959d12c | |||
a4fc5f7608 | |||
e3f4eb4e95 | |||
a8350459ae | |||
eac67e269c | |||
85cfca08f5 | |||
2cc05a19e6 | |||
d54d04bcc9 | |||
5f76f69d8b | |||
ef5309363c | |||
ff89683038 | |||
a338186a77 | |||
8710ffc70d | |||
a98fae0b92 | |||
d05bac8651 | |||
c500790ea3 | |||
2e4c096bbe | |||
12582b352c | |||
8d686c2aa5 | |||
249eb52ceb | |||
ef4f49fafb | |||
06a7889024 | |||
68f0276ac0 | |||
d4bec94b99 | |||
8ca2122cb3 | |||
ccab665d26 | |||
1c9ab0f5e6 | |||
7fdb52e91b | |||
a2c3b53640 | |||
e1f09fc119 | |||
1280bba7ff | |||
798d35be16 | |||
4fb991ac52 | |||
4d1732ff16 | |||
2a7bd0dc74 | |||
c94c3641b0 | |||
e7cac9e19c | |||
3fbd0c5053 | |||
579fb581c6 | |||
37f47a4cf3 | |||
e3cef5ec47 | |||
47cf24b637 | |||
fe596a2387 | |||
3908ffa9e6 | |||
e8c9d42b77 | |||
1271fdc2ce | |||
12a664415d | |||
58ddde7dfc | |||
d2d0accd2c | |||
d43f70b68f | |||
951531df0c | |||
6620fe6a86 | |||
27fce8c757 | |||
8b5e82b7e1 | |||
cbc343884b |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,5 @@
|
|||||||
.python-version
|
.python-version
|
||||||
secrets.enc
|
secrets.enc
|
||||||
|
vault_pass
|
||||||
|
DEPLOYMENT_LEARNINGS.md
|
||||||
|
group_vars/all/vault.yml
|
164
CLAUDE.md
Normal file
164
CLAUDE.md
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This is a personal infrastructure Ansible playbook that automates deployment and management of 24 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.
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
### Initial Setup
|
||||||
|
```bash
|
||||||
|
# Install Ansible dependencies
|
||||||
|
ansible-galaxy install -r requirements.yml
|
||||||
|
|
||||||
|
# Bootstrap new server (creates user, installs Tailscale, security hardening)
|
||||||
|
ansible-playbook bootstrap.yml -i hosts.yml
|
||||||
|
|
||||||
|
# Deploy all Docker services
|
||||||
|
ansible-playbook site.yml -i hosts.yml
|
||||||
|
|
||||||
|
# Update DNS records in AWS Route53
|
||||||
|
ansible-playbook dns.yml -i hosts.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Management
|
||||||
|
```bash
|
||||||
|
# Deploy specific services using tags (now properly isolated)
|
||||||
|
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 --vault-password-file vault_pass --extra-vars "@secrets.enc"
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags mmdl --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 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"
|
||||||
|
|
||||||
|
# Deploy only infrastructure components
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags common,cron --vault-password-file vault_pass --extra-vars "@secrets.enc"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Host Configuration
|
||||||
|
- **Bootstrap Host** (`netcup`): 152.53.36.98 - Initial server setup target
|
||||||
|
- **Docker Host** (`docker-01`): 100.70.169.99 - Main service deployment via Tailscale
|
||||||
|
|
||||||
|
### Role Structure
|
||||||
|
- **bootstrap**: Initial server hardening, user creation, Tailscale VPN setup
|
||||||
|
- **common**: Basic system configuration, UFW firewall management
|
||||||
|
- **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)
|
||||||
|
The docker role is now organized into logical service groups under `roles/docker/tasks/`:
|
||||||
|
|
||||||
|
- **infrastructure/**: Core platform components
|
||||||
|
- Caddy (reverse proxy), Authentik (SSO), Dockge (container management)
|
||||||
|
- **development/**: Development and collaboration tools
|
||||||
|
- Gitea, Code Server
|
||||||
|
- **media/**: Content creation and consumption
|
||||||
|
- 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
|
||||||
|
- **communication/**: Social media and external communication
|
||||||
|
- GoToSocial (Fediverse), Postiz (social media management)
|
||||||
|
- **monitoring/**: System monitoring and alerts
|
||||||
|
- Changedetection, Glance dashboard, AppriseAPI
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
||||||
|
### Template-Driven Configuration
|
||||||
|
The docker role uses Jinja2 templates exclusively for all services. When modifying services:
|
||||||
|
- Update templates in `roles/docker/templates/[service]-compose.yml.j2`
|
||||||
|
- Environment files use `.env.j2` templates where needed
|
||||||
|
- Task files organized by category in `roles/docker/tasks/[category]/[service].yml`
|
||||||
|
- All services now use templated configurations (no static compose files)
|
||||||
|
|
||||||
|
### DNS Management
|
||||||
|
The `dns.yml` playbook manages AWS Route53 records for both domains. All subdomains point to the netcup server (152.53.36.98), with Caddy handling internal routing to the docker host via Tailscale.
|
||||||
|
|
||||||
|
### Security Architecture
|
||||||
|
- Tailscale provides secure networking between management and service hosts
|
||||||
|
- Services are network-isolated using Docker
|
||||||
|
- Caddy handles SSL termination with automatic Let's Encrypt certificates
|
||||||
|
- UFW firewall managed through Docker integration script
|
||||||
|
|
||||||
|
### Service Dependencies
|
||||||
|
Many services depend on Authentik for SSO. When deploying new services, consider:
|
||||||
|
- Whether SSO integration is needed
|
||||||
|
- Caddy routing configuration for subdomain access
|
||||||
|
- Network connectivity requirements within Docker stack
|
||||||
|
- Hairpinning fixes for internal service-to-service communication
|
||||||
|
|
||||||
|
### Hairpinning Resolution
|
||||||
|
Services inside Docker containers cannot reach external domains that resolve to the same server. Fix by adding `extra_hosts` mappings:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
extra_hosts:
|
||||||
|
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||||
|
- "{{ subdomains.cal }}:{{ docker.hairpin_ip }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Common domains requiring hairpinning fixes:
|
||||||
|
- `{{ 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
|
||||||
|
- pingvin 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 }}"
|
||||||
|
```
|
159
README.md
Normal file
159
README.md
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
# Personal Infrastructure Ansible Playbook
|
||||||
|
|
||||||
|
This Ansible playbook automates the setup and management of a personal self-hosted infrastructure running Docker containers for various services.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The playbook manages two main environments:
|
||||||
|
- **Bootstrap server** (`netcup`): Initial server setup with Tailscale VPN
|
||||||
|
- **Docker server** (`docker-01`): Main application server running containerized services
|
||||||
|
|
||||||
|
## Services Deployed
|
||||||
|
|
||||||
|
The Docker role deploys and manages 24 self-hosted services organized into logical categories:
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
- **Caddy** (Reverse proxy with automatic HTTPS)
|
||||||
|
- **Authentik** (SSO/Identity Provider)
|
||||||
|
- **Dockge** (Container management)
|
||||||
|
|
||||||
|
### Development
|
||||||
|
- **Gitea** (Git repository hosting)
|
||||||
|
- **Code Server** (VS Code in browser)
|
||||||
|
|
||||||
|
### Media
|
||||||
|
- **Audiobookshelf** (Audiobook server)
|
||||||
|
- **Calibre** (E-book management)
|
||||||
|
- **Ghost** (Blog platform)
|
||||||
|
- **Pinchflat** (Media downloader)
|
||||||
|
- **Pinry** (Pinterest-like board)
|
||||||
|
- **Hoarder** (Bookmark manager)
|
||||||
|
- **Manyfold** (3D model organizer)
|
||||||
|
|
||||||
|
### Productivity
|
||||||
|
- **Paperless-NGX** (Document management)
|
||||||
|
- **MMDL** (Task management)
|
||||||
|
- **Baikal** (CalDAV/CardDAV server)
|
||||||
|
- **Syncthing** (File synchronization)
|
||||||
|
- **HeyForm** (Form builder)
|
||||||
|
- **Dawarich** (Location tracking)
|
||||||
|
- **Pingvin Share** (File sharing)
|
||||||
|
|
||||||
|
### Communication
|
||||||
|
- **GoToSocial** (Fediverse/Mastodon)
|
||||||
|
- **Postiz** (Social media management)
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
- **Changedetection** (Website change monitoring)
|
||||||
|
- **Glance** (Dashboard)
|
||||||
|
- **AppriseAPI** (Notification service)
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
├── site.yml # Main playbook
|
||||||
|
├── bootstrap.yml # Server bootstrap playbook
|
||||||
|
├── dns.yml # AWS Route53 DNS management
|
||||||
|
├── hosts.yml # Inventory file
|
||||||
|
├── requirements.yml # External role dependencies
|
||||||
|
└── roles/
|
||||||
|
├── bootstrap/ # Initial server setup
|
||||||
|
├── common/ # Common server configuration
|
||||||
|
├── cron/ # Scheduled tasks
|
||||||
|
└── docker/ # Docker services deployment
|
||||||
|
```
|
||||||
|
|
||||||
|
## Roles Documentation
|
||||||
|
|
||||||
|
Each role has detailed documentation in its respective directory:
|
||||||
|
|
||||||
|
### [Bootstrap Role](roles/bootstrap/README.md)
|
||||||
|
Performs initial server setup and hardening:
|
||||||
|
- Creates user accounts with SSH key authentication
|
||||||
|
- Configures passwordless sudo and security hardening
|
||||||
|
- Installs essential packages and configures UFW firewall
|
||||||
|
- Sets up Tailscale VPN for secure network access
|
||||||
|
|
||||||
|
### [Common Role](roles/common/README.md)
|
||||||
|
Provides shared configuration for all servers:
|
||||||
|
- Installs common packages (aptitude)
|
||||||
|
- Enables UFW firewall with default deny policy
|
||||||
|
- Ensures consistent base configuration across infrastructure
|
||||||
|
|
||||||
|
### [Cron Role](roles/cron/README.md)
|
||||||
|
Manages scheduled tasks and automation:
|
||||||
|
- **Warhammer RSS Feed Updater**: Daily job that generates and updates RSS feeds
|
||||||
|
- Integrates with Docker services for content generation
|
||||||
|
- Supports easy addition of new scheduled tasks
|
||||||
|
|
||||||
|
### [Docker Role](roles/docker/README.md)
|
||||||
|
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
|
||||||
|
- **Productivity**: Paperless-NGX, MMDL task management, Baikal calendar
|
||||||
|
- **Communication**: GoToSocial, Postiz social media management
|
||||||
|
- **Monitoring**: Glance dashboard, Changedetection, AppriseAPI notifications
|
||||||
|
- **Template-Driven**: All services use Jinja2 templates for consistent configuration
|
||||||
|
- **Category-Based Deployment**: Deploy services by category using Ansible tags
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
1. Install Ansible and required collections:
|
||||||
|
```bash
|
||||||
|
ansible-galaxy install -r requirements.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Configure your inventory in `hosts.yml` with your server details
|
||||||
|
|
||||||
|
### Bootstrap a New Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook bootstrap.yml -i hosts.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
This will:
|
||||||
|
- Create a user account
|
||||||
|
- Install and configure Tailscale VPN
|
||||||
|
- Set up basic security
|
||||||
|
|
||||||
|
### Deploy Docker Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook site.yml -i hosts.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy specific services using tags:
|
||||||
|
```bash
|
||||||
|
# Deploy by service category
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags infrastructure
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags media,productivity
|
||||||
|
|
||||||
|
# Deploy individual services
|
||||||
|
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 mmdl
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manage DNS Records
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook dns.yml -i hosts.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Updates AWS Route53 DNS records for configured domains (`thesatelliteoflove.com` and `nerder.land`).
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- Service configurations are templated in `roles/docker/templates/`
|
||||||
|
- Environment variables and secrets should be managed through Ansible Vault
|
||||||
|
- Docker Compose files are generated from Jinja2 templates
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- Uses Tailscale for secure network access
|
||||||
|
- Caddy provides automatic HTTPS with Let's Encrypt
|
||||||
|
- Services are containerized for isolation
|
||||||
|
- UFW firewall rules are managed via Docker integration
|
@ -3,11 +3,8 @@
|
|||||||
become: true
|
become: true
|
||||||
vars:
|
vars:
|
||||||
created_username: phil
|
created_username: phil
|
||||||
vars_prompt:
|
|
||||||
- name: tailscale_key
|
|
||||||
prompt: Enter the tailscale key
|
|
||||||
roles:
|
roles:
|
||||||
- bootstrap
|
- bootstrap
|
||||||
- role: artis3n.tailscale
|
- role: artis3n.tailscale
|
||||||
vars:
|
vars:
|
||||||
tailscale_authkey: "{{ tailscale_key }}"
|
tailscale_authkey: "{{ vault_infrastructure.tailscale_key }}"
|
18
dns.yml
18
dns.yml
@ -33,7 +33,21 @@
|
|||||||
ip: "152.53.36.98"
|
ip: "152.53.36.98"
|
||||||
- name: loclog
|
- name: loclog
|
||||||
ip: "152.53.36.98"
|
ip: "152.53.36.98"
|
||||||
- name: habits
|
- name: watcher
|
||||||
|
ip: "152.53.36.98"
|
||||||
|
- name: models
|
||||||
|
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
|
||||||
|
ip: "152.53.36.98"
|
||||||
|
- name: gotify
|
||||||
|
ip: "152.53.36.98"
|
||||||
|
- name: gotify-assistant
|
||||||
ip: "152.53.36.98"
|
ip: "152.53.36.98"
|
||||||
- name: nerder.land
|
- name: nerder.land
|
||||||
dns_records:
|
dns_records:
|
||||||
@ -47,7 +61,7 @@
|
|||||||
amazon.aws.route53:
|
amazon.aws.route53:
|
||||||
state: present
|
state: present
|
||||||
zone: "{{ item.0.name }}"
|
zone: "{{ item.0.name }}"
|
||||||
record: "{{ item.1.name }}.{{ item.0.name }}"
|
record: "{{ item.0.name if item.1.name == '@' else item.1.name + '.' + item.0.name }}"
|
||||||
type: A
|
type: A
|
||||||
ttl: 300
|
ttl: 300
|
||||||
value: "{{ item.1.ip }}"
|
value: "{{ item.1.ip }}"
|
||||||
|
40
group_vars/all/domains.yml
Normal file
40
group_vars/all/domains.yml
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# 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 }}" # Pingvin 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
|
||||||
|
gotify: "gotify.{{ primary_domain }}" # Gotify notifications
|
||||||
|
gotify_assistant: "gotify-assistant.{{ primary_domain }}" # iGotify iOS assistant
|
||||||
|
|
||||||
|
# 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"
|
41
roles/bootstrap/README.md
Normal file
41
roles/bootstrap/README.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Bootstrap Role
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Performs initial server setup and hardening for new Ubuntu/Debian servers.
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
### User Management
|
||||||
|
- Creates a new user account with sudo privileges (specified by `created_username` variable)
|
||||||
|
- Configures passwordless sudo for the sudo group
|
||||||
|
- Sets up SSH key authentication using your local `~/.ssh/id_ed25519.pub` key
|
||||||
|
- Disables root password authentication
|
||||||
|
|
||||||
|
### System Packages
|
||||||
|
- Installs `aptitude` for better package management
|
||||||
|
- Installs essential packages:
|
||||||
|
- `curl` - HTTP client
|
||||||
|
- `vim` - Text editor
|
||||||
|
- `git` - Version control
|
||||||
|
- `ufw` - Uncomplicated Firewall
|
||||||
|
|
||||||
|
### Security Configuration
|
||||||
|
- Configures UFW firewall to:
|
||||||
|
- Allow SSH connections
|
||||||
|
- Enable firewall with default deny policy
|
||||||
|
- Hardens SSH configuration
|
||||||
|
|
||||||
|
## Variables Required
|
||||||
|
- `created_username`: The username to create (typically set in bootstrap.yml)
|
||||||
|
- `tailscale_key`: Tailscale authentication key (prompted during playbook run)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- Requires the `artis3n.tailscale` role for VPN setup
|
||||||
|
- Requires your SSH public key at `~/.ssh/id_ed25519.pub`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
```bash
|
||||||
|
ansible-playbook bootstrap.yml -i hosts.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
This role is designed to be run once on a fresh server before deploying other services.
|
23
roles/common/README.md
Normal file
23
roles/common/README.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Common Role
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Provides shared configuration and security setup that applies to all servers in the infrastructure.
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
### System Packages
|
||||||
|
- Installs `aptitude` for better package management and dependency resolution
|
||||||
|
- Updates package cache to ensure latest package information
|
||||||
|
|
||||||
|
### Security Configuration
|
||||||
|
- Enables UFW (Uncomplicated Firewall) with default deny policy
|
||||||
|
- Provides baseline firewall protection for all managed servers
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
This role is automatically applied to all servers in the infrastructure as part of the main site.yml playbook. It ensures consistent base configuration across all managed systems.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
None - this is a foundational role that other roles can depend on.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
This role is designed to be lightweight and provide only the most essential common functionality. Server-specific configurations should be handled by dedicated roles like `docker` or `bootstrap`.
|
@ -1,6 +1,8 @@
|
|||||||
- name: Install aptitude
|
- name: Install common packages
|
||||||
apt:
|
apt:
|
||||||
name: aptitude
|
name:
|
||||||
|
- aptitude
|
||||||
|
- jq
|
||||||
state: latest
|
state: latest
|
||||||
update_cache: true
|
update_cache: true
|
||||||
|
|
||||||
|
37
roles/cron/README.md
Normal file
37
roles/cron/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Cron Role
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Manages scheduled tasks and automated maintenance jobs for the infrastructure.
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
### Warhammer RSS Feed Updater
|
||||||
|
- Copies `update_warhammer_feed.sh` script to `/usr/local/bin/` with executable permissions
|
||||||
|
- Creates a daily cron job that runs at 09:10 AM
|
||||||
|
- The script performs these actions:
|
||||||
|
1. Creates a temporary directory `/tmp/warhammer_feed`
|
||||||
|
2. Runs a custom Docker container (`git.thesatelliteoflove.com/phil/rss-warhammer`) to generate RSS feed
|
||||||
|
3. Copies the generated `warhammer_rss_feed.xml` to `/opt/stacks/caddy/site/tsol/feeds/`
|
||||||
|
4. Restarts the Glance dashboard stack to reflect the updated feed
|
||||||
|
|
||||||
|
## Files Managed
|
||||||
|
- `/usr/local/bin/update_warhammer_feed.sh` - RSS feed update script
|
||||||
|
- Cron job: "Update Warhammer RSS Feed" (daily at 09:10)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- Requires Docker to be installed and running
|
||||||
|
- Depends on the following Docker stacks being deployed:
|
||||||
|
- Custom RSS generator container at `git.thesatelliteoflove.com/phil/rss-warhammer`
|
||||||
|
- Caddy web server stack at `/opt/stacks/caddy/`
|
||||||
|
- Glance dashboard stack at `/opt/stacks/glance/`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
This role is automatically applied as part of the main site.yml playbook with the `cron` tag.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy only cron jobs
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags cron
|
||||||
|
```
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
To add additional cron jobs, create new tasks in the main.yml file following the same pattern as the Warhammer feed updater.
|
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
|
# Ensure the script is copied to the target machine
|
||||||
- name: Copy the warhammer feed update script
|
- name: Copy the warhammer feed update script
|
||||||
copy:
|
copy:
|
||||||
@ -16,3 +19,97 @@
|
|||||||
hour: "9"
|
hour: "9"
|
||||||
user: root
|
user: root
|
||||||
job: "/usr/local/bin/update_warhammer_feed.sh"
|
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 }}"
|
225
roles/docker/README.md
Normal file
225
roles/docker/README.md
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
# Docker Role
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
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 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
|
||||||
|
|
||||||
|
### Security Features
|
||||||
|
- **Centralized SSO**: Authentik provides OIDC authentication for most services
|
||||||
|
- **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)
|
||||||
|
|
||||||
|
### Infrastructure (`infrastructure/`)
|
||||||
|
- **Caddy** - Reverse proxy with automatic HTTPS (static IP: 172.20.0.5)
|
||||||
|
- **Authentik** - Enterprise authentication server (OIDC/SAML SSO)
|
||||||
|
- **Dockge** - Docker compose stack management UI
|
||||||
|
|
||||||
|
### Development (`development/`)
|
||||||
|
- **Gitea** - Self-hosted Git with CI/CD runners
|
||||||
|
- **Code Server** - VS Code in the browser
|
||||||
|
|
||||||
|
### Media (`media/`)
|
||||||
|
- **Audiobookshelf** - Audiobook and podcast server
|
||||||
|
- **Calibre** - E-book management and conversion
|
||||||
|
- **Ghost** - Modern blogging platform
|
||||||
|
- **Pinchflat** - YouTube video archiving
|
||||||
|
- **Pinry** - Pinterest-like image board
|
||||||
|
- **Karakeep** - Bookmark management with AI tagging
|
||||||
|
- **Manyfold** - 3D model file organization
|
||||||
|
|
||||||
|
### Productivity (`productivity/`)
|
||||||
|
- **Paperless-ngx** - Document management with OCR
|
||||||
|
- **MMDL** - Task and calendar management with CalDAV integration
|
||||||
|
- **Baikal** - CalDAV/CardDAV server
|
||||||
|
- **Syncthing** - Decentralized file sync
|
||||||
|
- **Heyform** - Form builder and surveys
|
||||||
|
- **Dawarich** - Location tracking
|
||||||
|
- **Pingvin Share** - File sharing service
|
||||||
|
|
||||||
|
### Communication (`communication/`)
|
||||||
|
- **GoToSocial** - Lightweight ActivityPub server
|
||||||
|
- **Postiz** - Social media management
|
||||||
|
|
||||||
|
### Monitoring (`monitoring/`)
|
||||||
|
- **Glance** - Customizable dashboard with monitoring
|
||||||
|
- **Change Detection** - Website monitoring
|
||||||
|
- **Apprise API** - Unified notifications
|
||||||
|
|
||||||
|
## Deployment Patterns
|
||||||
|
|
||||||
|
### Standardized Service Deployment
|
||||||
|
Each service follows a consistent pattern:
|
||||||
|
1. Creates `/opt/stacks/[service-name]` directory structure
|
||||||
|
2. Generates Docker Compose file from Jinja2 template
|
||||||
|
3. Deploys using `community.docker.docker_compose_v2`
|
||||||
|
4. Configures environment variables from vault secrets
|
||||||
|
|
||||||
|
### 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 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:
|
||||||
|
- **Zsh Installation**: Sets zsh as default shell
|
||||||
|
- **Atuin**: Command history sync and search
|
||||||
|
- **Bat**: Enhanced `cat` command with syntax highlighting
|
||||||
|
|
||||||
|
## File Organization
|
||||||
|
```
|
||||||
|
roles/docker/
|
||||||
|
├── tasks/
|
||||||
|
│ ├── main.yml # Orchestrates all deployments
|
||||||
|
│ ├── shell.yml # Shell environment setup
|
||||||
|
│ ├── infrastructure/
|
||||||
|
│ │ ├── main.yml # Infrastructure category orchestrator
|
||||||
|
│ │ ├── caddy.yml # Reverse proxy
|
||||||
|
│ │ └── authentik.yml # Authentication
|
||||||
|
│ ├── development/
|
||||||
|
│ │ ├── main.yml # Development category orchestrator
|
||||||
|
│ │ ├── gitea.yml # Git hosting
|
||||||
|
│ │ └── codeserver.yml # VS Code server
|
||||||
|
│ ├── media/ # Media services (7 services)
|
||||||
|
│ ├── productivity/ # Productivity services (7 services)
|
||||||
|
│ ├── communication/ # Communication services (2 services)
|
||||||
|
│ └── monitoring/ # Monitoring services (3 services)
|
||||||
|
├── templates/
|
||||||
|
│ ├── [service]-compose.yml.j2 # Docker Compose templates (all templated)
|
||||||
|
│ ├── [service]-env.j2 # Environment variable templates
|
||||||
|
│ └── [service]-*.j2 # Service-specific templates
|
||||||
|
├── files/
|
||||||
|
│ ├── Caddyfile # Caddy configuration
|
||||||
|
│ ├── ufw-docker.sh # Firewall integration script
|
||||||
|
│ ├── client # Matrix well-known client file
|
||||||
|
│ └── server # Matrix well-known server file
|
||||||
|
└── handlers/
|
||||||
|
└── main.yml # Service restart handlers
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Deploy All Services
|
||||||
|
```bash
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags docker
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy by Service Category
|
||||||
|
```bash
|
||||||
|
# Deploy entire service categories
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags infrastructure
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags development
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags media
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags productivity
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags communication
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags monitoring
|
||||||
|
|
||||||
|
# Deploy multiple categories
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags infrastructure,monitoring
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Individual Services
|
||||||
|
```bash
|
||||||
|
# Deploy specific services
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags authentik
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags gitea,codeserver
|
||||||
|
ansible-playbook site.yml -i hosts.yml --tags mmdl
|
||||||
|
```
|
||||||
|
|
||||||
|
## Service-Specific Notes
|
||||||
|
|
||||||
|
### MMDL (Task Management)
|
||||||
|
- **URL**: https://tasks.thesatelliteoflove.com
|
||||||
|
- **Initial Setup**: Visit `/install` endpoint first to run database migrations
|
||||||
|
- **Authentication**: Integrates with Authentik OIDC provider
|
||||||
|
- **Database**: Uses MySQL 8.0 with automatic schema migration
|
||||||
|
- **Features**: CalDAV integration, multiple account support, task management
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
### System Requirements
|
||||||
|
- Docker CE installed and running
|
||||||
|
- UFW firewall configured
|
||||||
|
- DNS records pointing to the server
|
||||||
|
- Valid SSL certificates (handled automatically by Caddy)
|
||||||
|
|
||||||
|
### External Services
|
||||||
|
- **DNS**: Requires subdomains configured for each service
|
||||||
|
- **Email**: Gitea uses Resend for notifications
|
||||||
|
- **Storage**: All services persist data to `/opt/stacks/[service]/`
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### 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:
|
||||||
|
- `auth.thesatelliteoflove.com` - Authentik
|
||||||
|
- `git.thesatelliteoflove.com` - Gitea
|
||||||
|
- `books.thesatelliteoflove.com` - Calibre
|
||||||
|
- `tasks.thesatelliteoflove.com` - MMDL
|
||||||
|
- (and many more...)
|
||||||
|
|
||||||
|
## Monitoring & Management
|
||||||
|
|
||||||
|
### Glance Dashboard Integration
|
||||||
|
All services include Glance labels for dashboard monitoring:
|
||||||
|
- Service health status
|
||||||
|
- Container resource usage
|
||||||
|
- Parent-child relationships for multi-container services
|
||||||
|
|
||||||
|
### Operational Features
|
||||||
|
- Automatic container restart policies
|
||||||
|
- Health checks for database services
|
||||||
|
- Centralized logging and monitoring
|
||||||
|
- Backup-ready data structure in `/opt/stacks/`
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### Network Security
|
||||||
|
- UFW-Docker integration for proper firewall rules
|
||||||
|
- Services isolated to appropriate network segments
|
||||||
|
- Restricted access for sensitive tools (Stirling PDF)
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
- Centralized SSO through Authentik for most services
|
||||||
|
- OAuth integration where supported
|
||||||
|
- Secure secret management through Ansible vault
|
||||||
|
|
||||||
|
### Container Security
|
||||||
|
- Non-root container execution (UID/GID 1000:1000)
|
||||||
|
- Security options: `no-new-privileges: true`
|
||||||
|
- Capability dropping and minimal permissions
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
- **Database Connection**: Ensure MySQL containers use proper authentication plugins
|
||||||
|
- **OAuth Discovery**: Check issuer URLs don't have trailing slashes
|
||||||
|
- **Migration Failures**: Visit service `/install` endpoints for database setup
|
||||||
|
- **Network Issues**: Verify containers are on the same Docker network
|
@ -32,18 +32,18 @@ loclog.thesatelliteoflove.com {
|
|||||||
reverse_proxy dawarich_app:3000
|
reverse_proxy dawarich_app:3000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watcher.thesatelliteoflove.com {
|
||||||
|
reverse_proxy changedetection:5000
|
||||||
|
}
|
||||||
|
|
||||||
tasks.thesatelliteoflove.com {
|
tasks.thesatelliteoflove.com {
|
||||||
reverse_proxy authentik-server-1:9000
|
reverse_proxy mmdl:3000
|
||||||
}
|
}
|
||||||
|
|
||||||
phlog.thesatelliteoflove.com {
|
phlog.thesatelliteoflove.com {
|
||||||
reverse_proxy ghost-1-ghost-1:2368
|
reverse_proxy ghost-1-ghost-1:2368
|
||||||
}
|
}
|
||||||
|
|
||||||
habits.thesatelliteoflove.com {
|
|
||||||
reverse_proxy beaverhabits:8080
|
|
||||||
}
|
|
||||||
|
|
||||||
code.thesatelliteoflove.com {
|
code.thesatelliteoflove.com {
|
||||||
reverse_proxy authentik-server-1:9000
|
reverse_proxy authentik-server-1:9000
|
||||||
@ -58,10 +58,14 @@ git.thesatelliteoflove.com {
|
|||||||
}
|
}
|
||||||
|
|
||||||
thesatelliteoflove.com {
|
thesatelliteoflove.com {
|
||||||
|
reverse_proxy /micropub/* micropub_server-micropub-1:5000
|
||||||
|
reverse_proxy /micropub micropub_server-micropub-1:5000
|
||||||
root * /srv/tsol
|
root * /srv/tsol
|
||||||
file_server
|
file_server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bookmarks.thesatelliteoflove.com {
|
bookmarks.thesatelliteoflove.com {
|
||||||
reverse_proxy hoarder-web-1:3000
|
reverse_proxy hoarder-web-1:3000
|
||||||
}
|
}
|
||||||
@ -70,33 +74,34 @@ social.thesatelliteoflove.com {
|
|||||||
reverse_proxy gotosocial:8080
|
reverse_proxy gotosocial:8080
|
||||||
}
|
}
|
||||||
|
|
||||||
grist.thesatelliteoflove.com {
|
models.thesatelliteoflove.com {
|
||||||
reverse_proxy grist-grist-1:8484
|
reverse_proxy manyfold-app-1:3214
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
home.thesatelliteoflove.com {
|
home.thesatelliteoflove.com {
|
||||||
reverse_proxy authentik-server-1:9000
|
reverse_proxy authentik-server-1:9000
|
||||||
}
|
}
|
||||||
|
|
||||||
pdftools.thesatelliteoflove.com:80 {
|
gotify.thesatelliteoflove.com {
|
||||||
@allowed {
|
reverse_proxy gotify-gotify-1:80
|
||||||
remote_ip 100.64.0.0/10
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handle @allowed {
|
gotify-assistant.thesatelliteoflove.com {
|
||||||
reverse_proxy stirling-stirlingpdf-1:8080
|
reverse_proxy gotify-igotify-assistant-1:8080
|
||||||
}
|
}
|
||||||
|
|
||||||
handle {
|
|
||||||
respond "Access denied" 403
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repair.nerder.land {
|
repair.nerder.land {
|
||||||
root * /srv/repair
|
root * /srv/repair
|
||||||
file_server
|
file_server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nerder.land {
|
||||||
|
root * /srv/nerderland
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
|
||||||
forms.nerder.land {
|
forms.nerder.land {
|
||||||
reverse_proxy heyform-heyform-1:8000
|
reverse_proxy heyform-heyform-1:8000
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
version: "3"
|
|
||||||
services:
|
|
||||||
tasks.md:
|
|
||||||
image: baldissaramatheus/tasks.md:2.5.4
|
|
||||||
container_name: tasksmd
|
|
||||||
environment:
|
|
||||||
- PUID=1000
|
|
||||||
- PGID=1000
|
|
||||||
volumes:
|
|
||||||
- tasksmd-data:/tasks
|
|
||||||
- tasksmd-config:/config
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
tasksmd-data:
|
|
||||||
driver: local
|
|
||||||
tasksmd-config:
|
|
||||||
driver: local
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
external: true
|
|
||||||
name: lava
|
|
10
roles/docker/tasks/communication/main.yml
Normal file
10
roles/docker/tasks/communication/main.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
# Communication services - Social media, messaging, and external communication
|
||||||
|
|
||||||
|
- name: Install gotosocial
|
||||||
|
import_tasks: gotosocial.yml
|
||||||
|
tags: gotosocial
|
||||||
|
|
||||||
|
- name: Install postiz
|
||||||
|
import_tasks: postiz.yml
|
||||||
|
tags: postiz
|
11
roles/docker/tasks/development/main.yml
Normal file
11
roles/docker/tasks/development/main.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
# Development services - Code, collaboration, and development tools
|
||||||
|
|
||||||
|
- name: Install gitea
|
||||||
|
import_tasks: gitea.yml
|
||||||
|
tags: gitea
|
||||||
|
|
||||||
|
- name: Install codeserver
|
||||||
|
import_tasks: codeserver.yml
|
||||||
|
tags: codeserver
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
- name: make grist directories
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ item}}"
|
|
||||||
state: directory
|
|
||||||
loop:
|
|
||||||
- /opt/stacks/grist
|
|
||||||
|
|
||||||
- name: Template out the compose file
|
|
||||||
ansible.builtin.template:
|
|
||||||
src: grist-compose.yml.j2
|
|
||||||
dest: /opt/stacks/grist/compose.yml
|
|
||||||
owner: root
|
|
||||||
mode: 644
|
|
||||||
|
|
||||||
- name: deploy grist stack
|
|
||||||
community.docker.docker_compose_v2:
|
|
||||||
project_src: /opt/stacks/grist
|
|
||||||
files:
|
|
||||||
- compose.yml
|
|
@ -13,9 +13,9 @@
|
|||||||
mode: 644
|
mode: 644
|
||||||
notify: restart caddy
|
notify: restart caddy
|
||||||
|
|
||||||
- name: copy caddy compose file
|
- name: template caddy compose file
|
||||||
ansible.builtin.copy:
|
ansible.builtin.template:
|
||||||
src: caddy-compose.yml
|
src: caddy-compose.yml.j2
|
||||||
dest: /opt/stacks/caddy/compose.yml
|
dest: /opt/stacks/caddy/compose.yml
|
||||||
owner: root
|
owner: root
|
||||||
mode: 644
|
mode: 644
|
17
roles/docker/tasks/infrastructure/main.yml
Normal file
17
roles/docker/tasks/infrastructure/main.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
# Infrastructure services - Core platform components
|
||||||
|
|
||||||
|
- name: Install caddy
|
||||||
|
import_tasks: caddy.yml
|
||||||
|
tags: caddy
|
||||||
|
|
||||||
|
- name: Install authentik
|
||||||
|
import_tasks: authentik.yml
|
||||||
|
tags: authentik
|
||||||
|
|
||||||
|
- name: Deploy dockge stack
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: /opt/dockge
|
||||||
|
files:
|
||||||
|
- dockge.yml
|
||||||
|
tags: dockge
|
@ -49,103 +49,34 @@
|
|||||||
- /opt/stacks
|
- /opt/stacks
|
||||||
- /opt/dockge
|
- /opt/dockge
|
||||||
|
|
||||||
- name: copy dockge compose file
|
- name: template dockge compose file
|
||||||
ansible.builtin.copy:
|
ansible.builtin.template:
|
||||||
src: dockge-compose.yml
|
src: dockge-compose.yml.j2
|
||||||
dest: /opt/dockge/dockge.yml
|
dest: /opt/dockge/dockge.yml
|
||||||
owner: root
|
owner: root
|
||||||
mode: 644
|
mode: 644
|
||||||
|
|
||||||
- name: deploy dockge stack
|
# Deploy services by category for better organization and dependency management
|
||||||
community.docker.docker_compose_v2:
|
- name: Deploy infrastructure services
|
||||||
project_src: /opt/dockge
|
import_tasks: infrastructure/main.yml
|
||||||
files:
|
tags: infrastructure
|
||||||
- dockge.yml
|
|
||||||
|
|
||||||
- name: Install caddy
|
- name: Deploy development services
|
||||||
import_tasks: caddy.yml
|
import_tasks: development/main.yml
|
||||||
tags: caddy
|
tags: development
|
||||||
|
|
||||||
- name: Install gitea
|
- name: Deploy media services
|
||||||
import_tasks: gitea.yml
|
import_tasks: media/main.yml
|
||||||
tags: gitea
|
tags: media
|
||||||
|
|
||||||
- name: Install hoarder
|
- name: Deploy productivity services
|
||||||
import_tasks: hoarder.yml
|
import_tasks: productivity/main.yml
|
||||||
tags: hoarder
|
tags: productivity
|
||||||
|
|
||||||
- name: Install authentik
|
- name: Deploy monitoring services
|
||||||
import_tasks: authentik.yml
|
import_tasks: monitoring/main.yml
|
||||||
tags: authentik
|
tags: monitoring
|
||||||
|
|
||||||
- name: Install gotosocial
|
- name: Deploy communication services
|
||||||
import_tasks: gotosocial.yml
|
import_tasks: communication/main.yml
|
||||||
tags: gotosocial
|
tags: communication
|
||||||
|
|
||||||
#- name: Install grist
|
|
||||||
# import_tasks: grist.yml
|
|
||||||
# tags: grist
|
|
||||||
|
|
||||||
#- name: Install tasksmd
|
|
||||||
# import_tasks: tasksmd.yml
|
|
||||||
# tags: tasksmd
|
|
||||||
|
|
||||||
- name: Install glance
|
|
||||||
import_tasks: glance.yml
|
|
||||||
tags: glance
|
|
||||||
|
|
||||||
#- name: Install stirlingpdf
|
|
||||||
# import_tasks: stirlingpdf.yml
|
|
||||||
# tags: stirlingpdf
|
|
||||||
|
|
||||||
- name: Install pingvin
|
|
||||||
import_tasks: pingvin.yml
|
|
||||||
tags: pingvin
|
|
||||||
|
|
||||||
- name: Install postiz
|
|
||||||
import_tasks: postiz.yml
|
|
||||||
tags: postiz
|
|
||||||
|
|
||||||
- name: Install pinry
|
|
||||||
import_tasks: pinry.yml
|
|
||||||
tags: pinry
|
|
||||||
|
|
||||||
- name: Install audiobookshelf
|
|
||||||
import_tasks: audiobookshelf.yml
|
|
||||||
tags: audiobookshelf
|
|
||||||
|
|
||||||
- name: Install calibre
|
|
||||||
import_tasks: calibre.yml
|
|
||||||
tags: calibre
|
|
||||||
|
|
||||||
- name: Install paperlessngx
|
|
||||||
import_tasks: paperlessngx.yml
|
|
||||||
tags: paperlessngx
|
|
||||||
|
|
||||||
- name: Install heyform
|
|
||||||
import_tasks: heyform.yml
|
|
||||||
tags: heyform
|
|
||||||
|
|
||||||
- name: Install codeserver
|
|
||||||
import_tasks: codeserver.yml
|
|
||||||
tags: codeserver
|
|
||||||
|
|
||||||
- name: Install baikal
|
|
||||||
import_tasks: baikal.yml
|
|
||||||
tags: baikal
|
|
||||||
|
|
||||||
- name: Install syncthing
|
|
||||||
import_tasks: syncthing.yml
|
|
||||||
tags: syncthing
|
|
||||||
|
|
||||||
- name: Install ghost-1
|
|
||||||
import_tasks: ghost-1.yml
|
|
||||||
tags: ghost-1
|
|
||||||
|
|
||||||
- name: Install dawarich
|
|
||||||
import_tasks: dawarich.yml
|
|
||||||
tags: dawarich
|
|
||||||
|
|
||||||
- name: Install beaver
|
|
||||||
import_tasks: beaver.yml
|
|
||||||
tags: beaver
|
|
@ -5,9 +5,9 @@
|
|||||||
loop:
|
loop:
|
||||||
- /opt/stacks/hoarder
|
- /opt/stacks/hoarder
|
||||||
|
|
||||||
- name: copy hoarder compose file
|
- name: template hoarder compose file
|
||||||
ansible.builtin.copy:
|
ansible.builtin.template:
|
||||||
src: hoarder-compose.yml
|
src: hoarder-compose.yml.j2
|
||||||
dest: /opt/stacks/hoarder/compose.yml
|
dest: /opt/stacks/hoarder/compose.yml
|
||||||
owner: root
|
owner: root
|
||||||
mode: 644
|
mode: 644
|
32
roles/docker/tasks/media/main.yml
Normal file
32
roles/docker/tasks/media/main.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
# Media services - Content creation, management, and consumption
|
||||||
|
|
||||||
|
- name: Install audiobookshelf
|
||||||
|
import_tasks: audiobookshelf.yml
|
||||||
|
tags: audiobookshelf
|
||||||
|
|
||||||
|
- name: Install calibre
|
||||||
|
import_tasks: calibre.yml
|
||||||
|
tags: calibre
|
||||||
|
|
||||||
|
- name: Install ghost-1
|
||||||
|
import_tasks: ghost-1.yml
|
||||||
|
tags: ghost-1
|
||||||
|
|
||||||
|
- name: Install pinchflat
|
||||||
|
import_tasks: pinchflat.yml
|
||||||
|
tags: pinchflat
|
||||||
|
|
||||||
|
- name: Install pinry
|
||||||
|
import_tasks: pinry.yml
|
||||||
|
tags: pinry
|
||||||
|
|
||||||
|
- name: Install karakeep
|
||||||
|
import_tasks: hoarder.yml
|
||||||
|
tags:
|
||||||
|
- hoarder
|
||||||
|
- karakeep
|
||||||
|
|
||||||
|
- name: Install manyfold
|
||||||
|
import_tasks: manyfold.yml
|
||||||
|
tags: manyfold
|
29
roles/docker/tasks/media/manyfold.yml
Normal file
29
roles/docker/tasks/media/manyfold.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
- name: make manyfold directories
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item}}"
|
||||||
|
state: directory
|
||||||
|
loop:
|
||||||
|
- /opt/stacks/manyfold
|
||||||
|
|
||||||
|
- name: make manyfold data directories
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item}}"
|
||||||
|
state: directory
|
||||||
|
owner: 1000
|
||||||
|
group: 1000
|
||||||
|
loop:
|
||||||
|
- /opt/stacks/manyfold/config
|
||||||
|
- /opt/stacks/manyfold/models
|
||||||
|
|
||||||
|
- name: Template out the compose file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: manyfold-compose.yml.j2
|
||||||
|
dest: /opt/stacks/manyfold/compose.yml
|
||||||
|
owner: root
|
||||||
|
mode: 644
|
||||||
|
|
||||||
|
- name: deploy manyfold stack
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: /opt/stacks/manyfold
|
||||||
|
files:
|
||||||
|
- compose.yml
|
@ -1,19 +1,19 @@
|
|||||||
- name: make StirlingPDF directories
|
- name: make pinchflat directories
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ item}}"
|
path: "{{ item}}"
|
||||||
state: directory
|
state: directory
|
||||||
loop:
|
loop:
|
||||||
- /opt/stacks/stirlingpdf
|
- /opt/stacks/pinchflat
|
||||||
|
|
||||||
- name: Template out the compose file
|
- name: Template out the compose file
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: striling-compose.yml.j2
|
src: pinchflat-compose.yml.j2
|
||||||
dest: /opt/stacks/stirling/compose.yml
|
dest: /opt/stacks/pinchflat/compose.yml
|
||||||
owner: root
|
owner: root
|
||||||
mode: 644
|
mode: 644
|
||||||
|
|
||||||
- name: deploy stirling stack
|
- name: deploy pinchflat stack
|
||||||
community.docker.docker_compose_v2:
|
community.docker.docker_compose_v2:
|
||||||
project_src: /opt/stacks/stirling
|
project_src: /opt/stacks/pinchflat
|
||||||
files:
|
files:
|
||||||
- compose.yml
|
- compose.yml
|
@ -1,19 +1,19 @@
|
|||||||
- name: make beaver directories
|
- name: make appriseapi directories
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ item}}"
|
path: "{{ item}}"
|
||||||
state: directory
|
state: directory
|
||||||
loop:
|
loop:
|
||||||
- /opt/stacks/beaver
|
- /opt/stacks/appriseapi
|
||||||
|
|
||||||
- name: Template out the compose file
|
- name: Template out the compose file
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: beaver-compose.yml.j2
|
src: appriseapi-compose.yml.j2
|
||||||
dest: /opt/stacks/beaver/compose.yml
|
dest: /opt/stacks/appriseapi/compose.yml
|
||||||
owner: root
|
owner: root
|
||||||
mode: 644
|
mode: 644
|
||||||
|
|
||||||
- name: deploy beaver stack
|
- name: deploy appriseapi stack
|
||||||
community.docker.docker_compose_v2:
|
community.docker.docker_compose_v2:
|
||||||
project_src: /opt/stacks/beaver
|
project_src: /opt/stacks/appriseapi
|
||||||
files:
|
files:
|
||||||
- compose.yml
|
- compose.yml
|
19
roles/docker/tasks/monitoring/changedetection.yml
Normal file
19
roles/docker/tasks/monitoring/changedetection.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
- name: make changedetection directories
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item}}"
|
||||||
|
state: directory
|
||||||
|
loop:
|
||||||
|
- /opt/stacks/changedetection
|
||||||
|
|
||||||
|
- name: Template out the compose file
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: changedetection-compose.yml.j2
|
||||||
|
dest: /opt/stacks/changedetection/compose.yml
|
||||||
|
owner: root
|
||||||
|
mode: 644
|
||||||
|
|
||||||
|
- name: deploy changedetection stack
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: /opt/stacks/changedetection
|
||||||
|
files:
|
||||||
|
- compose.yml
|
@ -4,6 +4,7 @@
|
|||||||
state: directory
|
state: directory
|
||||||
loop:
|
loop:
|
||||||
- /opt/stacks/glance
|
- /opt/stacks/glance
|
||||||
|
- /opt/stacks/glance/config
|
||||||
|
|
||||||
- name: Template out the compose file
|
- name: Template out the compose file
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
@ -15,7 +16,7 @@
|
|||||||
- name: Template out the config file
|
- name: Template out the config file
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: glance.yml.j2
|
src: glance.yml.j2
|
||||||
dest: /opt/stacks/glance/glance.yml
|
dest: /opt/stacks/glance/config/glance.yml
|
||||||
owner: root
|
owner: root
|
||||||
mode: '0644'
|
mode: '0644'
|
||||||
notify: restart glance
|
notify: restart glance
|
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
|
18
roles/docker/tasks/monitoring/main.yml
Normal file
18
roles/docker/tasks/monitoring/main.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
# Monitoring services - System monitoring, alerts, and dashboards
|
||||||
|
|
||||||
|
- name: Install glance
|
||||||
|
import_tasks: glance.yml
|
||||||
|
tags: glance
|
||||||
|
|
||||||
|
- name: Install changedetection
|
||||||
|
import_tasks: changedetection.yml
|
||||||
|
tags: changedetection
|
||||||
|
|
||||||
|
- name: Install appriseapi
|
||||||
|
import_tasks: appriseapi.yml
|
||||||
|
tags: appriseapi
|
||||||
|
|
||||||
|
- name: Install gotify
|
||||||
|
import_tasks: gotify.yml
|
||||||
|
tags: gotify
|
30
roles/docker/tasks/productivity/main.yml
Normal file
30
roles/docker/tasks/productivity/main.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# Productivity services - Task management, document handling, and personal organization
|
||||||
|
|
||||||
|
- name: Install paperlessngx
|
||||||
|
import_tasks: paperlessngx.yml
|
||||||
|
tags: paperlessngx
|
||||||
|
|
||||||
|
- name: Install baikal
|
||||||
|
import_tasks: baikal.yml
|
||||||
|
tags: baikal
|
||||||
|
|
||||||
|
- name: Install syncthing
|
||||||
|
import_tasks: syncthing.yml
|
||||||
|
tags: syncthing
|
||||||
|
|
||||||
|
- name: Install mmdl
|
||||||
|
import_tasks: mmdl.yml
|
||||||
|
tags: mmdl
|
||||||
|
|
||||||
|
- name: Install heyform
|
||||||
|
import_tasks: heyform.yml
|
||||||
|
tags: heyform
|
||||||
|
|
||||||
|
- name: Install dawarich
|
||||||
|
import_tasks: dawarich.yml
|
||||||
|
tags: dawarich
|
||||||
|
|
||||||
|
- name: Install pingvin
|
||||||
|
import_tasks: pingvin.yml
|
||||||
|
tags: pingvin
|
25
roles/docker/tasks/productivity/mmdl.yml
Normal file
25
roles/docker/tasks/productivity/mmdl.yml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
- 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:
|
||||||
|
project_src: /opt/stacks/mmdl
|
||||||
|
files:
|
||||||
|
- compose.yml
|
@ -1,19 +0,0 @@
|
|||||||
- name: make tasksmd directories
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ item}}"
|
|
||||||
state: directory
|
|
||||||
loop:
|
|
||||||
- /opt/stacks/tasksmd
|
|
||||||
|
|
||||||
- name: copy tasksmd compose file
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: tasksmd-compose.yml
|
|
||||||
dest: /opt/stacks/tasksmd/compose.yml
|
|
||||||
owner: root
|
|
||||||
mode: 644
|
|
||||||
|
|
||||||
- name: deploy tasksmd stack
|
|
||||||
community.docker.docker_compose_v2:
|
|
||||||
project_src: /opt/stacks/tasksmd
|
|
||||||
files:
|
|
||||||
- compose.yml
|
|
30
roles/docker/templates/appriseapi-compose.yml.j2
Normal file
30
roles/docker/templates/appriseapi-compose.yml.j2
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
services:
|
||||||
|
apprise:
|
||||||
|
container_name: apprise
|
||||||
|
ports:
|
||||||
|
- {{ network.docker_host_ip }}:8000:8000
|
||||||
|
environment:
|
||||||
|
- APPRISE_STATEFUL_MODE=simple
|
||||||
|
- APPRISE_WORKER_COUNT=1
|
||||||
|
volumes:
|
||||||
|
- config:/config
|
||||||
|
- 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://{{ subdomains.appriseapi }}/
|
||||||
|
glance.description: Apprise api server
|
||||||
|
glance.id: apprise
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
config:
|
||||||
|
attach:
|
||||||
|
plugin:
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
external: true
|
||||||
|
name: {{ docker.network_name }}
|
@ -8,8 +8,14 @@ services:
|
|||||||
- metadata:/metadata
|
- metadata:/metadata
|
||||||
environment:
|
environment:
|
||||||
- TZ=America/Denver
|
- TZ=America/Denver
|
||||||
|
- DISABLE_SSRF_REQUEST_FILTER=1
|
||||||
extra_hosts:
|
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://{{ subdomains.audio }}/
|
||||||
|
glance.description: Audio book server
|
||||||
volumes:
|
volumes:
|
||||||
audiobooks:
|
audiobooks:
|
||||||
driver: local
|
driver: local
|
||||||
@ -22,4 +28,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -18,6 +18,9 @@ services:
|
|||||||
POSTGRES_DB: ${PG_DB:-authentik}
|
POSTGRES_DB: ${PG_DB:-authentik}
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
labels:
|
||||||
|
glance.parent: authentik
|
||||||
|
glance.name: DB
|
||||||
trout:
|
trout:
|
||||||
image: docker.io/library/redis:alpine
|
image: docker.io/library/redis:alpine
|
||||||
command: --save 60 1 --loglevel warning
|
command: --save 60 1 --loglevel warning
|
||||||
@ -30,8 +33,11 @@ services:
|
|||||||
timeout: 3s
|
timeout: 3s
|
||||||
volumes:
|
volumes:
|
||||||
- trout:/data
|
- trout:/data
|
||||||
|
labels:
|
||||||
|
glance.parent: authentik
|
||||||
|
glance.name: Redis
|
||||||
server:
|
server:
|
||||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.12.0}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.2}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
@ -51,8 +57,14 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- postgresql
|
- postgresql
|
||||||
- trout
|
- trout
|
||||||
|
labels:
|
||||||
|
glance.name: Authentik
|
||||||
|
glance.icon: si:authentik
|
||||||
|
glance.url: https://auth.thesatelliteoflove.com/
|
||||||
|
glance.description: Authentication server
|
||||||
|
glance.id: authentik
|
||||||
worker:
|
worker:
|
||||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.12.0}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.2}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: worker
|
command: worker
|
||||||
environment:
|
environment:
|
||||||
@ -78,6 +90,9 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- postgresql
|
- postgresql
|
||||||
- trout
|
- trout
|
||||||
|
labels:
|
||||||
|
glance.parent: authentik
|
||||||
|
glance.name: Worker
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
database:
|
database:
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
PG_PASS={{ authentik_pg_pass }}
|
PG_PASS={{ vault_authentik.postgres_password }}
|
||||||
AUTHENTIK_SECRET_KEY={{ authentik_secret_key }}
|
AUTHENTIK_SECRET_KEY={{ vault_authentik.secret_key }}
|
||||||
# SMTP Host Emails are sent to
|
# SMTP Host Emails are sent to
|
||||||
AUTHENTIK_EMAIL__HOST=smtp.resend.com
|
AUTHENTIK_EMAIL__HOST={{ smtp.host }}
|
||||||
AUTHENTIK_EMAIL__PORT=25
|
AUTHENTIK_EMAIL__PORT=25
|
||||||
# Optionally authenticate (don't add quotation marks to your password)
|
# Optionally authenticate (don't add quotation marks to your password)
|
||||||
AUTHENTIK_EMAIL__USERNAME=resend
|
AUTHENTIK_EMAIL__USERNAME={{ smtp.username }}
|
||||||
AUTHENTIK_EMAIL__PASSWORD={{ resend_key }}
|
AUTHENTIK_EMAIL__PASSWORD={{ vault_smtp.password }}
|
||||||
# Use StartTLS
|
# Use StartTLS
|
||||||
AUTHENTIK_EMAIL__USE_TLS=true
|
AUTHENTIK_EMAIL__USE_TLS=true
|
||||||
# Use SSL
|
# Use SSL
|
||||||
AUTHENTIK_EMAIL__USE_SSL=false
|
AUTHENTIK_EMAIL__USE_SSL=false
|
||||||
AUTHENTIK_EMAIL__TIMEOUT=10
|
AUTHENTIK_EMAIL__TIMEOUT=10
|
||||||
# Email address authentik will send from, should have a correct @domain
|
# 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,10 +1,15 @@
|
|||||||
services:
|
services:
|
||||||
baikal:
|
baikal:
|
||||||
image: ckulka/baikal:nginx
|
image: ckulka/baikal:0.10.1-nginx
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- config:/var/www/baikal/config
|
- config:/var/www/baikal/config
|
||||||
- data:/var/www/baikal/Specific
|
- data:/var/www/baikal/Specific
|
||||||
|
labels:
|
||||||
|
glance.name: Baikal
|
||||||
|
glance.icon: si:protoncalendar
|
||||||
|
glance.url: https://{{ subdomains.cal }}/
|
||||||
|
glance.description: CalDav server
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
config:
|
config:
|
||||||
@ -13,4 +18,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -1,20 +0,0 @@
|
|||||||
services:
|
|
||||||
beaverhabits:
|
|
||||||
container_name: beaverhabits
|
|
||||||
user: 1000:1000
|
|
||||||
environment:
|
|
||||||
# See the note below to find all the environment variables
|
|
||||||
- HABITS_STORAGE=USER_DISK # DATABASE stores in a single SQLite database named habits.db. USER_DISK option saves in a local json file.
|
|
||||||
- MAX_USER_COUNT=1
|
|
||||||
volumes:
|
|
||||||
- ./data:/app/.user/ # Change directory to match your docker file scheme.
|
|
||||||
restart: unless-stopped
|
|
||||||
image: daya0576/beaverhabits:latest
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
data:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
external: true
|
|
||||||
name: lava
|
|
@ -6,14 +6,21 @@ services:
|
|||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
- "443:443/udp"
|
- "443:443/udp"
|
||||||
|
- "8448:8448"
|
||||||
|
- "8448:8448/udp"
|
||||||
volumes:
|
volumes:
|
||||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||||
- ./site:/srv
|
- ./site:/srv
|
||||||
- caddy_data:/data
|
- caddy_data:/data
|
||||||
- caddy_config:/config
|
- caddy_config:/config
|
||||||
|
labels:
|
||||||
|
glance.name: Caddy
|
||||||
|
glance.icon: si:caddy
|
||||||
|
glance.url: https://{{ primary_domain }}/
|
||||||
|
glance.description: Reverse proxy
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
ipv4_address: 172.20.0.5
|
ipv4_address: {{ docker.hairpin_ip }}
|
||||||
volumes:
|
volumes:
|
||||||
caddy_data:
|
caddy_data:
|
||||||
caddy_config:
|
caddy_config:
|
||||||
@ -21,4 +28,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -13,6 +13,12 @@ services:
|
|||||||
- config:/config
|
- config:/config
|
||||||
- books:/books
|
- books:/books
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
glance.name: Calibre
|
||||||
|
glance.icon: si:calibreweb
|
||||||
|
glance.url: https://{{ subdomains.books }}/
|
||||||
|
glance.description: Book server
|
||||||
|
mag37.dockcheck.update: true
|
||||||
volumes:
|
volumes:
|
||||||
config:
|
config:
|
||||||
driver: local
|
driver: local
|
||||||
@ -21,4 +27,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
137
roles/docker/templates/changedetection-compose.yml.j2
Normal file
137
roles/docker/templates/changedetection-compose.yml.j2
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
version: '3.2'
|
||||||
|
services:
|
||||||
|
changedetection:
|
||||||
|
image: ghcr.io/dgtlmoon/changedetection.io
|
||||||
|
container_name: changedetection
|
||||||
|
hostname: changedetection
|
||||||
|
labels:
|
||||||
|
glance.name: Changedetection
|
||||||
|
glance.icon: si:watchtower
|
||||||
|
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
|
||||||
|
# - ./proxies.json:/datastore/proxies.json
|
||||||
|
|
||||||
|
environment:
|
||||||
|
# Default listening port, can also be changed with the -p option
|
||||||
|
# - PORT=5000
|
||||||
|
#
|
||||||
|
# Log levels are in descending order. (TRACE is the most detailed one)
|
||||||
|
# Log output levels: TRACE, DEBUG(default), INFO, SUCCESS, WARNING, ERROR, CRITICAL
|
||||||
|
# - LOGGER_LEVEL=TRACE
|
||||||
|
#
|
||||||
|
# Alternative WebDriver/selenium URL, do not use "'s or 's!
|
||||||
|
# - WEBDRIVER_URL=http://browser-chrome:4444/wd/hub
|
||||||
|
#
|
||||||
|
# WebDriver proxy settings webdriver_proxyType, webdriver_ftpProxy, webdriver_noProxy,
|
||||||
|
# webdriver_proxyAutoconfigUrl, webdriver_autodetect,
|
||||||
|
# webdriver_socksProxy, webdriver_socksUsername, webdriver_socksVersion, webdriver_socksPassword
|
||||||
|
#
|
||||||
|
# https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.proxy
|
||||||
|
#
|
||||||
|
# Alternative target "Chrome" Playwright URL, do not use "'s or 's!
|
||||||
|
# "Playwright" is a driver/librarythat allows changedetection to talk to a Chrome or similar browser.
|
||||||
|
- PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000
|
||||||
|
#
|
||||||
|
# Playwright proxy settings playwright_proxy_server, playwright_proxy_bypass, playwright_proxy_username, playwright_proxy_password
|
||||||
|
#
|
||||||
|
# https://playwright.dev/python/docs/api/class-browsertype#browser-type-launch-option-proxy
|
||||||
|
#
|
||||||
|
# Plain requests - proxy support example.
|
||||||
|
# - HTTP_PROXY=socks5h://10.10.1.10:1080
|
||||||
|
# - HTTPS_PROXY=socks5h://10.10.1.10:1080
|
||||||
|
#
|
||||||
|
# An exclude list (useful for notification URLs above) can be specified by with
|
||||||
|
# - NO_PROXY="localhost,192.168.0.0/24"
|
||||||
|
#
|
||||||
|
# Base URL of your changedetection.io install (Added to the notification alert)
|
||||||
|
- 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
|
||||||
|
#
|
||||||
|
# Hides the `Referer` header so that monitored websites can't see the changedetection.io hostname.
|
||||||
|
# - HIDE_REFERER=true
|
||||||
|
#
|
||||||
|
# Default number of parallel/concurrent fetchers
|
||||||
|
# - FETCH_WORKERS=10
|
||||||
|
#
|
||||||
|
# Absolute minimum seconds to recheck, overrides any watch minimum, change to 0 to disable
|
||||||
|
# - MINIMUM_SECONDS_RECHECK_TIME=3
|
||||||
|
#
|
||||||
|
# If you want to watch local files file:///path/to/file.txt (careful! security implications!)
|
||||||
|
# - ALLOW_FILE_URI=False
|
||||||
|
#
|
||||||
|
# For complete privacy if you don't want to use the 'check version' / telemetry service
|
||||||
|
# - DISABLE_VERSION_CHECK=true
|
||||||
|
#
|
||||||
|
# A valid timezone name to run as (for scheduling watch checking) see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||||
|
- TZ=America/Denver
|
||||||
|
|
||||||
|
# Comment out ports: when using behind a reverse proxy , enable networks: etc.
|
||||||
|
# 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)
|
||||||
|
# replace image with seleniarm/standalone-chromium:4.0.0-20211213
|
||||||
|
|
||||||
|
# If WEBDRIVER or PLAYWRIGHT are enabled, changedetection container depends on that
|
||||||
|
# and must wait before starting (substitute "browser-chrome" with "playwright-chrome" if last one is used)
|
||||||
|
depends_on:
|
||||||
|
sockpuppetbrowser:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
|
|
||||||
|
# Sockpuppetbrowser is basically chrome wrapped in an API for allowing fast fetching of web-pages.
|
||||||
|
# RECOMMENDED FOR FETCHING PAGES WITH CHROME
|
||||||
|
sockpuppetbrowser:
|
||||||
|
hostname: sockpuppetbrowser
|
||||||
|
labels:
|
||||||
|
glance.parent: changedetection
|
||||||
|
glance.name: Browser
|
||||||
|
mag37.dockcheck.update: true
|
||||||
|
image: dgtlmoon/sockpuppetbrowser:latest
|
||||||
|
cap_add:
|
||||||
|
- SYS_ADMIN
|
||||||
|
## SYS_ADMIN might be too much, but it can be needed on your platform https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-on-gitlabci
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- SCREEN_WIDTH=1920
|
||||||
|
- 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)
|
||||||
|
# Does not report status codes (200, 404, 403) and other issues
|
||||||
|
# browser-chrome:
|
||||||
|
# hostname: browser-chrome
|
||||||
|
# image: selenium/standalone-chrome:4
|
||||||
|
# environment:
|
||||||
|
# - VNC_NO_PASSWORD=1
|
||||||
|
# - SCREEN_WIDTH=1920
|
||||||
|
# - SCREEN_HEIGHT=1080
|
||||||
|
# - SCREEN_DEPTH=24
|
||||||
|
# volumes:
|
||||||
|
# # Workaround to avoid the browser crashing inside a docker container
|
||||||
|
# # See https://github.com/SeleniumHQ/docker-selenium#quick-start
|
||||||
|
# - /dev/shm:/dev/shm
|
||||||
|
# restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
changedetection-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
external: true
|
||||||
|
name: {{ docker.network_name }}
|
@ -2,6 +2,11 @@ services:
|
|||||||
codeserver:
|
codeserver:
|
||||||
stdin_open: true
|
stdin_open: true
|
||||||
tty: true
|
tty: true
|
||||||
|
labels:
|
||||||
|
glance.name: Code Server
|
||||||
|
glance.icon: si:vscodium
|
||||||
|
glance.url: https://{{ subdomains.code }}/
|
||||||
|
glance.description: Code Server
|
||||||
container_name: codeserver
|
container_name: codeserver
|
||||||
volumes:
|
volumes:
|
||||||
- home:/home
|
- home:/home
|
||||||
@ -14,4 +19,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -1,67 +1,76 @@
|
|||||||
services:
|
services:
|
||||||
dawarich_redis:
|
dawarich_redis:
|
||||||
image: redis:7.0-alpine
|
image: redis:7.4-alpine
|
||||||
container_name: dawarich_redis
|
container_name: dawarich_redis
|
||||||
command: redis-server
|
labels:
|
||||||
|
glance.parent: dawarich
|
||||||
|
glance.name: Redis
|
||||||
volumes:
|
volumes:
|
||||||
- dawarich_shared:/data
|
- dawarich_redis_data:/data
|
||||||
restart: always
|
restart: always
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
dawarich_db:
|
dawarich_db:
|
||||||
image: postgres:14.2-alpine
|
image: postgis/postgis:17-3.5-alpine
|
||||||
shm_size: 1G
|
shm_size: 1G
|
||||||
|
labels:
|
||||||
|
glance.parent: dawarich
|
||||||
|
glance.name: DB
|
||||||
container_name: dawarich_db
|
container_name: dawarich_db
|
||||||
volumes:
|
volumes:
|
||||||
- dawarich_db_data:/var/lib/postgresql/data
|
- dawarich_db_data:/var/lib/postgresql/data
|
||||||
- dawarich_shared:/var/shared
|
|
||||||
# - ./postgresql.conf:/etc/postgresql/postgresql.conf # Optional, uncomment if you want to use a custom config
|
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: {{ dawarich_db_password }}
|
POSTGRES_PASSWORD: {{ vault_dawarich.postgres_password }}
|
||||||
|
POSTGRES_DB: dawarich_production
|
||||||
restart: always
|
restart: always
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD-SHELL", "pg_isready -U postgres -d dawarich_development" ]
|
test: [ "CMD", "pg_isready", "-U", "postgres" ]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
# command: postgres -c config_file=/etc/postgresql/postgresql.conf # Use custom config, uncomment if you want to use a custom config
|
|
||||||
dawarich_app:
|
dawarich_app:
|
||||||
image: freikin/dawarich:latest
|
image: freikin/dawarich:0.28.1
|
||||||
container_name: dawarich_app
|
container_name: dawarich_app
|
||||||
|
labels:
|
||||||
|
glance.name: Dawarich
|
||||||
|
glance.icon: si:openstreetmap
|
||||||
|
glance.url: https://{{ subdomains.loclog }}/
|
||||||
|
glance.description: Dawarich
|
||||||
|
glance.id: dawarich
|
||||||
volumes:
|
volumes:
|
||||||
- dawarich_gem_cache_app:/usr/local/bundle/gems
|
|
||||||
- dawarich_public:/var/app/public
|
- dawarich_public:/var/app/public
|
||||||
- dawarich_watched:/var/app/tmp/imports/watched
|
- dawarich_watched:/var/app/tmp/imports/watched
|
||||||
|
- dawarich_storage:/var/app/storage
|
||||||
stdin_open: true
|
stdin_open: true
|
||||||
tty: true
|
tty: true
|
||||||
entrypoint: dev-entrypoint.sh
|
entrypoint: web-entrypoint.sh
|
||||||
command: ['bin/dev']
|
command: ['bin/rails', 'server', '-p', '3000', '-b', '::']
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
environment:
|
environment:
|
||||||
RAILS_ENV: development
|
RAILS_ENV: production
|
||||||
REDIS_URL: redis://dawarich_redis:6379/0
|
|
||||||
DATABASE_HOST: dawarich_db
|
DATABASE_HOST: dawarich_db
|
||||||
|
DATABASE_PORT: 5432
|
||||||
DATABASE_USERNAME: postgres
|
DATABASE_USERNAME: postgres
|
||||||
DATABASE_PASSWORD: {{ dawarich_db_password }}
|
DATABASE_PASSWORD: {{ vault_dawarich.postgres_password }}
|
||||||
DATABASE_NAME: dawarich_development
|
DATABASE_NAME: dawarich_production
|
||||||
|
REDIS_URL: redis://dawarich_redis:6379
|
||||||
MIN_MINUTES_SPENT_IN_CITY: 60
|
MIN_MINUTES_SPENT_IN_CITY: 60
|
||||||
APPLICATION_HOST: "loclog.thesatelliteoflove.com"
|
APPLICATION_HOSTS: {{ subdomains.loclog }},localhost,::1,127.0.0.1
|
||||||
APPLICATION_HOSTS: "loclog.thesatelliteoflove.com, localhost, 127.0.0.1"
|
|
||||||
TIME_ZONE: America/Denver
|
TIME_ZONE: America/Denver
|
||||||
APPLICATION_PROTOCOL: http
|
APPLICATION_PROTOCOL: http
|
||||||
DISTANCE_UNIT: mi
|
DISTANCE_UNIT: mi
|
||||||
PHOTON_API_HOST: photon.komoot.io
|
|
||||||
PHOTON_API_USE_HTTPS: true
|
|
||||||
PROMETHEUS_EXPORTER_ENABLED: false
|
PROMETHEUS_EXPORTER_ENABLED: false
|
||||||
PROMETHEUS_EXPORTER_HOST: 0.0.0.0
|
PROMETHEUS_EXPORTER_HOST: 0.0.0.0
|
||||||
PROMETHEUS_EXPORTER_PORT: 9394
|
PROMETHEUS_EXPORTER_PORT: 9394
|
||||||
ENABLE_TELEMETRY: false # More on telemetry: https://dawarich.app/docs/tutorials/telemetry
|
SECRET_KEY_BASE: {{ vault_dawarich.secret_key_base }}
|
||||||
|
RAILS_LOG_TO_STDOUT: "true"
|
||||||
logging:
|
logging:
|
||||||
driver: "json-file"
|
driver: "json-file"
|
||||||
options:
|
options:
|
||||||
@ -83,74 +92,67 @@ services:
|
|||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
cpus: '0.50' # Limit CPU usage to 50% of one core
|
cpus: '0.50'
|
||||||
memory: '2G' # Limit memory usage to 2GB
|
memory: '2G'
|
||||||
dawarich_sidekiq:
|
dawarich_sidekiq:
|
||||||
image: freikin/dawarich:latest
|
image: freikin/dawarich:0.28.1
|
||||||
container_name: dawarich_sidekiq
|
container_name: dawarich_sidekiq
|
||||||
|
labels:
|
||||||
|
glance.parent: dawarich
|
||||||
|
glance.name: Sidekiq
|
||||||
volumes:
|
volumes:
|
||||||
- dawarich_gem_cache_sidekiq:/usr/local/bundle/gems
|
|
||||||
- dawarich_public:/var/app/public
|
- dawarich_public:/var/app/public
|
||||||
- dawarich_watched:/var/app/tmp/imports/watched
|
- dawarich_watched:/var/app/tmp/imports/watched
|
||||||
|
- dawarich_storage:/var/app/storage
|
||||||
stdin_open: true
|
stdin_open: true
|
||||||
tty: true
|
tty: true
|
||||||
entrypoint: dev-entrypoint.sh
|
entrypoint: sidekiq-entrypoint.sh
|
||||||
command: ['sidekiq']
|
command: ['sidekiq']
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
environment:
|
environment:
|
||||||
RAILS_ENV: development
|
RAILS_ENV: production
|
||||||
REDIS_URL: redis://dawarich_redis:6379/0
|
|
||||||
DATABASE_HOST: dawarich_db
|
DATABASE_HOST: dawarich_db
|
||||||
|
DATABASE_PORT: 5432
|
||||||
DATABASE_USERNAME: postgres
|
DATABASE_USERNAME: postgres
|
||||||
DATABASE_PASSWORD: {{ dawarich_db_password }}
|
DATABASE_PASSWORD: {{ vault_dawarich.postgres_password }}
|
||||||
DATABASE_NAME: dawarich_development
|
DATABASE_NAME: dawarich_production
|
||||||
APPLICATION_HOST: "loclog.thesatelliteoflove.com"
|
REDIS_URL: redis://dawarich_redis:6379
|
||||||
APPLICATION_HOSTS: "loclog.thesatelliteoflove.com, localhost, 127.0.0.1"
|
MIN_MINUTES_SPENT_IN_CITY: 60
|
||||||
BACKGROUND_PROCESSING_CONCURRENCY: 10
|
APPLICATION_HOSTS: {{ subdomains.loclog }},localhost,::1,127.0.0.1
|
||||||
|
TIME_ZONE: America/Denver
|
||||||
APPLICATION_PROTOCOL: http
|
APPLICATION_PROTOCOL: http
|
||||||
DISTANCE_UNIT: mi
|
DISTANCE_UNIT: mi
|
||||||
PHOTON_API_HOST: photon.komoot.io
|
|
||||||
PHOTON_API_USE_HTTPS: true
|
|
||||||
PROMETHEUS_EXPORTER_ENABLED: false
|
PROMETHEUS_EXPORTER_ENABLED: false
|
||||||
PROMETHEUS_EXPORTER_HOST: dawarich_app
|
SECRET_KEY_BASE: {{ vault_dawarich.secret_key_base }}
|
||||||
PROMETHEUS_EXPORTER_PORT: 9394
|
RAILS_LOG_TO_STDOUT: "true"
|
||||||
ENABLE_TELEMETRY: false # More on telemetry: https://dawarich.app/docs/tutorials/telemetry
|
|
||||||
logging:
|
logging:
|
||||||
driver: "json-file"
|
driver: "json-file"
|
||||||
options:
|
options:
|
||||||
max-size: "100m"
|
max-size: "100m"
|
||||||
max-file: "5"
|
max-file: "5"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD-SHELL", "bundle exec sidekiqmon processes | grep $${HOSTNAME}" ]
|
test: ["CMD-SHELL", "ps aux | grep '[s]idekiq' || exit 1"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
retries: 30
|
retries: 30
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
depends_on:
|
depends_on:
|
||||||
|
dawarich_app:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: true
|
||||||
dawarich_db:
|
dawarich_db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
restart: true
|
restart: true
|
||||||
dawarich_redis:
|
dawarich_redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
restart: true
|
restart: true
|
||||||
dawarich_app:
|
|
||||||
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
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
dawarich_db_data:
|
dawarich_db_data:
|
||||||
dawarich_gem_cache_app:
|
dawarich_redis_data:
|
||||||
dawarich_gem_cache_sidekiq:
|
|
||||||
dawarich_shared:
|
|
||||||
dawarich_public:
|
dawarich_public:
|
||||||
dawarich_watched:
|
dawarich_watched:
|
||||||
|
dawarich_storage:
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -2,6 +2,11 @@ services:
|
|||||||
dockge:
|
dockge:
|
||||||
image: louislam/dockge:1
|
image: louislam/dockge:1
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
glance.name: Dockge
|
||||||
|
glance.icon: si:docker
|
||||||
|
glance.url: http://netcup.porgy-porgy.ts.net:5001
|
||||||
|
glance.description: Docker management
|
||||||
ports:
|
ports:
|
||||||
# Host Port : Container Port
|
# Host Port : Container Port
|
||||||
- 5001:5001
|
- 5001:5001
|
@ -7,16 +7,21 @@ services:
|
|||||||
- database__client=sqlite3
|
- database__client=sqlite3
|
||||||
- database__connection__filename=/var/lib/ghost/content/data/ghost.db
|
- database__connection__filename=/var/lib/ghost/content/data/ghost.db
|
||||||
- database__useNullAsDefault=true
|
- database__useNullAsDefault=true
|
||||||
- url=https://phlog.thesatelliteoflove.com
|
- url=https://{{ subdomains.phlog }}
|
||||||
volumes:
|
volumes:
|
||||||
- ghost:/var/lib/ghost/content
|
- ghost:/var/lib/ghost/content
|
||||||
extra_hosts:
|
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://{{ subdomains.phlog }}/
|
||||||
|
glance.description: Photo Blog
|
||||||
|
mag37.dockcheck.update: true
|
||||||
volumes:
|
volumes:
|
||||||
ghost:
|
ghost:
|
||||||
driver: local
|
driver: local
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -7,13 +7,19 @@ services:
|
|||||||
- USER_UID=1000
|
- USER_UID=1000
|
||||||
- USER_GID=1000
|
- USER_GID=1000
|
||||||
- GITEA__mailer__ENABLED=true
|
- GITEA__mailer__ENABLED=true
|
||||||
- GITEA__mailer__FROM=git@updates.thesatelliteoflove.com
|
- GITEA__mailer__FROM=git@{{ email_domains.updates }}
|
||||||
- GITEA__mailer__PROTOCOL=smtps
|
- GITEA__mailer__PROTOCOL=smtps
|
||||||
- GITEA__mailer__SMTP_ADDR=smtp.resend.com
|
- GITEA__mailer__SMTP_ADDR={{ smtp.host }}
|
||||||
- GITEA__mailer__SMTP_PORT=465
|
- GITEA__mailer__SMTP_PORT=465
|
||||||
- GITEA__mailer__USER=resend
|
- GITEA__mailer__USER={{ smtp.username }}
|
||||||
- GITEA__mailer__PASSWD={{ resend_key }}
|
- GITEA__mailer__PASSWD={{ vault_smtp.password }}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
glance.name: Gitea
|
||||||
|
glance.icon: si:gitea
|
||||||
|
glance.url: https://{{ subdomains.git }}/
|
||||||
|
glance.description: Code repo
|
||||||
|
glance.id: gitea
|
||||||
volumes:
|
volumes:
|
||||||
- gitea:/data
|
- gitea:/data
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
@ -21,26 +27,34 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 222:22
|
- 222:22
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||||
|
- '{{ subdomains.git }}:{{ docker.hairpin_ip }}'
|
||||||
runner:
|
runner:
|
||||||
image: gitea/act_runner:nightly
|
image: gitea/act_runner:nightly
|
||||||
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
- server
|
- server
|
||||||
environment:
|
environment:
|
||||||
- CONFIG_FILE=/config.yaml
|
- CONFIG_FILE=/config.yaml
|
||||||
- GITEA_INSTANCE_URL=http://gitea:3000
|
- 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_NAME=runner_1
|
||||||
- GITEA_RUNNER_LABELS=docker
|
- GITEA_RUNNER_LABELS=docker
|
||||||
|
extra_hosts:
|
||||||
|
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||||
|
- '{{ subdomains.git }}:{{ docker.hairpin_ip }}'
|
||||||
|
labels:
|
||||||
|
glance.parent: gitea
|
||||||
|
glance.name: Worker
|
||||||
volumes:
|
volumes:
|
||||||
- ./runner-config.yaml:/config.yaml
|
- ./runner-config.yaml:/config.yaml
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- /opt/stacks/caddy/site:/sites
|
- {{ paths.stacks }}/caddy/site:/sites
|
||||||
volumes:
|
volumes:
|
||||||
gitea:
|
gitea:
|
||||||
driver: local
|
driver: local
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -1,15 +1,23 @@
|
|||||||
services:
|
services:
|
||||||
glance:
|
glance:
|
||||||
image: glanceapp/glance
|
image: glanceapp/glance:latest
|
||||||
volumes:
|
volumes:
|
||||||
- ./glance.yml:/app/glance.yml
|
- ./config:/app/config
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- '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://{{ subdomains.home }}/
|
||||||
|
glance.description: Homepage app
|
||||||
|
glance.id: glance
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -5,14 +5,10 @@ pages:
|
|||||||
widgets:
|
widgets:
|
||||||
- type: calendar
|
- type: calendar
|
||||||
|
|
||||||
- type: twitch-channels
|
- type: server-stats
|
||||||
channels:
|
servers:
|
||||||
- warhammer
|
- type: local
|
||||||
- marcofrisoninjm
|
name: Services
|
||||||
- miniac
|
|
||||||
- next_level_painting
|
|
||||||
- monument_hobbies
|
|
||||||
- visit_the_chronicler
|
|
||||||
|
|
||||||
- size: full
|
- size: full
|
||||||
widgets:
|
widgets:
|
||||||
@ -24,17 +20,21 @@ pages:
|
|||||||
collapse-after: 3
|
collapse-after: 3
|
||||||
cache: 3h
|
cache: 3h
|
||||||
feeds:
|
feeds:
|
||||||
- url: https://hiro.report/rss/
|
|
||||||
- url: https://kill-the-newsletter.com/feeds/ij4twrnzhrwvyic13qcm.xml
|
- url: https://kill-the-newsletter.com/feeds/ij4twrnzhrwvyic13qcm.xml
|
||||||
|
- url: https://mrmoneymustache.ck.page/68f9e9826c
|
||||||
- type: videos
|
- type: rss
|
||||||
channels:
|
title: Gear
|
||||||
- UCR-DXc1voovS8nhAvccRZhg # Jeff Geerling
|
limit: 10
|
||||||
- UCv6J_jJa8GJqFwQNgNrMuww # ServeTheHome
|
collapse-after: 3
|
||||||
- UCOk-gHyjcWZNj3Br4oxwh0A
|
cache: 3h
|
||||||
|
feeds:
|
||||||
- type: reddit
|
- url: https://9to5toys.com/steals/feed
|
||||||
subreddit: selfhosted
|
- 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
|
- size: small
|
||||||
widgets:
|
widgets:
|
||||||
@ -62,6 +62,16 @@ pages:
|
|||||||
name: Trump Media
|
name: Trump Media
|
||||||
- name: Mini Painting
|
- name: Mini Painting
|
||||||
columns:
|
columns:
|
||||||
|
- size: small
|
||||||
|
widgets:
|
||||||
|
- type: twitch-channels
|
||||||
|
channels:
|
||||||
|
- warhammer
|
||||||
|
- marcofrisoninjm
|
||||||
|
- miniac
|
||||||
|
- next_level_painting
|
||||||
|
- monument_hobbies
|
||||||
|
- visit_the_chronicler
|
||||||
- size: full
|
- size: full
|
||||||
widgets:
|
widgets:
|
||||||
- type: rss
|
- type: rss
|
||||||
@ -71,6 +81,8 @@ pages:
|
|||||||
feeds:
|
feeds:
|
||||||
- url: https://thesatelliteoflove.com/feeds/warhammer_rss_feed.xml
|
- url: https://thesatelliteoflove.com/feeds/warhammer_rss_feed.xml
|
||||||
title: Warhammer Community
|
title: Warhammer Community
|
||||||
|
- url: https://yenneferofexeter.wordpress.com/feed/
|
||||||
|
title: Yennefer of Exeter
|
||||||
- name: Self Hosting
|
- name: Self Hosting
|
||||||
columns:
|
columns:
|
||||||
- size: small
|
- size: small
|
||||||
@ -88,12 +100,20 @@ pages:
|
|||||||
- stonith404/pingvin-share
|
- stonith404/pingvin-share
|
||||||
- caddyserver/caddy
|
- caddyserver/caddy
|
||||||
- gitroomhq/postiz-app
|
- gitroomhq/postiz-app
|
||||||
- BaldissaraMatheus/Tasks.md
|
- 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
|
- coder/code-server
|
||||||
|
- dgtlmoon/changedetection.io
|
||||||
|
- Freika/dawarich
|
||||||
|
- manyfold3d/manyfold
|
||||||
|
- caronc/apprise-api
|
||||||
|
- kieraneglin/pinchflat
|
||||||
|
- pinry/pinry
|
||||||
|
- syncthing/syncthing
|
||||||
|
|
||||||
- size: full
|
- size: full
|
||||||
widgets:
|
widgets:
|
||||||
- type: rss
|
- type: rss
|
||||||
|
44
roles/docker/templates/gotify-compose.yml.j2
Normal file
44
roles/docker/templates/gotify-compose.yml.j2
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
services:
|
||||||
|
gotify:
|
||||||
|
image: gotify/server:latest
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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 }}"
|
@ -1,40 +1,49 @@
|
|||||||
services:
|
services:
|
||||||
gotosocial:
|
gotosocial:
|
||||||
image: superseriousbusiness/gotosocial:0.17.3
|
image: docker.io/superseriousbusiness/gotosocial:0.19.1
|
||||||
container_name: gotosocial
|
container_name: gotosocial
|
||||||
user: 1000:1000
|
user: 1000:1000
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||||
environment:
|
environment:
|
||||||
GTS_HOST: social.thesatelliteoflove.com
|
GTS_HOST: {{ subdomains.social }}
|
||||||
GTS_DB_TYPE: sqlite
|
GTS_DB_TYPE: sqlite
|
||||||
GTS_DB_ADDRESS: /gotosocial/storage/sqlite.db
|
GTS_DB_ADDRESS: /gotosocial/storage/sqlite.db
|
||||||
|
GTS_WAZERO_COMPILATION_CACHE: /gotosocial/.cache
|
||||||
GTS_LETSENCRYPT_ENABLED: "false"
|
GTS_LETSENCRYPT_ENABLED: "false"
|
||||||
GTS_LETSENCRYPT_EMAIL_ADDRESS: ""
|
GTS_LETSENCRYPT_EMAIL_ADDRESS: ""
|
||||||
GTS_TRUSTED_PROXIES: "172.20.0.5"
|
GTS_TRUSTED_PROXIES: "{{ docker.hairpin_ip }}"
|
||||||
GTS_ACCOUNT_DOMAIN: thesatelliteoflove.com
|
GTS_ACCOUNT_DOMAIN: {{ primary_domain }}
|
||||||
GTS_OIDC_ENABLED: "true"
|
GTS_OIDC_ENABLED: "true"
|
||||||
GTS_OIDC_IDP_NAME: "Authentik"
|
GTS_OIDC_IDP_NAME: "Authentik"
|
||||||
GTS_OIDC_ISSUER: https://auth.thesatelliteoflove.com/application/o/gotosocial/
|
GTS_OIDC_ISSUER: https://{{ subdomains.auth }}/application/o/gotosocial/
|
||||||
GTS_OIDC_CLIENT_ID: {{ gts_oidc_client_id }}
|
GTS_OIDC_CLIENT_ID: {{ vault_gotosocial.oidc.client_id }}
|
||||||
GTS_OIDC_CLIENT_SECRET: {{ gts_oidc_client_secret }}
|
GTS_OIDC_CLIENT_SECRET: {{ vault_gotosocial.oidc.client_secret }}
|
||||||
GTS_OIDC_LINK_EXISTING: "true"
|
GTS_OIDC_LINK_EXISTING: "true"
|
||||||
GTS_HTTP_CLIENT: "20s"
|
GTS_HTTP_CLIENT: "20s"
|
||||||
GTS_SMTP_HOST: "smtp.resend.com"
|
GTS_SMTP_HOST: "{{ smtp.host }}"
|
||||||
GTS_SMTP_PORT: "587"
|
GTS_SMTP_PORT: "587"
|
||||||
GTS_SMTP_USERNAME: "resend"
|
GTS_SMTP_USERNAME: "{{ smtp.username }}"
|
||||||
GTS_SMTP_PASSWORD: {{ resend_key }}
|
GTS_SMTP_PASSWORD: {{ vault_smtp.password }}
|
||||||
GTS_SMTP_FROM: "social@updates.thesatelliteoflove.com"
|
GTS_SMTP_FROM: "social@{{ email_domains.updates }}"
|
||||||
TZ: UTC
|
TZ: UTC
|
||||||
volumes:
|
volumes:
|
||||||
- gotosocial:/gotosocial/storage
|
- gotosocial:/gotosocial/storage
|
||||||
restart: "always"
|
restart: "always"
|
||||||
labels:
|
labels:
|
||||||
- docker-volume-backup.stop-during-backup=true
|
docker-volume-backup.stop-during-backup: true
|
||||||
|
glance.name: GoToSocial
|
||||||
|
glance.icon: si:mastodon
|
||||||
|
glance.url: https://{{ subdomains.social }}/
|
||||||
|
glance.description: Fediverse server
|
||||||
|
glance.id: gotosocial
|
||||||
|
|
||||||
backup:
|
backup:
|
||||||
image: offen/docker-volume-backup:v2
|
image: offen/docker-volume-backup:v2
|
||||||
restart: always
|
restart: always
|
||||||
|
labels:
|
||||||
|
glance.parent: gotosocial
|
||||||
|
glance.name: Backup
|
||||||
environment:
|
environment:
|
||||||
BACKUP_FILENAME: backup-gts-%Y-%m-%dT%H-%M-%S.tar.gz
|
BACKUP_FILENAME: backup-gts-%Y-%m-%dT%H-%M-%S.tar.gz
|
||||||
BACKUP_LATEST_SYMLINK: backup-latest.tar.gz
|
BACKUP_LATEST_SYMLINK: backup-latest.tar.gz
|
||||||
@ -43,8 +52,8 @@ services:
|
|||||||
BACKUP_RETENTION_DAYS: 1
|
BACKUP_RETENTION_DAYS: 1
|
||||||
AWS_S3_BUCKET_NAME: tsolbackups
|
AWS_S3_BUCKET_NAME: tsolbackups
|
||||||
AWS_ENDPOINT: s3.us-west-004.backblazeb2.com
|
AWS_ENDPOINT: s3.us-west-004.backblazeb2.com
|
||||||
AWS_ACCESS_KEY_ID: {{ backup_key_id }}
|
AWS_ACCESS_KEY_ID: {{ vault_backup.access_key_id }}
|
||||||
AWS_SECRET_ACCESS_KEY: {{ backup_key }}
|
AWS_SECRET_ACCESS_KEY: {{ vault_backup.secret_access_key }}
|
||||||
BACKUP_SKIP_BACKENDS_FROM_PRUNE: s3
|
BACKUP_SKIP_BACKENDS_FROM_PRUNE: s3
|
||||||
|
|
||||||
|
|
||||||
@ -60,4 +69,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -1,23 +0,0 @@
|
|||||||
version: "3.3"
|
|
||||||
services:
|
|
||||||
grist:
|
|
||||||
volumes:
|
|
||||||
- grist:/persist
|
|
||||||
extra_hosts:
|
|
||||||
- 'auth.thesatelliteoflove.com:172.20.0.3'
|
|
||||||
environment:
|
|
||||||
- GRIST_SESSION_SECRET={{ grist_session_secret }}
|
|
||||||
- APP_HOME_URL=https://grist.thesatelliteoflove.com
|
|
||||||
- GRIST_OIDC_IDP_ISSUER=https://auth.thesatelliteoflove.com/application/o/grist/.well-known/openid-configuration
|
|
||||||
- GRIST_OIDC_IDP_CLIENT_ID={{ grist_oidc_client_id }}
|
|
||||||
- GRIST_OIDC_IDP_CLIENT_SECRET={{ grist_oidc_client_secret }}
|
|
||||||
image: gristlabs/grist
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
grist:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
external: true
|
|
||||||
name: lava
|
|
@ -8,23 +8,32 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- mongo
|
- mongo
|
||||||
- keydb
|
- keydb
|
||||||
|
labels:
|
||||||
|
glance.name: Heyform
|
||||||
|
glance.icon: si:googleforms
|
||||||
|
glance.url: https://{{ subdomains.heyform }}/
|
||||||
|
glance.description: Forms server
|
||||||
|
glance.id: heyform
|
||||||
environment:
|
environment:
|
||||||
- APP_HOMEPAGE_URL=http://forms.nerder.land
|
- APP_HOMEPAGE_URL=http://{{ subdomains.heyform }}
|
||||||
- SESSION_KEY={{ heyform_session_key }}
|
- SESSION_KEY={{ vault_heyform.session_key }}
|
||||||
- FORM_ENCRYPTION_KEY={{ heyform_encryption_key }}
|
- FORM_ENCRYPTION_KEY={{ vault_heyform.encryption_key }}
|
||||||
- MONGO_URI='mongodb://mongo:27017/heyform'
|
- MONGO_URI='mongodb://mongo:27017/heyform'
|
||||||
- REDIS_HOST=keydb
|
- REDIS_HOST=keydb
|
||||||
- REDIS_PORT=6379
|
- REDIS_PORT=6379
|
||||||
- SMTP_FROM=nerderland@updates.thesatelliteoflove.com
|
- SMTP_FROM=nerderland@{{ email_domains.updates }}
|
||||||
- SMTP_HOST=smtp.resend.com
|
- SMTP_HOST={{ smtp.host }}
|
||||||
- SMTP_PORT=465
|
- SMTP_PORT=465
|
||||||
- SMTP_USER=resend
|
- SMTP_USER={{ smtp.username }}
|
||||||
- SMTP_PASSWORD={{ resend_key }}
|
- SMTP_PASSWORD={{ vault_smtp.password }}
|
||||||
- SMTP_SECURE=true
|
- SMTP_SECURE=true
|
||||||
|
|
||||||
mongo:
|
mongo:
|
||||||
image: percona/percona-server-mongodb:4.4
|
image: percona/percona-server-mongodb:4.4
|
||||||
restart: always
|
restart: always
|
||||||
|
labels:
|
||||||
|
glance.parent: heyform
|
||||||
|
glance.name: MongoDB
|
||||||
volumes:
|
volumes:
|
||||||
# Persist MongoDB data
|
# Persist MongoDB data
|
||||||
- database:/data/db
|
- database:/data/db
|
||||||
@ -33,6 +42,9 @@ services:
|
|||||||
image: eqalpha/keydb:latest
|
image: eqalpha/keydb:latest
|
||||||
restart: always
|
restart: always
|
||||||
command: keydb-server --appendonly yes
|
command: keydb-server --appendonly yes
|
||||||
|
labels:
|
||||||
|
glance.parent: heyform
|
||||||
|
glance.name: KeyDB
|
||||||
volumes:
|
volumes:
|
||||||
# Persist KeyDB data
|
# Persist KeyDB data
|
||||||
- keydb:/data
|
- keydb:/data
|
||||||
@ -48,4 +60,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -1,7 +1,7 @@
|
|||||||
version: "3.8"
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
web:
|
web:
|
||||||
image: ghcr.io/hoarder-app/hoarder:${HOARDER_VERSION:-release}
|
image: ghcr.io/karakeep-app/karakeep:0.25.0
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- data:/data
|
- data:/data
|
||||||
@ -10,15 +10,24 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||||
- bookmarks.thesatelliteoflove.com:172.20.0.5
|
- '{{ subdomains.bookmarks }}:{{ docker.hairpin_ip }}'
|
||||||
environment:
|
environment:
|
||||||
MEILI_ADDR: http://meilisearch:7700
|
MEILI_ADDR: http://meilisearch:7700
|
||||||
DATA_DIR: /data
|
DATA_DIR: /data
|
||||||
BROWSER_WEB_URL: http://chrome:9222
|
BROWSER_WEB_URL: http://chrome:9222
|
||||||
|
labels:
|
||||||
|
glance.name: Karakeep
|
||||||
|
glance.icon: si:wikibooks
|
||||||
|
glance.url: https://{{ subdomains.bookmarks }}/
|
||||||
|
glance.description: Bookmark manager
|
||||||
|
glance.id: karakeep
|
||||||
chrome:
|
chrome:
|
||||||
image: gcr.io/zenika-hub/alpine-chrome:123
|
image: gcr.io/zenika-hub/alpine-chrome:123
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
glance.name: Chrome
|
||||||
|
glance.parent: karakeep
|
||||||
command:
|
command:
|
||||||
- --no-sandbox
|
- --no-sandbox
|
||||||
- --disable-gpu
|
- --disable-gpu
|
||||||
@ -27,8 +36,11 @@ services:
|
|||||||
- --remote-debugging-port=9222
|
- --remote-debugging-port=9222
|
||||||
- --hide-scrollbars
|
- --hide-scrollbars
|
||||||
meilisearch:
|
meilisearch:
|
||||||
image: getmeili/meilisearch:v1.6
|
image: getmeili/meilisearch:v1.13.3
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
glance.name: Meilisearch
|
||||||
|
glance.parent: karakeep
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
@ -41,4 +53,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -1,10 +1,10 @@
|
|||||||
HOARDER_VERSION=release
|
KARAKEEP_VERSION=release
|
||||||
NEXTAUTH_SECRET={{ hoarder_nextauth_secret }}
|
NEXTAUTH_SECRET={{ vault_hoarder.nextauth_secret }}
|
||||||
MEILI_MASTER_KEY={{ hoarder_meili_master_key }}
|
MEILI_MASTER_KEY={{ vault_hoarder.meili_master_key }}
|
||||||
NEXTAUTH_URL=https://bookmarks.thesatelliteoflove.com
|
NEXTAUTH_URL=https://{{ subdomains.bookmarks }}
|
||||||
OPENAI_API_KEY={{ openai_api_key }}
|
OPENAI_API_KEY={{ vault_infrastructure.openai_api_key }}
|
||||||
OAUTH_CLIENT_SECRET={{ hoarder_oidc_client_secret }}
|
OAUTH_CLIENT_SECRET={{ vault_hoarder.oidc.client_secret }}
|
||||||
OAUTH_CLIENT_ID=GTi0QBRH5TiTqZfxfAkYSQVVFouGdlOFMc2sjivN
|
OAUTH_CLIENT_ID=GTi0QBRH5TiTqZfxfAkYSQVVFouGdlOFMc2sjivN
|
||||||
OAUTH_PROVIDER_NAME=Authentik
|
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
|
OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING=true
|
48
roles/docker/templates/manyfold-compose.yml.j2
Normal file
48
roles/docker/templates/manyfold-compose.yml.j2
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: ghcr.io/manyfold3d/manyfold-solo:latest
|
||||||
|
volumes:
|
||||||
|
# Uncomment to add a volume where a database file should be created.
|
||||||
|
# Don't change the part after the colon, it needs to be at /config
|
||||||
|
- ./config:/config
|
||||||
|
# Uncomment to add a filesystem volume for your model library (or multiple if
|
||||||
|
# you want multiple libraries), in the form <local_path>:<container_path>.
|
||||||
|
# The local path could be a folder that already contains models, in which case Manyfold
|
||||||
|
# will scan and import them, or it could be empty.
|
||||||
|
# The container path can be anything; you will need to enter it in the "new library" form.
|
||||||
|
- ./models:/models
|
||||||
|
environment:
|
||||||
|
SECRET_KEY_BASE: {{ vault_manyfold.secret_key }}
|
||||||
|
MULTIUSER: enabled
|
||||||
|
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: {{ subdomains.models }}
|
||||||
|
MAX_FILE_UPLOAD_SIZE: 5368709120
|
||||||
|
PUID: 1000
|
||||||
|
PGID: 1000
|
||||||
|
extra_hosts:
|
||||||
|
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||||
|
labels:
|
||||||
|
glance.name: Manyfold
|
||||||
|
glance.icon: si:open3d
|
||||||
|
glance.url: https://{{ subdomains.models }}/
|
||||||
|
glance.description: STL Storage
|
||||||
|
mag37.dockcheck.update: true
|
||||||
|
restart: unless-stopped
|
||||||
|
# Optional, but recommended for better security
|
||||||
|
security_opt:
|
||||||
|
- no-new-privileges:true
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
cap_add:
|
||||||
|
- CHOWN
|
||||||
|
- DAC_OVERRIDE
|
||||||
|
- SETUID
|
||||||
|
- SETGID
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
external: true
|
||||||
|
name: "{{ docker.network_name }}"
|
46
roles/docker/templates/mmdl-compose.yml.j2
Normal file
46
roles/docker/templates/mmdl-compose.yml.j2
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
services:
|
||||||
|
mmdl:
|
||||||
|
image: intriin/mmdl:latest
|
||||||
|
container_name: mmdl
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- mmdl_db
|
||||||
|
env_file:
|
||||||
|
- .env.local
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
- "{{ subdomains.auth }}:{{ docker.hairpin_ip }}"
|
||||||
|
- "{{ subdomains.cal }}:{{ docker.hairpin_ip }}"
|
||||||
|
labels:
|
||||||
|
glance.name: MMDL
|
||||||
|
glance.icon: si:task
|
||||||
|
glance.url: https://{{ subdomains.tasks }}/
|
||||||
|
glance.description: Task and calendar management
|
||||||
|
glance.id: mmdl
|
||||||
|
|
||||||
|
mmdl_db:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: mmdl_db
|
||||||
|
restart: unless-stopped
|
||||||
|
command: --default-authentication-plugin=mysql_native_password
|
||||||
|
environment:
|
||||||
|
MYSQL_DATABASE: mmdl
|
||||||
|
MYSQL_USER: mmdl
|
||||||
|
MYSQL_PASSWORD: "{{ vault_mmdl.mysql_password }}"
|
||||||
|
MYSQL_ROOT_PASSWORD: "{{ vault_mmdl.mysql_root_password }}"
|
||||||
|
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
|
||||||
|
MYSQL_ROOT_HOST: "%"
|
||||||
|
volumes:
|
||||||
|
- mmdl_db:/var/lib/mysql
|
||||||
|
labels:
|
||||||
|
glance.parent: mmdl
|
||||||
|
glance.name: DB
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mmdl_db:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
external: true
|
||||||
|
name: {{ docker.network_name }}
|
42
roles/docker/templates/mmdl-env.j2
Normal file
42
roles/docker/templates/mmdl-env.j2
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Database Configuration
|
||||||
|
DB_HOST=mmdl_db
|
||||||
|
DB_USER=mmdl
|
||||||
|
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 }}
|
||||||
|
|
||||||
|
# SMTP Settings
|
||||||
|
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://{{ subdomains.tasks }}
|
||||||
|
NEXTAUTH_SECRET={{ vault_mmdl.nextauth_secret }}
|
||||||
|
|
||||||
|
# Authentik OIDC Configuration
|
||||||
|
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
|
||||||
|
MAX_CONCURRENT_LOGINS=3
|
||||||
|
OTP_VALIDITY_PERIOD=300
|
||||||
|
SESSION_VALIDITY_PERIOD=30
|
||||||
|
|
||||||
|
# Application Settings
|
||||||
|
API_URL=https://{{ subdomains.tasks }}
|
||||||
|
DEBUG_MODE=false
|
||||||
|
TEST_MODE=false
|
||||||
|
NEXT_API_DEBUG_MODE=false
|
||||||
|
SUBTASK_RECURSION_DEPTH=5
|
@ -2,12 +2,21 @@ services:
|
|||||||
broker:
|
broker:
|
||||||
image: docker.io/library/redis:7
|
image: docker.io/library/redis:7
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
glance.parent: paperlessngx
|
||||||
|
glance.name: Redis
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
glance.name: Paperless NGX
|
||||||
|
glance.icon: si:paperlessngx
|
||||||
|
glance.url: https://{{ subdomains.paper }}/
|
||||||
|
glance.description: Document server
|
||||||
|
glance.id: paperlessngx
|
||||||
depends_on:
|
depends_on:
|
||||||
- broker
|
- broker
|
||||||
- gotenberg
|
- gotenberg
|
||||||
@ -19,7 +28,7 @@ services:
|
|||||||
- ./consume:/usr/src/paperless/consume
|
- ./consume:/usr/src/paperless/consume
|
||||||
env_file: docker-compose.env
|
env_file: docker-compose.env
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||||
environment:
|
environment:
|
||||||
PAPERLESS_REDIS: redis://broker:6379
|
PAPERLESS_REDIS: redis://broker:6379
|
||||||
PAPERLESS_TIKA_ENABLED: 1
|
PAPERLESS_TIKA_ENABLED: 1
|
||||||
@ -29,6 +38,9 @@ services:
|
|||||||
|
|
||||||
gotenberg:
|
gotenberg:
|
||||||
image: docker.io/gotenberg/gotenberg:8.7
|
image: docker.io/gotenberg/gotenberg:8.7
|
||||||
|
labels:
|
||||||
|
glance.parent: paperlessngx
|
||||||
|
glance.name: Gotenburg
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
# The gotenberg chromium route is used to convert .eml files. We do not
|
# The gotenberg chromium route is used to convert .eml files. We do not
|
||||||
@ -40,6 +52,9 @@ services:
|
|||||||
|
|
||||||
tika:
|
tika:
|
||||||
image: docker.io/apache/tika:latest
|
image: docker.io/apache/tika:latest
|
||||||
|
labels:
|
||||||
|
glance.parent: paperlessngx
|
||||||
|
glance.name: Tika
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
@ -50,4 +65,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
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
|
# 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)
|
# (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
|
# 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.
|
# 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.
|
# Use this variable to set a timezone for the Paperless Docker containers. If not specified, defaults to UTC.
|
||||||
PAPERLESS_TIME_ZONE=America/Denver
|
PAPERLESS_TIME_ZONE=America/Denver
|
||||||
@ -43,4 +43,4 @@ PAPERLESS_TIME_ZONE=America/Denver
|
|||||||
|
|
||||||
# authentik
|
# authentik
|
||||||
PAPERLESS_APPS: "allauth.socialaccount.providers.openid_connect"
|
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"}}]}}'
|
22
roles/docker/templates/pinchflat-compose.yml.j2
Normal file
22
roles/docker/templates/pinchflat-compose.yml.j2
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
services:
|
||||||
|
pinchflat:
|
||||||
|
environment:
|
||||||
|
- TZ=America/Denver
|
||||||
|
ports:
|
||||||
|
- 100.70.169.99:8945:8945
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
- data:/downloads
|
||||||
|
image: ghcr.io/kieraneglin/pinchflat:latest
|
||||||
|
labels:
|
||||||
|
glance.name: Pinchflat
|
||||||
|
glance.icon: si:youtube
|
||||||
|
glance.url: http://netcup.porgy-porgy.ts.net:8945
|
||||||
|
glance.description: Youtube interface
|
||||||
|
glance.id: pinchflat
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
external: true
|
||||||
|
name: lava
|
@ -5,7 +5,13 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- TRUST_PROXY=true
|
- TRUST_PROXY=true
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- 'auth.thesatelliteoflove.com:172.20.0.5'
|
- '{{ subdomains.auth }}:{{ docker.hairpin_ip }}'
|
||||||
|
labels:
|
||||||
|
glance.name: Pingvin
|
||||||
|
glance.icon: si:files
|
||||||
|
glance.url: https://{{ subdomains.files }}
|
||||||
|
glance.description: File sharing service
|
||||||
|
glance.id: pingvin
|
||||||
volumes:
|
volumes:
|
||||||
- data:/opt/app/backend/data
|
- data:/opt/app/backend/data
|
||||||
- images:/opt/app/frontend/public/img
|
- images:/opt/app/frontend/public/img
|
||||||
@ -15,4 +21,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -2,6 +2,12 @@ services:
|
|||||||
pinry:
|
pinry:
|
||||||
volumes:
|
volumes:
|
||||||
- pinry:/data
|
- pinry:/data
|
||||||
|
labels:
|
||||||
|
glance.name: Pinry
|
||||||
|
glance.icon: si:pinterest
|
||||||
|
glance.url: https://{{ subdomains.pin }}
|
||||||
|
glance.description: Pinterest clone
|
||||||
|
glance.id: pinterest
|
||||||
environment:
|
environment:
|
||||||
- SECRET_KEY=no2254XiwYFWDnt2UW6wraSbVPRdHx8wVIeBh3jeYcI=
|
- SECRET_KEY=no2254XiwYFWDnt2UW6wraSbVPRdHx8wVIeBh3jeYcI=
|
||||||
- ALLOW_NEW_REGISTRATIONS=False
|
- ALLOW_NEW_REGISTRATIONS=False
|
||||||
@ -12,4 +18,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -5,9 +5,9 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
# You must change these. Replace `postiz.your-server.com` with your DNS name - what your web browser sees.
|
# You must change these. Replace `postiz.your-server.com` with your DNS name - what your web browser sees.
|
||||||
MAIN_URL: "https://post.thesatelliteoflove.com"
|
MAIN_URL: "https://{{ subdomains.post }}"
|
||||||
FRONTEND_URL: "https://post.thesatelliteoflove.com"
|
FRONTEND_URL: "https://{{ subdomains.post }}"
|
||||||
NEXT_PUBLIC_BACKEND_URL: "https://post.thesatelliteoflove.com/api"
|
NEXT_PUBLIC_BACKEND_URL: "https://{{ subdomains.post }}/api"
|
||||||
JWT_SECRET: "TShr6Fdcwf67wIhuUvg0gOsJbdcQmgMiJl5kUh6JCfY="
|
JWT_SECRET: "TShr6Fdcwf67wIhuUvg0gOsJbdcQmgMiJl5kUh6JCfY="
|
||||||
|
|
||||||
# These defaults are probably fine, but if you change your user/password, update it in the
|
# These defaults are probably fine, but if you change your user/password, update it in the
|
||||||
@ -24,7 +24,7 @@ services:
|
|||||||
|
|
||||||
# Social keys
|
# Social keys
|
||||||
LINKEDIN_CLIENT_ID: "86q7ksc8q5pai3"
|
LINKEDIN_CLIENT_ID: "86q7ksc8q5pai3"
|
||||||
LINKEDIN_CLIENT_SECRET: {{ linkedin_secret }}
|
LINKEDIN_CLIENT_SECRET: {{ vault_postiz.linkedin_secret }}
|
||||||
volumes:
|
volumes:
|
||||||
- postiz-config:/config/
|
- postiz-config:/config/
|
||||||
- postiz-uploads:/uploads/
|
- postiz-uploads:/uploads/
|
||||||
@ -33,6 +33,11 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
postiz-redis:
|
postiz-redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
labels:
|
||||||
|
glance.name: Postiz
|
||||||
|
glance.url: https://{{ subdomains.post }}/
|
||||||
|
glance.description: Social media scheduler
|
||||||
|
glance.id: postiz
|
||||||
|
|
||||||
postiz-postgres:
|
postiz-postgres:
|
||||||
image: postgres:14.5
|
image: postgres:14.5
|
||||||
@ -49,6 +54,9 @@ services:
|
|||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
labels:
|
||||||
|
glance.parent: postiz
|
||||||
|
glance.name: DB
|
||||||
postiz-redis:
|
postiz-redis:
|
||||||
image: redis:7.2
|
image: redis:7.2
|
||||||
container_name: postiz-redis
|
container_name: postiz-redis
|
||||||
@ -60,6 +68,9 @@ services:
|
|||||||
retries: 3
|
retries: 3
|
||||||
volumes:
|
volumes:
|
||||||
- postiz-redis-data:/data
|
- postiz-redis-data:/data
|
||||||
|
labels:
|
||||||
|
glance.parent: postiz
|
||||||
|
glance.name: Redis
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -79,4 +90,4 @@ volumes:
|
|||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external: true
|
external: true
|
||||||
name: lava
|
name: {{ docker.network_name }}
|
@ -1,18 +0,0 @@
|
|||||||
version: '3.3'
|
|
||||||
services:
|
|
||||||
stirlingpdf:
|
|
||||||
image: frooodle/s-pdf:latest
|
|
||||||
volumes:
|
|
||||||
- ./trainingData:/usr/share/tessdata #Required for extra OCR languages
|
|
||||||
- ./extraConfigs:/configs
|
|
||||||
# - ./customFiles:/customFiles/
|
|
||||||
# - ./logs:/logs/
|
|
||||||
environment:
|
|
||||||
- DOCKER_ENABLE_SECURITY=false
|
|
||||||
- INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false
|
|
||||||
- LANGS=en_GB
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
external: true
|
|
||||||
name: lava
|
|
@ -3,6 +3,12 @@ services:
|
|||||||
image: syncthing/syncthing
|
image: syncthing/syncthing
|
||||||
container_name: syncthing
|
container_name: syncthing
|
||||||
hostname: my-syncthing
|
hostname: my-syncthing
|
||||||
|
labels:
|
||||||
|
glance.name: Syncthing
|
||||||
|
glance.icon: si:syncthing
|
||||||
|
glance.url: https://netcup.porgy-porgy.ts.net:8384
|
||||||
|
glance.description: Syncthing core
|
||||||
|
glance.id: Syncthing
|
||||||
environment:
|
environment:
|
||||||
- PUID=1000
|
- PUID=1000
|
||||||
- PGID=1000
|
- PGID=1000
|
||||||
|
141
todo.md
Normal file
141
todo.md
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# Infrastructure Improvements TODO
|
||||||
|
|
||||||
|
## High Priority (Quick Wins)
|
||||||
|
|
||||||
|
### 1. Split the massive docker role ✅ COMPLETED
|
||||||
|
- **Current Issue**: `roles/docker/tasks/main.yml` has 20+ services in one file (176 lines)
|
||||||
|
- **Solution**: Break into logical service groups:
|
||||||
|
```
|
||||||
|
roles/docker/tasks/
|
||||||
|
├── main.yml (orchestrator)
|
||||||
|
├── infrastructure/ (caddy, authentik, dockge)
|
||||||
|
├── development/ (gitea, codeserver)
|
||||||
|
├── media/ (audiobookshelf, calibre, ghost, pinchflat, pinry, hoarder, manyfold)
|
||||||
|
├── productivity/ (paperless, baikal, syncthing, mmdl, heyform, dawarich, pingvin)
|
||||||
|
├── communication/ (gotosocial, postiz)
|
||||||
|
└── monitoring/ (glance, changedetection, appriseapi)
|
||||||
|
```
|
||||||
|
- **COMPLETED**: All services organized into logical categories with category-level tags
|
||||||
|
|
||||||
|
### 2. Standardize variable management ✅ COMPLETED
|
||||||
|
- **Current Issue**: Secrets in single encrypted file, no clear variable hierarchy
|
||||||
|
- **Solution**: Create proper variable structure:
|
||||||
|
```
|
||||||
|
group_vars/
|
||||||
|
├── all/
|
||||||
|
│ ├── 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
|
||||||
|
- **Solution**: Create reusable template includes with standard service template structure
|
||||||
|
- **COMPLETED**: Converted all static compose files (caddy, dockge, hoarder) to Jinja2 templates
|
||||||
|
- **REMAINING**: Create reusable template patterns for common configurations
|
||||||
|
|
||||||
|
## Security & Reliability
|
||||||
|
|
||||||
|
### 4. Add health checks
|
||||||
|
- **Issue**: Most services lack proper healthcheck configurations in compose templates
|
||||||
|
- **Solution**: Implement comprehensive health monitoring with standardized healthcheck patterns
|
||||||
|
|
||||||
|
### 5. Implement backup strategy
|
||||||
|
- **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
|
||||||
|
- Rotation policies
|
||||||
|
- Restoration testing
|
||||||
|
|
||||||
|
### 6. Network segmentation
|
||||||
|
- **Issue**: All services share one Docker network
|
||||||
|
- **Solution**: Separate into:
|
||||||
|
- `frontend` (Public-facing services)
|
||||||
|
- `backend` (Internal services only)
|
||||||
|
- `database` (Database access only)
|
||||||
|
|
||||||
|
### 7. Security hardening
|
||||||
|
- Remove unnecessary `user: root` from services
|
||||||
|
- Add security contexts to all containers
|
||||||
|
- Implement least-privilege access patterns
|
||||||
|
- Add fail2ban for authentication services
|
||||||
|
|
||||||
|
## Automation Opportunities
|
||||||
|
|
||||||
|
### 8. CI/CD with Gitea Actions
|
||||||
|
- Leverage self-hosted Gitea for:
|
||||||
|
- Ansible syntax validation
|
||||||
|
- Service configuration testing
|
||||||
|
- Automated deployment triggers
|
||||||
|
- Rollback capabilities
|
||||||
|
|
||||||
|
### 9. Configuration drift detection
|
||||||
|
- Add validation tasks to catch manual changes
|
||||||
|
- Implement configuration validation with proper assertions
|
||||||
|
|
||||||
|
### 10. Service dependency management
|
||||||
|
- **Issue**: Some services depend on Authentik SSO but no startup ordering
|
||||||
|
- **Solution**: Implement dependency checking and startup ordering
|
||||||
|
|
||||||
|
### 11. Ansible best practices
|
||||||
|
- Replace deprecated `apt_key` with proper patterns
|
||||||
|
- Use `ansible.builtin` FQCN consistently
|
||||||
|
- Add `check_mode` support
|
||||||
|
- Implement proper idempotency checks
|
||||||
|
|
||||||
|
### 12. Documentation automation
|
||||||
|
- Auto-generate service inventory
|
||||||
|
- Create service documentation templates
|
||||||
|
- Implement automated documentation updates
|
||||||
|
|
||||||
|
## Implementation Roadmap
|
||||||
|
|
||||||
|
### Week 1: Foundation
|
||||||
|
- [x] Document improvements in todo.md
|
||||||
|
- [x] Reorganize docker role structure
|
||||||
|
- [x] Convert static compose files to templates
|
||||||
|
- [x] Remove unused services (beaver, grist, stirlingpdf, tasksmd, redlib)
|
||||||
|
- [x] Clean up templates and files directories
|
||||||
|
- [x] Implement variable hierarchy
|
||||||
|
- [ ] Create reusable template patterns
|
||||||
|
|
||||||
|
### Week 2: Security & Monitoring
|
||||||
|
- [ ] Add health checks
|
||||||
|
- [ ] Implement backup strategy
|
||||||
|
- [ ] Security hardening
|
||||||
|
|
||||||
|
### Week 3: Automation
|
||||||
|
- [ ] CI/CD pipeline setup
|
||||||
|
- [ ] Configuration validation
|
||||||
|
- [ ] Documentation automation
|
||||||
|
|
||||||
|
### Week 4: Advanced Features
|
||||||
|
- [ ] Network segmentation
|
||||||
|
- [ ] Dependency management
|
||||||
|
- [ ] Monitoring dashboard
|
||||||
|
|
||||||
|
## Completed Work Summary
|
||||||
|
|
||||||
|
### ✅ Major Accomplishments
|
||||||
|
- **Docker Role Reorganization**: Split monolithic 176-line main.yml into 6 logical service categories
|
||||||
|
- **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.)
|
||||||
|
- **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
|
||||||
|
- **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
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
- Current architecture is solid and much better organized for long-term maintainability
|
||||||
|
- Focus on high-impact, low-effort improvements first
|
||||||
|
- Leverage existing infrastructure (Gitea, Authentik) for automation
|
||||||
|
- Template-driven approach enables future dynamic configuration
|
Reference in New Issue
Block a user