From fd48fed9d8dde3c88f17b0ee5806b29325d4b7ea Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Nov 2025 19:12:04 +0000 Subject: [PATCH] feat: Complete homelab GitOps setup with SSO and SSL Core Infrastructure: - Add LLDAP for centralized user authentication (lldap.fig.systems) - Configure Tinyauth with LLDAP backend for SSO (auth.fig.systems) - Set up Traefik v3.3 with Let's Encrypt SSL automation - Create homelab Docker network for service isolation Media Services: - Configure Jellyfin with /media folder mappings (flix.fig.systems) - Add Jellyseerr for media requests (requests.fig.systems) - Update Immich with photo library access (photos.fig.systems) - Set up Sonarr for TV automation (sonarr.fig.systems) - Set up Radarr for movie automation (radarr.fig.systems) - Configure SABnzbd for Usenet downloads (sabnzbd.fig.systems) - Add qBittorrent for torrent downloads (qbt.fig.systems) Utility Services: - Update Linkwarden with proper networking (links.fig.systems) - Configure Vikunja task management (tasks.fig.systems) - Set up LubeLogger vehicle tracking (garage.fig.systems) - Configure Calibre-web for ebooks (books.fig.systems) - Add Booklore for book tracking (booklore.fig.systems) - Update FreshRSS reader (rss.fig.systems) - Update RSSHub with internal networking (rsshub.fig.systems) - Update MicroBin pastebin (paste.fig.systems) - Add File Browser for media access (files.fig.systems) Technical Improvements: - Standardize all compose files to compose.yaml (Docker best practice) - Add Traefik labels to all services for SSL termination - Implement proper network isolation (homelab + service-specific networks) - Add health checks to database services - Configure dual domain support (fig.systems + edfig.dev) - Set proper /media folder mappings for all media services - Add comprehensive README with deployment instructions Security: - Enable SSO via Tinyauth for most services - Configure LLDAP with admin user (edfig/admin@edfig.dev) - Services with built-in auth have SSO disabled by default - All traffic secured with automatic Let's Encrypt certificates --- README.md | 219 +++++++++++++++++- compose/core/lldap/.env | 25 ++ compose/core/lldap/compose.yaml | 24 ++ compose/core/tinyauth/.env | 32 ++- compose/core/tinyauth/compose.yaml | 66 ++---- compose/core/traefik/compose.yaml | 46 ++++ .../media/automation/qbittorrent/compose.yaml | 34 +++ compose/media/automation/radarr/compose.yaml | 33 +++ compose/media/automation/radarr/compose.yml | 11 - compose/media/automation/sabnzbd/compose.yaml | 30 +++ compose/media/automation/sabnzbd/compose.yml | 11 - compose/media/automation/sonarr/compose.yaml | 33 +++ compose/media/automation/sonarr/compose.yml | 11 - .../{docker-compose.yml => compose.yaml} | 28 +++ compose/media/frontend/immich/compose.yml | 11 - compose/media/frontend/jellyfin/compose.yaml | 84 ++++--- compose/media/frontend/jellyseer/compose.yaml | 28 +++ compose/media/frontend/jellyseer/compose.yml | 14 -- compose/services/FreshRSS/compose.yaml | 27 +++ compose/services/FreshRSS/compose.yml | 14 -- compose/services/booklore/compose.yaml | 28 +++ compose/services/calibre-web/compose.yaml | 30 +++ compose/services/calibre-web/compose.yml | 19 -- compose/services/filebrowser/compose.yaml | 29 +++ compose/services/filebrowser/compose.yml | 11 - compose/services/linkwarden/compose.yaml | 73 ++++-- compose/services/lubelogger/compose.yaml | 30 +++ compose/services/lubelogger/compose.yml | 15 -- compose/services/microbin/compose.yaml | 26 ++- compose/services/rsshub/compose.yaml | 95 ++++---- compose/services/vikunja/compose.yaml | 58 +++++ compose/services/vikunja/compose.yml | 32 --- 32 files changed, 921 insertions(+), 306 deletions(-) create mode 100644 compose/core/lldap/.env create mode 100644 compose/core/lldap/compose.yaml create mode 100644 compose/core/traefik/compose.yaml create mode 100644 compose/media/automation/qbittorrent/compose.yaml create mode 100644 compose/media/automation/radarr/compose.yaml delete mode 100644 compose/media/automation/radarr/compose.yml create mode 100644 compose/media/automation/sabnzbd/compose.yaml delete mode 100644 compose/media/automation/sabnzbd/compose.yml create mode 100644 compose/media/automation/sonarr/compose.yaml delete mode 100644 compose/media/automation/sonarr/compose.yml rename compose/media/frontend/immich/{docker-compose.yml => compose.yaml} (75%) delete mode 100644 compose/media/frontend/immich/compose.yml create mode 100644 compose/media/frontend/jellyseer/compose.yaml delete mode 100644 compose/media/frontend/jellyseer/compose.yml create mode 100644 compose/services/FreshRSS/compose.yaml delete mode 100644 compose/services/FreshRSS/compose.yml create mode 100644 compose/services/booklore/compose.yaml create mode 100644 compose/services/calibre-web/compose.yaml delete mode 100644 compose/services/calibre-web/compose.yml create mode 100644 compose/services/filebrowser/compose.yaml delete mode 100644 compose/services/filebrowser/compose.yml create mode 100644 compose/services/lubelogger/compose.yaml delete mode 100644 compose/services/lubelogger/compose.yml create mode 100644 compose/services/vikunja/compose.yaml delete mode 100644 compose/services/vikunja/compose.yml diff --git a/README.md b/README.md index 50ee4f4..6db6978 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,218 @@ -# Homelab - Containers +# Homelab GitOps Configuration -This repo contains container related items for deployment in my homelab +This repository contains Docker Compose configurations for self-hosted home services. + +## 🏗️ Infrastructure + +### Core Services (Port 80/443) +- **Traefik** - Reverse proxy with automatic Let's Encrypt SSL +- **LLDAP** - Lightweight LDAP server for user management + - Admin: `edfig` (admin@edfig.dev) + - Web UI: https://lldap.fig.systems +- **Tinyauth** - SSO authentication via Traefik forward auth + - Connected to LLDAP for user authentication + - Web UI: https://auth.fig.systems + +## 📁 Directory Structure + +``` +compose/ +├── core/ # Infrastructure services +│ ├── traefik/ # Reverse proxy & SSL +│ ├── lldap/ # LDAP user directory +│ └── tinyauth/ # SSO authentication +├── media/ # Media services +│ ├── frontend/ # Media frontends +│ │ ├── jellyfin/ # Media server (flix.fig.systems) +│ │ ├── jellyseer/ # Request management (requests.fig.systems) +│ │ └── immich/ # Photo management (photos.fig.systems) +│ └── automation/ # Media automation +│ ├── sonarr/ # TV show management +│ ├── radarr/ # Movie management +│ ├── sabnzbd/ # Usenet downloader +│ └── qbittorrent/# Torrent client +└── services/ # Utility services + ├── linkwarden/ # Bookmark manager (links.fig.systems) + ├── vikunja/ # Task management (tasks.fig.systems) + ├── lubelogger/ # Vehicle tracker (garage.fig.systems) + ├── calibre-web/ # Ebook library (books.fig.systems) + ├── booklore/ # Book tracking (booklore.fig.systems) + ├── FreshRSS/ # RSS reader (rss.fig.systems) + ├── rsshub/ # RSS feed generator (rsshub.fig.systems) + ├── microbin/ # Pastebin (paste.fig.systems) + └── filebrowser/ # File manager (files.fig.systems) +``` + +## 🌐 Domains + +All services are accessible via: +- Primary: `*.fig.systems` +- Secondary: `*.edfig.dev` + +### Service URLs + +| Service | URL | SSO Protected | +|---------|-----|---------------| +| Traefik Dashboard | traefik.fig.systems | ✅ | +| LLDAP | lldap.fig.systems | ✅ | +| Tinyauth | auth.fig.systems | ❌ | +| Jellyfin | flix.fig.systems | ❌* | +| Jellyseerr | requests.fig.systems | ✅ | +| Immich | photos.fig.systems | ❌* | +| Sonarr | sonarr.fig.systems | ✅ | +| Radarr | radarr.fig.systems | ✅ | +| SABnzbd | sabnzbd.fig.systems | ✅ | +| qBittorrent | qbt.fig.systems | ✅ | +| Linkwarden | links.fig.systems | ✅ | +| Vikunja | tasks.fig.systems | ✅ | +| LubeLogger | garage.fig.systems | ✅ | +| Calibre-web | books.fig.systems | ✅ | +| Booklore | booklore.fig.systems | ✅ | +| FreshRSS | rss.fig.systems | ✅ | +| RSSHub | rsshub.fig.systems | ❌* | +| MicroBin | paste.fig.systems | ❌* | +| File Browser | files.fig.systems | ✅ | + +*Services marked with ❌* have their own authentication systems + +## 📦 Media Folder Structure + +The VM should have `/media` mounted at the root with this structure: + +``` +/media/ +├── audiobooks/ +├── books/ +├── comics/ +├── complete/ # Completed downloads +├── downloads/ # Active downloads +├── homemovies/ +├── incomplete/ # Incomplete downloads +├── movies/ +├── music/ +├── photos/ +└── tv/ +``` + +## 🚀 Deployment + +### Prerequisites + +1. **DNS Configuration**: Point `*.fig.systems` and `*.edfig.dev` to your server IP +2. **Media Folders**: Ensure `/media` is mounted with the folder structure above +3. **Docker Network**: Create the homelab network + +```bash +docker network create homelab +``` + +### Deployment Order + +1. **Core Infrastructure** (must be first): +```bash +cd compose/core/traefik && docker compose up -d +cd compose/core/lldap && docker compose up -d +cd compose/core/tinyauth && docker compose up -d +``` + +2. **Configure LLDAP**: + - Visit https://lldap.fig.systems + - Login with admin credentials from `.env` + - Create an observer user for tinyauth + - Add regular users for authentication + +3. **Update Passwords**: + - Update `LLDAP_LDAP_USER_PASS` in `core/lldap/.env` + - Update `LDAP_BIND_PASSWORD` in `core/tinyauth/.env` to match + - Update `SESSION_SECRET` in `core/tinyauth/.env` + - Update database passwords in service `.env` files + +4. **Deploy Services**: +```bash +# Media frontend +cd compose/media/frontend/jellyfin && docker compose up -d +cd compose/media/frontend/jellyseer && docker compose up -d +cd compose/media/frontend/immich && docker compose up -d + +# Media automation +cd compose/media/automation/sonarr && docker compose up -d +cd compose/media/automation/radarr && docker compose up -d +cd compose/media/automation/sabnzbd && docker compose up -d +cd compose/media/automation/qbittorrent && docker compose up -d + +# Utility services +cd compose/services/linkwarden && docker compose up -d +cd compose/services/vikunja && docker compose up -d +cd compose/services/lubelogger && docker compose up -d +cd compose/services/calibre-web && docker compose up -d +cd compose/services/booklore && docker compose up -d +cd compose/services/FreshRSS && docker compose up -d +cd compose/services/rsshub && docker compose up -d +cd compose/services/microbin && docker compose up -d +cd compose/services/filebrowser && docker compose up -d +``` + +## 🔐 Security Considerations + +1. **Change Default Passwords**: All `.env` files contain placeholder passwords marked with `changeme_*` +2. **LLDAP Observer User**: Create a readonly user in LLDAP for tinyauth to bind +3. **SSL Certificates**: Traefik automatically obtains Let's Encrypt certificates +4. **Network Isolation**: Services use internal networks for database/cache communication +5. **SSO**: Most services are protected by tinyauth forward authentication + +## 📝 Configuration Files + +Each service has its own `.env` file where applicable. Key files to review: + +- `core/lldap/.env` - LDAP configuration and admin credentials +- `core/tinyauth/.env` - LDAP connection and session settings +- `media/frontend/immich/.env` - Photo management configuration +- `services/linkwarden/.env` - Bookmark manager settings +- `services/microbin/.env` - Pastebin configuration + +## 🔧 Maintenance + +### Viewing Logs +```bash +cd compose/[category]/[service] +docker compose logs -f +``` + +### Updating Services +```bash +cd compose/[category]/[service] +docker compose pull +docker compose up -d +``` + +### Backing Up Data +Important data locations: +- LLDAP: `compose/core/lldap/data/` +- Service configs: `compose/*/*/config/` +- Databases: `compose/*/*/db/` or `compose/*/*/pgdata/` +- Media: `/media/` (handle separately) + +## 🐛 Troubleshooting + +### Service won't start +1. Check logs: `docker compose logs` +2. Verify network exists: `docker network ls | grep homelab` +3. Check port conflicts: `docker ps -a` + +### SSL certificate issues +1. Verify DNS points to your server +2. Check Traefik logs: `cd compose/core/traefik && docker compose logs` +3. Ensure ports 80 and 443 are open + +### SSO not working +1. Verify tinyauth is running: `docker ps | grep tinyauth` +2. Check LLDAP connection in tinyauth logs +3. Verify LDAP bind credentials match in both services + +## 📄 License + +This is a personal homelab configuration. Use at your own risk. + +## 🤝 Contributing + +This is a personal repository, but feel free to use it as a reference for your own homelab! diff --git a/compose/core/lldap/.env b/compose/core/lldap/.env new file mode 100644 index 0000000..b55bf63 --- /dev/null +++ b/compose/core/lldap/.env @@ -0,0 +1,25 @@ +# LLDAP Configuration +# Base DN for the LDAP directory +LLDAP_LDAP_BASE_DN=dc=fig,dc=systems + +# Admin user configuration +LLDAP_LDAP_USER_DN=admin +LLDAP_LDAP_USER_EMAIL=admin@edfig.dev +LLDAP_LDAP_USER_PASS=changeme_please_set_secure_password + +# JWT secret for session management (change this!) +LLDAP_JWT_SECRET=changeme_please_set_random_secret + +# Database URL (SQLite by default) +LLDAP_DATABASE_URL=sqlite:///data/users.db + +# Timezone +TZ=America/New_York + +# Optional: SMTP configuration for password reset emails +# LLDAP_SMTP_OPTIONS__SERVER=smtp.gmail.com +# LLDAP_SMTP_OPTIONS__PORT=587 +# LLDAP_SMTP_OPTIONS__SMTP_ENCRYPTION=STARTTLS +# LLDAP_SMTP_OPTIONS__USER=your-email@gmail.com +# LLDAP_SMTP_OPTIONS__PASSWORD=your-app-password +# LLDAP_SMTP_OPTIONS__FROM=LLDAP Admin diff --git a/compose/core/lldap/compose.yaml b/compose/core/lldap/compose.yaml new file mode 100644 index 0000000..124c9ef --- /dev/null +++ b/compose/core/lldap/compose.yaml @@ -0,0 +1,24 @@ +services: + lldap: + container_name: lldap + image: lldap/lldap:stable + ports: + - "3890:3890" # LDAP + - "17170:17170" # Web UI + env_file: .env + volumes: + - ./data:/data + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.lldap.rule: Host(`lldap.fig.systems`) || Host(`lldap.edfig.dev`) + traefik.http.routers.lldap.entrypoints: websecure + traefik.http.routers.lldap.tls.certresolver: letsencrypt + traefik.http.services.lldap.loadbalancer.server.port: 17170 + traefik.http.routers.lldap.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/core/tinyauth/.env b/compose/core/tinyauth/.env index dc20b36..1ea201d 100644 --- a/compose/core/tinyauth/.env +++ b/compose/core/tinyauth/.env @@ -1,7 +1,27 @@ -TZ=America/Los_Angeles -PUID=1000 -PGID=1000 +# Tinyauth Configuration -MYSQL_DATABASE=librenms -MYSQL_USER=librenms -MYSQL_PASSWORD=asupersecretpassword +# App URL - publicly accessible URL +APP_URL=https://auth.fig.systems + +# Timezone +TZ=America/Los_Angeles + +# LDAP Configuration - Connect to LLDAP +LDAP_ADDRESS=ldap://lldap:3890 +LDAP_BASE_DN=dc=fig,dc=systems +LDAP_BIND_DN=uid=admin,ou=people,dc=fig,dc=systems +LDAP_BIND_PASSWORD=changeme_please_set_secure_password +LDAP_SEARCH_FILTER=(uid=%s) +LDAP_INSECURE=true + +# Optional: Local users (if you want fallback auth) +# Format: username:bcrypt_hash:totp_secret (totp_secret is optional) +# Generate hash with: docker run --rm -it ghcr.io/steveiliop56/tinyauth:latest hash +# USERS= + +# Session configuration +SESSION_SECRET=changeme_please_set_random_session_secret +SESSION_MAX_AGE=86400 + +# Database (optional, uses SQLite by default at /data/tinyauth.db) +# DATABASE_URL=sqlite:///data/tinyauth.db diff --git a/compose/core/tinyauth/compose.yaml b/compose/core/tinyauth/compose.yaml index 7bf1b89..9a0b0a6 100644 --- a/compose/core/tinyauth/compose.yaml +++ b/compose/core/tinyauth/compose.yaml @@ -1,54 +1,26 @@ services: - traefik: - container_name: traefik - image: traefik:v3.3 - command: --api.insecure=true --providers.docker - ports: - - 80:80 - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - whoami: - container_name: whoami - image: traefik/whoami:latest - labels: - traefik.enable: true - traefik.http.routers.whoami.rule: Host(`whoami.example.com`) - traefik.http.routers.whoami.middlewares: tinyauth - - tinyauth-frontend: - container_name: tinyauth-frontend - build: - context: . - dockerfile: frontend/Dockerfile.dev - volumes: - - ./frontend/src:/frontend/src - ports: - - 5173:5173 - labels: - traefik.enable: true - traefik.http.routers.tinyauth.rule: Host(`tinyauth.example.com`) - - tinyauth-backend: - container_name: tinyauth-backend - build: - context: . - dockerfile: Dockerfile.dev - args: - - VERSION=development - - COMMIT_HASH=development - - BUILD_TIMESTAMP=000-00-00T00:00:00Z + tinyauth: + container_name: tinyauth + image: ghcr.io/steveiliop56/tinyauth:latest env_file: .env volumes: - - ./internal:/tinyauth/internal - - ./cmd:/tinyauth/cmd - - ./main.go:/tinyauth/main.go - - /var/run/docker.sock:/var/run/docker.sock - ./data:/data - ports: - - 3000:3000 - - 4000:4000 + restart: unless-stopped + networks: + - homelab labels: traefik.enable: true - traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth-backend:3000/api/auth/traefik + # Web UI routing + traefik.http.routers.tinyauth.rule: Host(`auth.fig.systems`) || Host(`auth.edfig.dev`) + traefik.http.routers.tinyauth.entrypoints: websecure + traefik.http.routers.tinyauth.tls.certresolver: letsencrypt + traefik.http.routers.tinyauth.service: tinyauth-ui + traefik.http.services.tinyauth-ui.loadbalancer.server.port: 3000 + # Forward Auth Middleware + traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik + traefik.http.middlewares.tinyauth.forwardauth.trustforwardheader: true + traefik.http.middlewares.tinyauth.forwardauth.authresponseheaders: X-Forwarded-User +networks: + homelab: + external: true diff --git a/compose/core/traefik/compose.yaml b/compose/core/traefik/compose.yaml new file mode 100644 index 0000000..66a5914 --- /dev/null +++ b/compose/core/traefik/compose.yaml @@ -0,0 +1,46 @@ +services: + traefik: + container_name: traefik + image: traefik:v3.3 + command: + # API Settings + - --api.dashboard=true + # Provider Settings + - --providers.docker=true + - --providers.docker.exposedbydefault=false + - --providers.docker.network=homelab + # Entrypoints + - --entrypoints.web.address=:80 + - --entrypoints.websecure.address=:443 + # HTTP to HTTPS redirect + - --entrypoints.web.http.redirections.entrypoint.to=websecure + - --entrypoints.web.http.redirections.entrypoint.scheme=https + # Let's Encrypt Certificate Resolver + - --certificatesresolvers.letsencrypt.acme.email=admin@edfig.dev + - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json + - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web + # Logging + - --log.level=INFO + - --accesslog=true + ports: + - "80:80" + - "443:443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./letsencrypt:/letsencrypt + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + # Dashboard routing + traefik.http.routers.traefik.rule: Host(`traefik.fig.systems`) || Host(`traefik.edfig.dev`) + traefik.http.routers.traefik.entrypoints: websecure + traefik.http.routers.traefik.tls.certresolver: letsencrypt + traefik.http.routers.traefik.service: api@internal + traefik.http.routers.traefik.middlewares: tinyauth + +networks: + homelab: + name: homelab + driver: bridge diff --git a/compose/media/automation/qbittorrent/compose.yaml b/compose/media/automation/qbittorrent/compose.yaml new file mode 100644 index 0000000..1065fcb --- /dev/null +++ b/compose/media/automation/qbittorrent/compose.yaml @@ -0,0 +1,34 @@ +# qBittorrent - Bittorrent client with WebUI +# Docs: https://docs.linuxserver.io/images/docker-qbittorrent/ + +services: + qbittorrent: + container_name: qbittorrent + image: lscr.io/linuxserver/qbittorrent:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + - WEBUI_PORT=8080 + volumes: + - ./config:/config + - /media/downloads:/downloads + - /media/complete:/complete + - /media/incomplete:/incomplete + ports: + - "6881:6881" # BitTorrent port + - "6881:6881/udp" # BitTorrent DHT + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.qbittorrent.rule: Host(`qbt.fig.systems`) || Host(`qbt.edfig.dev`) + traefik.http.routers.qbittorrent.entrypoints: websecure + traefik.http.routers.qbittorrent.tls.certresolver: letsencrypt + traefik.http.services.qbittorrent.loadbalancer.server.port: 8080 + traefik.http.routers.qbittorrent.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/media/automation/radarr/compose.yaml b/compose/media/automation/radarr/compose.yaml new file mode 100644 index 0000000..39570e7 --- /dev/null +++ b/compose/media/automation/radarr/compose.yaml @@ -0,0 +1,33 @@ +# Radarr - Movie Management and Automation +# Docs: https://wiki.servarr.com/radarr + +services: + radarr: + container_name: radarr + image: lscr.io/linuxserver/radarr:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + volumes: + - ./config:/config + # Media library + - /media/movies:/media/movies + # Download folders + - /media/downloads:/downloads + - /media/complete:/complete + - /media/incomplete:/incomplete + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.radarr.rule: Host(`radarr.fig.systems`) || Host(`radarr.edfig.dev`) + traefik.http.routers.radarr.entrypoints: websecure + traefik.http.routers.radarr.tls.certresolver: letsencrypt + traefik.http.services.radarr.loadbalancer.server.port: 7878 + traefik.http.routers.radarr.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/media/automation/radarr/compose.yml b/compose/media/automation/radarr/compose.yml deleted file mode 100644 index 75fbd7a..0000000 --- a/compose/media/automation/radarr/compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -services: - radarr: - image: - container_name: radarr - restart: unless-stopped - # ports: - # - ":" - # volumes: - # - ./data:/data - # environment: - # - VARIABLE=value diff --git a/compose/media/automation/sabnzbd/compose.yaml b/compose/media/automation/sabnzbd/compose.yaml new file mode 100644 index 0000000..0600d71 --- /dev/null +++ b/compose/media/automation/sabnzbd/compose.yaml @@ -0,0 +1,30 @@ +# SABnzbd - Usenet binary newsreader +# Docs: https://docs.linuxserver.io/images/docker-sabnzbd/ + +services: + sabnzbd: + container_name: sabnzbd + image: lscr.io/linuxserver/sabnzbd:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + volumes: + - ./config:/config + - /media/downloads:/downloads + - /media/complete:/complete + - /media/incomplete:/incomplete + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.sabnzbd.rule: Host(`sabnzbd.fig.systems`) || Host(`sabnzbd.edfig.dev`) + traefik.http.routers.sabnzbd.entrypoints: websecure + traefik.http.routers.sabnzbd.tls.certresolver: letsencrypt + traefik.http.services.sabnzbd.loadbalancer.server.port: 8080 + traefik.http.routers.sabnzbd.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/media/automation/sabnzbd/compose.yml b/compose/media/automation/sabnzbd/compose.yml deleted file mode 100644 index 7d69aba..0000000 --- a/compose/media/automation/sabnzbd/compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -services: - sabnzbd: - image: - container_name: sabnzbd - restart: unless-stopped - # ports: - # - ":" - # volumes: - # - ./data:/data - # environment: - # - VARIABLE=value diff --git a/compose/media/automation/sonarr/compose.yaml b/compose/media/automation/sonarr/compose.yaml new file mode 100644 index 0000000..db39d4d --- /dev/null +++ b/compose/media/automation/sonarr/compose.yaml @@ -0,0 +1,33 @@ +# Sonarr - TV Show Management and Automation +# Docs: https://wiki.servarr.com/sonarr + +services: + sonarr: + container_name: sonarr + image: lscr.io/linuxserver/sonarr:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + volumes: + - ./config:/config + # Media library + - /media/tv:/media/tv + # Download folders + - /media/downloads:/downloads + - /media/complete:/complete + - /media/incomplete:/incomplete + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.sonarr.rule: Host(`sonarr.fig.systems`) || Host(`sonarr.edfig.dev`) + traefik.http.routers.sonarr.entrypoints: websecure + traefik.http.routers.sonarr.tls.certresolver: letsencrypt + traefik.http.services.sonarr.loadbalancer.server.port: 8989 + traefik.http.routers.sonarr.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/media/automation/sonarr/compose.yml b/compose/media/automation/sonarr/compose.yml deleted file mode 100644 index 1210fcc..0000000 --- a/compose/media/automation/sonarr/compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -services: - sonarr: - image: - container_name: sonarr - restart: unless-stopped - # ports: - # - ":" - # volumes: - # - ./data:/data - # environment: - # - VARIABLE=value diff --git a/compose/media/frontend/immich/docker-compose.yml b/compose/media/frontend/immich/compose.yaml similarity index 75% rename from compose/media/frontend/immich/docker-compose.yml rename to compose/media/frontend/immich/compose.yaml index ade846b..c5e8601 100644 --- a/compose/media/frontend/immich/docker-compose.yml +++ b/compose/media/frontend/immich/compose.yaml @@ -1,4 +1,5 @@ # +# Immich - Self-hosted photo and video management # WARNING: To install Immich, follow our guide: https://docs.immich.app/install/docker-compose # # Make sure to use the docker-compose.yml of the current release: @@ -21,6 +22,8 @@ services: # Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file - ${UPLOAD_LOCATION}:/data - /etc/localtime:/etc/localtime:ro + # External photo library (optional - can be imported into Immich) + - /media/photos:/media/photos:ro env_file: - .env ports: @@ -29,8 +32,20 @@ services: - redis - database restart: always + networks: + - homelab + - immich_internal healthcheck: disable: false + labels: + traefik.enable: true + traefik.docker.network: homelab + traefik.http.routers.immich.rule: Host(`photos.fig.systems`) || Host(`photos.edfig.dev`) + traefik.http.routers.immich.entrypoints: websecure + traefik.http.routers.immich.tls.certresolver: letsencrypt + traefik.http.services.immich.loadbalancer.server.port: 2283 + # Optional: Enable SSO (note: Immich has its own user management) + # traefik.http.routers.immich.middlewares: tinyauth immich-machine-learning: container_name: immich_machine_learning @@ -45,6 +60,8 @@ services: env_file: - .env restart: always + networks: + - immich_internal healthcheck: disable: false @@ -54,6 +71,8 @@ services: healthcheck: test: redis-cli ping || exit 1 restart: always + networks: + - immich_internal database: container_name: immich_postgres @@ -70,6 +89,15 @@ services: - ${DB_DATA_LOCATION}:/var/lib/postgresql/data shm_size: 128mb restart: always + networks: + - immich_internal + +networks: + homelab: + external: true + immich_internal: + name: immich_internal + driver: bridge volumes: model-cache: diff --git a/compose/media/frontend/immich/compose.yml b/compose/media/frontend/immich/compose.yml deleted file mode 100644 index a98c8ac..0000000 --- a/compose/media/frontend/immich/compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -services: - immich: - image: - container_name: immich - restart: unless-stopped - # ports: - # - ":" - # volumes: - # - ./data:/data - # environment: - # - VARIABLE=value diff --git a/compose/media/frontend/jellyfin/compose.yaml b/compose/media/frontend/jellyfin/compose.yaml index ba01880..5a4d00d 100644 --- a/compose/media/frontend/jellyfin/compose.yaml +++ b/compose/media/frontend/jellyfin/compose.yaml @@ -1,42 +1,50 @@ -# Compose Docs: -# https://jellyfin.org/docs/general/installation/container/?method=docker-compose -# Transcoding Docs -# https://jellyfin.org/docs/general/post-install/transcoding/hardware-acceleration/nvidia +# Jellyfin Media Server +# Docs: https://jellyfin.org/docs/general/installation/container/?method=docker-compose +# Transcoding: https://jellyfin.org/docs/general/post-install/transcoding/hardware-acceleration/nvidia + services: jellyfin: - image: jellyfin/jellyfin container_name: jellyfin - user: uid:gid - ports: - - 8096:8096/tcp - - 7359:7359/udp - volumes: - - /path/to/config:/config - - /path/to/cache:/cache - - type: bind - source: /path/to/media - target: /media - - type: bind - source: /path/to/media2 - target: /media2 - read_only: true - # Optional - extra fonts to be used during transcoding with subtitle burn-in - - type: bind - source: /path/to/fonts - target: /usr/local/share/fonts/custom - read_only: true - restart: 'unless-stopped' - # Optional - alternative address used for autodiscovery + image: lscr.io/linuxserver/jellyfin:latest environment: - - JELLYFIN_PublishedServerUrl=http://example.com - # Optional - may be necessary for docker healthcheck to pass if running in host network mode - extra_hosts: - - 'host.docker.internal:host-gateway' - runtime: nvidia - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: all - capabilities: [gpu] + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + - JELLYFIN_PublishedServerUrl=https://flix.fig.systems + volumes: + - ./config:/config + - ./cache:/cache + # Media folders (read-only) + - /media/movies:/media/movies:ro + - /media/tv:/media/tv:ro + - /media/music:/media/music:ro + - /media/photos:/media/photos:ro + - /media/homemovies:/media/homemovies:ro + ports: + - "8096:8096" + - "7359:7359/udp" # Optional - for autodiscovery + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.jellyfin.rule: Host(`flix.fig.systems`) || Host(`flix.edfig.dev`) + traefik.http.routers.jellyfin.entrypoints: websecure + traefik.http.routers.jellyfin.tls.certresolver: letsencrypt + traefik.http.services.jellyfin.loadbalancer.server.port: 8096 + # Note: Jellyfin has its own auth system, SSO middleware disabled by default + # Uncomment the line below to enable SSO (requires users to auth via tinyauth first) + # traefik.http.routers.jellyfin.middlewares: tinyauth + # Uncomment for NVIDIA GPU transcoding + # runtime: nvidia + # deploy: + # resources: + # reservations: + # devices: + # - driver: nvidia + # count: all + # capabilities: [gpu] + +networks: + homelab: + external: true diff --git a/compose/media/frontend/jellyseer/compose.yaml b/compose/media/frontend/jellyseer/compose.yaml new file mode 100644 index 0000000..5681ee5 --- /dev/null +++ b/compose/media/frontend/jellyseer/compose.yaml @@ -0,0 +1,28 @@ +# Jellyseerr - Media Request Management for Jellyfin +# Docs: https://hub.docker.com/r/fallenbagel/jellyseerr + +services: + jellyseerr: + container_name: jellyseerr + image: fallenbagel/jellyseerr:latest + environment: + - LOG_LEVEL=info + - TZ=America/Los_Angeles + - PUID=1000 + - PGID=1000 + volumes: + - ./config:/app/config + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.jellyseerr.rule: Host(`requests.fig.systems`) || Host(`requests.edfig.dev`) + traefik.http.routers.jellyseerr.entrypoints: websecure + traefik.http.routers.jellyseerr.tls.certresolver: letsencrypt + traefik.http.services.jellyseerr.loadbalancer.server.port: 5055 + traefik.http.routers.jellyseerr.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/media/frontend/jellyseer/compose.yml b/compose/media/frontend/jellyseer/compose.yml deleted file mode 100644 index 9ed27d3..0000000 --- a/compose/media/frontend/jellyseer/compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -# https://hub.docker.com/r/fallenbagel/jellyseerr -services: - jellyseerr: - image: fallenbagel/jellyseerr:latest - container_name: jellyseerr - environment: - - LOG_LEVEL=debug - - TZ=America/Los_Angeles - ports: - - 8002:5055 - volumes: - - /path/to/appdata/config:/app/config - restart: unless-stopped - diff --git a/compose/services/FreshRSS/compose.yaml b/compose/services/FreshRSS/compose.yaml new file mode 100644 index 0000000..2d23402 --- /dev/null +++ b/compose/services/FreshRSS/compose.yaml @@ -0,0 +1,27 @@ +# FreshRSS - Self-hosted RSS feed aggregator +# Docs: https://docs.linuxserver.io/images/docker-freshrss/ + +services: + freshrss: + container_name: freshrss + image: lscr.io/linuxserver/freshrss:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + volumes: + - ./config:/config + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.freshrss.rule: Host(`rss.fig.systems`) || Host(`rss.edfig.dev`) + traefik.http.routers.freshrss.entrypoints: websecure + traefik.http.routers.freshrss.tls.certresolver: letsencrypt + traefik.http.services.freshrss.loadbalancer.server.port: 80 + traefik.http.routers.freshrss.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/services/FreshRSS/compose.yml b/compose/services/FreshRSS/compose.yml deleted file mode 100644 index bc45db0..0000000 --- a/compose/services/FreshRSS/compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -# https://docs.linuxserver.io/images/docker-freshrss/ ---- -services: - freshrss: - image: lscr.io/linuxserver/freshrss:latest - container_name: freshrss - environment: - - PUID=1000 - - PGID=1000 - volumes: - - /path/to/freshrss/config:/config - ports: - - 8000:80 - restart: unless-stopped diff --git a/compose/services/booklore/compose.yaml b/compose/services/booklore/compose.yaml new file mode 100644 index 0000000..2a5d3c6 --- /dev/null +++ b/compose/services/booklore/compose.yaml @@ -0,0 +1,28 @@ +# Booklore - Book tracking and management +# Docs: https://github.com/lorebooks/booklore + +services: + booklore: + container_name: booklore + image: ghcr.io/lorebooks/booklore:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + volumes: + - ./config:/config + - /media/books:/books:ro + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.booklore.rule: Host(`booklore.fig.systems`) || Host(`booklore.edfig.dev`) + traefik.http.routers.booklore.entrypoints: websecure + traefik.http.routers.booklore.tls.certresolver: letsencrypt + traefik.http.services.booklore.loadbalancer.server.port: 3000 + traefik.http.routers.booklore.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/services/calibre-web/compose.yaml b/compose/services/calibre-web/compose.yaml new file mode 100644 index 0000000..52d24ce --- /dev/null +++ b/compose/services/calibre-web/compose.yaml @@ -0,0 +1,30 @@ +# Calibre-web - Web app for browsing, reading and downloading eBooks +# Docs: https://hub.docker.com/r/linuxserver/calibre-web + +services: + calibre-web: + container_name: calibre-web + image: lscr.io/linuxserver/calibre-web:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + - DOCKER_MODS=linuxserver/mods:universal-calibre + - OAUTHLIB_RELAX_TOKEN_SCOPE=1 + volumes: + - ./config:/config + - /media/books:/books + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.calibre-web.rule: Host(`books.fig.systems`) || Host(`books.edfig.dev`) + traefik.http.routers.calibre-web.entrypoints: websecure + traefik.http.routers.calibre-web.tls.certresolver: letsencrypt + traefik.http.services.calibre-web.loadbalancer.server.port: 8083 + traefik.http.routers.calibre-web.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/services/calibre-web/compose.yml b/compose/services/calibre-web/compose.yml deleted file mode 100644 index 8316c4b..0000000 --- a/compose/services/calibre-web/compose.yml +++ /dev/null @@ -1,19 +0,0 @@ -# https://hub.docker.com/r/linuxserver/calibre-web ---- -services: - calibre-web: - image: lscr.io/linuxserver/calibre-web:latest - container_name: calibre-web - environment: - - PUID=1000 - - PGID=1000 - - TZ=Etc/UTC - - DOCKER_MODS=linuxserver/mods:universal-calibre #optional - - OAUTHLIB_RELAX_TOKEN_SCOPE=1 #optional - volumes: - - /path/to/calibre-web/data:/config - - /path/to/calibre/library:/books - ports: - - 8002:8083 - restart: unless-stopped - diff --git a/compose/services/filebrowser/compose.yaml b/compose/services/filebrowser/compose.yaml new file mode 100644 index 0000000..63af6d8 --- /dev/null +++ b/compose/services/filebrowser/compose.yaml @@ -0,0 +1,29 @@ +# File Browser - Web-based file manager +# Docs: https://filebrowser.org/ + +services: + filebrowser: + container_name: filebrowser + image: filebrowser/filebrowser:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=America/Los_Angeles + volumes: + - ./config:/config + - ./database:/database + - /media:/srv + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.filebrowser.rule: Host(`files.fig.systems`) || Host(`files.edfig.dev`) + traefik.http.routers.filebrowser.entrypoints: websecure + traefik.http.routers.filebrowser.tls.certresolver: letsencrypt + traefik.http.services.filebrowser.loadbalancer.server.port: 80 + traefik.http.routers.filebrowser.middlewares: tinyauth + +networks: + homelab: + external: true diff --git a/compose/services/filebrowser/compose.yml b/compose/services/filebrowser/compose.yml deleted file mode 100644 index 4711e49..0000000 --- a/compose/services/filebrowser/compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -services: - filebrowser: - image: - container_name: filebrowser - restart: unless-stopped - # ports: - # - ":" - # volumes: - # - ./data:/data - # environment: - # - VARIABLE=value diff --git a/compose/services/linkwarden/compose.yaml b/compose/services/linkwarden/compose.yaml index 5e97376..78b3790 100644 --- a/compose/services/linkwarden/compose.yaml +++ b/compose/services/linkwarden/compose.yaml @@ -1,29 +1,64 @@ -# https://docs.linkwarden.app/self-hosting/installation +# Linkwarden - Collaborative bookmark manager +# Docs: https://docs.linkwarden.app/self-hosting/installation + services: - postgres: - image: postgres:16-alpine - env_file: .env - restart: always - volumes: - - ./pgdata:/var/lib/postgresql/data linkwarden: + container_name: linkwarden + image: ghcr.io/linkwarden/linkwarden:latest env_file: .env environment: - - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres - restart: always - # build: . # uncomment to build from source - image: ghcr.io/linkwarden/linkwarden:latest # comment to build from source - ports: - - 3000:3000 + - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@linkwarden-postgres:5432/postgres + - TZ=America/Los_Angeles volumes: - ./data:/data/data depends_on: - - postgres - - meilisearch - meilisearch: - image: getmeili/meilisearch:v1.12.8 + - linkwarden-postgres + - linkwarden-meilisearch restart: always - env_file: - - .env + networks: + - homelab + - linkwarden_internal + labels: + traefik.enable: true + traefik.docker.network: homelab + traefik.http.routers.linkwarden.rule: Host(`links.fig.systems`) || Host(`links.edfig.dev`) + traefik.http.routers.linkwarden.entrypoints: websecure + traefik.http.routers.linkwarden.tls.certresolver: letsencrypt + traefik.http.services.linkwarden.loadbalancer.server.port: 3000 + traefik.http.routers.linkwarden.middlewares: tinyauth + + linkwarden-postgres: + container_name: linkwarden-postgres + image: postgres:16-alpine + env_file: .env + environment: + - TZ=America/Los_Angeles + volumes: + - ./pgdata:/var/lib/postgresql/data + restart: always + networks: + - linkwarden_internal + healthcheck: + test: ["CMD-SHELL", "pg_isready -h localhost -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + + linkwarden-meilisearch: + container_name: linkwarden-meilisearch + image: getmeili/meilisearch:v1.12.8 + env_file: .env + environment: + - TZ=America/Los_Angeles volumes: - ./meili_data:/meili_data + restart: always + networks: + - linkwarden_internal + +networks: + homelab: + external: true + linkwarden_internal: + name: linkwarden_internal + driver: bridge diff --git a/compose/services/lubelogger/compose.yaml b/compose/services/lubelogger/compose.yaml new file mode 100644 index 0000000..422c249 --- /dev/null +++ b/compose/services/lubelogger/compose.yaml @@ -0,0 +1,30 @@ +# LubeLogger - Vehicle maintenance and fuel tracking +# Docs: https://github.com/hargata/lubelogger + +services: + lubelogger: + container_name: lubelogger + image: ghcr.io/hargata/lubelogger:latest + environment: + - TZ=America/Los_Angeles + volumes: + - data:/App/data + - keys:/root/.aspnet/DataProtection-Keys + restart: unless-stopped + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.lubelogger.rule: Host(`garage.fig.systems`) || Host(`garage.edfig.dev`) + traefik.http.routers.lubelogger.entrypoints: websecure + traefik.http.routers.lubelogger.tls.certresolver: letsencrypt + traefik.http.services.lubelogger.loadbalancer.server.port: 8080 + traefik.http.routers.lubelogger.middlewares: tinyauth + +networks: + homelab: + external: true + +volumes: + data: + keys: diff --git a/compose/services/lubelogger/compose.yml b/compose/services/lubelogger/compose.yml deleted file mode 100644 index 0d1111d..0000000 --- a/compose/services/lubelogger/compose.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- - -services: - app: - image: ghcr.io/hargata/lubelogger:latest - restart: unless-stopped - volumes: - - data:/App/data - - keys:/root/.aspnet/DataProtection-Keys - ports: - - 8007:8080 - -volumes: - data: - keys: diff --git a/compose/services/microbin/compose.yaml b/compose/services/microbin/compose.yaml index 9ae0b07..9d0e8be 100644 --- a/compose/services/microbin/compose.yaml +++ b/compose/services/microbin/compose.yaml @@ -1,11 +1,11 @@ +# MicroBin - Encrypted pastebin with file upload support +# Docs: https://github.com/szabodanika/microbin + services: microbin: + container_name: microbin image: danielszabo99/microbin:latest - restart: always - ports: - - "${MICROBIN_PORT}:8080" - volumes: - - ./microbin-data:/app/microbin_data + env_file: .env environment: MICROBIN_BASIC_AUTH_USERNAME: ${MICROBIN_BASIC_AUTH_USERNAME} MICROBIN_BASIC_AUTH_PASSWORD: ${MICROBIN_BASIC_AUTH_PASSWORD} @@ -45,4 +45,20 @@ services: MICROBIN_ENCRYPTION_SERVER_SIDE: ${MICROBIN_ENCRYPTION_SERVER_SIDE} MICROBIN_MAX_FILE_SIZE_ENCRYPTED_MB: ${MICROBIN_MAX_FILE_SIZE_ENCRYPTED_MB} MICROBIN_MAX_FILE_SIZE_UNENCRYPTED_MB: ${MICROBIN_MAX_FILE_SIZE_UNENCRYPTED_MB} + volumes: + - ./microbin-data:/app/microbin_data + restart: always + networks: + - homelab + labels: + traefik.enable: true + traefik.http.routers.microbin.rule: Host(`paste.fig.systems`) || Host(`paste.edfig.dev`) + traefik.http.routers.microbin.entrypoints: websecure + traefik.http.routers.microbin.tls.certresolver: letsencrypt + traefik.http.services.microbin.loadbalancer.server.port: 8080 + # Note: MicroBin has its own auth, SSO disabled by default + # traefik.http.routers.microbin.middlewares: tinyauth +networks: + homelab: + external: true diff --git a/compose/services/rsshub/compose.yaml b/compose/services/rsshub/compose.yaml index c56cf0e..6394c02 100644 --- a/compose/services/rsshub/compose.yaml +++ b/compose/services/rsshub/compose.yaml @@ -1,61 +1,76 @@ +# RSSHub - RSS feed generator for everything +# Docs: https://docs.rsshub.app/ + services: rsshub: - # two ways to enable puppeteer: - # * comment out marked lines, then use this image instead: diygod/rsshub:chromium-bundled - # * (consumes more disk space and memory) leave everything unchanged + container_name: rsshub + # Using chromium-bundled image for full puppeteer support image: diygod/rsshub:chromium-bundled - restart: always - ports: - - 1200:1200 environment: NODE_ENV: production CACHE_TYPE: redis - REDIS_URL: redis://redis:6379/ - PUPPETEER_WS_ENDPOINT: ws://browserless:3000 # marked - healthcheck: - test: - - CMD - - curl - - -f - - http://localhost:1200/healthz - interval: 30s - timeout: 10s - retries: 3 + REDIS_URL: redis://rsshub-redis:6379/ + PUPPETEER_WS_ENDPOINT: ws://rsshub-browserless:3000 + TZ: America/Los_Angeles + restart: always + networks: + - homelab + - rsshub_internal depends_on: - - redis - - browserless # marked - browserless: - # marked - image: browserless/chrome # marked - restart: always # marked - ulimits: - # marked - core: - # marked - hard: 0 # marked - soft: 0 # marked + - rsshub-redis + - rsshub-browserless healthcheck: - test: - - CMD - - curl - - -f - - http://localhost:3000/pressure + test: ["CMD", "curl", "-f", "http://localhost:1200/healthz"] interval: 30s timeout: 10s retries: 3 - redis: + labels: + traefik.enable: true + traefik.docker.network: homelab + traefik.http.routers.rsshub.rule: Host(`rsshub.fig.systems`) || Host(`rsshub.edfig.dev`) + traefik.http.routers.rsshub.entrypoints: websecure + traefik.http.routers.rsshub.tls.certresolver: letsencrypt + traefik.http.services.rsshub.loadbalancer.server.port: 1200 + # Optional: enable SSO (may interfere with RSS readers) + # traefik.http.routers.rsshub.middlewares: tinyauth + + rsshub-browserless: + container_name: rsshub-browserless + image: browserless/chrome + restart: always + networks: + - rsshub_internal + ulimits: + core: + hard: 0 + soft: 0 + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/pressure"] + interval: 30s + timeout: 10s + retries: 3 + + rsshub-redis: + container_name: rsshub-redis image: redis:alpine restart: always + networks: + - rsshub_internal volumes: - redis-data:/data healthcheck: - test: - - CMD - - redis-cli - - ping + test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 10s retries: 5 start_period: 5s + +networks: + homelab: + external: true + rsshub_internal: + name: rsshub_internal + driver: bridge + volumes: - redis-data: null + redis-data: diff --git a/compose/services/vikunja/compose.yaml b/compose/services/vikunja/compose.yaml new file mode 100644 index 0000000..4249010 --- /dev/null +++ b/compose/services/vikunja/compose.yaml @@ -0,0 +1,58 @@ +# Vikunja - The open-source, self-hostable to-do app +# Docs: https://vikunja.io/docs/full-docker-example/ + +services: + vikunja: + container_name: vikunja + image: vikunja/vikunja:latest + environment: + VIKUNJA_SERVICE_PUBLICURL: https://tasks.fig.systems + VIKUNJA_DATABASE_HOST: vikunja-db + VIKUNJA_DATABASE_PASSWORD: changeme_please_set_secure_password + VIKUNJA_DATABASE_TYPE: postgres + VIKUNJA_DATABASE_USER: vikunja + VIKUNJA_DATABASE_DATABASE: vikunja + VIKUNJA_SERVICE_JWTSECRET: changeme_please_set_random_jwt_secret + TZ: America/Los_Angeles + volumes: + - ./files:/app/vikunja/files + depends_on: + vikunja-db: + condition: service_healthy + restart: unless-stopped + networks: + - homelab + - vikunja_internal + labels: + traefik.enable: true + traefik.docker.network: homelab + traefik.http.routers.vikunja.rule: Host(`tasks.fig.systems`) || Host(`tasks.edfig.dev`) + traefik.http.routers.vikunja.entrypoints: websecure + traefik.http.routers.vikunja.tls.certresolver: letsencrypt + traefik.http.services.vikunja.loadbalancer.server.port: 3456 + traefik.http.routers.vikunja.middlewares: tinyauth + + vikunja-db: + container_name: vikunja-db + image: postgres:18 + environment: + POSTGRES_PASSWORD: changeme_please_set_secure_password + POSTGRES_USER: vikunja + POSTGRES_DB: vikunja + TZ: America/Los_Angeles + volumes: + - ./db:/var/lib/postgresql/data + restart: unless-stopped + networks: + - vikunja_internal + healthcheck: + test: ["CMD-SHELL", "pg_isready -h localhost -U $$POSTGRES_USER"] + interval: 2s + start_period: 30s + +networks: + homelab: + external: true + vikunja_internal: + name: vikunja_internal + driver: bridge diff --git a/compose/services/vikunja/compose.yml b/compose/services/vikunja/compose.yml deleted file mode 100644 index e18b7f3..0000000 --- a/compose/services/vikunja/compose.yml +++ /dev/null @@ -1,32 +0,0 @@ -# https://vikunja.io/docs/full-docker-example/#example-without-any-proxy -services: - vikunja: - image: vikunja/vikunja - environment: - VIKUNJA_SERVICE_PUBLICURL: http:// - VIKUNJA_DATABASE_HOST: db - VIKUNJA_DATABASE_PASSWORD: changeme - VIKUNJA_DATABASE_TYPE: postgres - VIKUNJA_DATABASE_USER: vikunja - VIKUNJA_DATABASE_DATABASE: vikunja - VIKUNJA_SERVICE_JWTSECRET: - ports: - - 3456:3456 - volumes: - - ./files:/app/vikunja/files - depends_on: - db: - condition: service_healthy - restart: unless-stopped - db: - image: postgres:18 - environment: - POSTGRES_PASSWORD: changeme - POSTGRES_USER: vikunja - volumes: - - ./db:/var/lib/postgresql/data - restart: unless-stopped - healthcheck: - test: ["CMD-SHELL", "pg_isready -h localhost -U $$POSTGRES_USER"] - interval: 2s - start_period: 30s