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
This commit is contained in:
parent
cae18a8dba
commit
fd48fed9d8
32 changed files with 921 additions and 306 deletions
219
README.md
219
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!
|
||||||
|
|
|
||||||
25
compose/core/lldap/.env
Normal file
25
compose/core/lldap/.env
Normal file
|
|
@ -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 <admin@edfig.dev>
|
||||||
24
compose/core/lldap/compose.yaml
Normal file
24
compose/core/lldap/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -1,7 +1,27 @@
|
||||||
TZ=America/Los_Angeles
|
# Tinyauth Configuration
|
||||||
PUID=1000
|
|
||||||
PGID=1000
|
|
||||||
|
|
||||||
MYSQL_DATABASE=librenms
|
# App URL - publicly accessible URL
|
||||||
MYSQL_USER=librenms
|
APP_URL=https://auth.fig.systems
|
||||||
MYSQL_PASSWORD=asupersecretpassword
|
|
||||||
|
# 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 <password>
|
||||||
|
# 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
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,26 @@
|
||||||
services:
|
services:
|
||||||
traefik:
|
tinyauth:
|
||||||
container_name: traefik
|
container_name: tinyauth
|
||||||
image: traefik:v3.3
|
image: ghcr.io/steveiliop56/tinyauth:latest
|
||||||
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
|
|
||||||
env_file: .env
|
env_file: .env
|
||||||
volumes:
|
volumes:
|
||||||
- ./internal:/tinyauth/internal
|
|
||||||
- ./cmd:/tinyauth/cmd
|
|
||||||
- ./main.go:/tinyauth/main.go
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
ports:
|
restart: unless-stopped
|
||||||
- 3000:3000
|
networks:
|
||||||
- 4000:4000
|
- homelab
|
||||||
labels:
|
labels:
|
||||||
traefik.enable: true
|
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
|
||||||
|
|
|
||||||
46
compose/core/traefik/compose.yaml
Normal file
46
compose/core/traefik/compose.yaml
Normal file
|
|
@ -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
|
||||||
34
compose/media/automation/qbittorrent/compose.yaml
Normal file
34
compose/media/automation/qbittorrent/compose.yaml
Normal file
|
|
@ -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
|
||||||
33
compose/media/automation/radarr/compose.yaml
Normal file
33
compose/media/automation/radarr/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
services:
|
|
||||||
radarr:
|
|
||||||
image:
|
|
||||||
container_name: radarr
|
|
||||||
restart: unless-stopped
|
|
||||||
# ports:
|
|
||||||
# - ":"
|
|
||||||
# volumes:
|
|
||||||
# - ./data:/data
|
|
||||||
# environment:
|
|
||||||
# - VARIABLE=value
|
|
||||||
30
compose/media/automation/sabnzbd/compose.yaml
Normal file
30
compose/media/automation/sabnzbd/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
services:
|
|
||||||
sabnzbd:
|
|
||||||
image:
|
|
||||||
container_name: sabnzbd
|
|
||||||
restart: unless-stopped
|
|
||||||
# ports:
|
|
||||||
# - ":"
|
|
||||||
# volumes:
|
|
||||||
# - ./data:/data
|
|
||||||
# environment:
|
|
||||||
# - VARIABLE=value
|
|
||||||
33
compose/media/automation/sonarr/compose.yaml
Normal file
33
compose/media/automation/sonarr/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
services:
|
|
||||||
sonarr:
|
|
||||||
image:
|
|
||||||
container_name: sonarr
|
|
||||||
restart: unless-stopped
|
|
||||||
# ports:
|
|
||||||
# - ":"
|
|
||||||
# volumes:
|
|
||||||
# - ./data:/data
|
|
||||||
# environment:
|
|
||||||
# - VARIABLE=value
|
|
||||||
|
|
@ -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
|
# 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:
|
# 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
|
# 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
|
- ${UPLOAD_LOCATION}:/data
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
# External photo library (optional - can be imported into Immich)
|
||||||
|
- /media/photos:/media/photos:ro
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
ports:
|
||||||
|
|
@ -29,8 +32,20 @@ services:
|
||||||
- redis
|
- redis
|
||||||
- database
|
- database
|
||||||
restart: always
|
restart: always
|
||||||
|
networks:
|
||||||
|
- homelab
|
||||||
|
- immich_internal
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: false
|
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:
|
immich-machine-learning:
|
||||||
container_name: immich_machine_learning
|
container_name: immich_machine_learning
|
||||||
|
|
@ -45,6 +60,8 @@ services:
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
restart: always
|
restart: always
|
||||||
|
networks:
|
||||||
|
- immich_internal
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: false
|
disable: false
|
||||||
|
|
||||||
|
|
@ -54,6 +71,8 @@ services:
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: redis-cli ping || exit 1
|
test: redis-cli ping || exit 1
|
||||||
restart: always
|
restart: always
|
||||||
|
networks:
|
||||||
|
- immich_internal
|
||||||
|
|
||||||
database:
|
database:
|
||||||
container_name: immich_postgres
|
container_name: immich_postgres
|
||||||
|
|
@ -70,6 +89,15 @@ services:
|
||||||
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
||||||
shm_size: 128mb
|
shm_size: 128mb
|
||||||
restart: always
|
restart: always
|
||||||
|
networks:
|
||||||
|
- immich_internal
|
||||||
|
|
||||||
|
networks:
|
||||||
|
homelab:
|
||||||
|
external: true
|
||||||
|
immich_internal:
|
||||||
|
name: immich_internal
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
model-cache:
|
model-cache:
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
services:
|
|
||||||
immich:
|
|
||||||
image:
|
|
||||||
container_name: immich
|
|
||||||
restart: unless-stopped
|
|
||||||
# ports:
|
|
||||||
# - ":"
|
|
||||||
# volumes:
|
|
||||||
# - ./data:/data
|
|
||||||
# environment:
|
|
||||||
# - VARIABLE=value
|
|
||||||
|
|
@ -1,42 +1,50 @@
|
||||||
# Compose Docs:
|
# Jellyfin Media Server
|
||||||
# https://jellyfin.org/docs/general/installation/container/?method=docker-compose
|
# Docs: https://jellyfin.org/docs/general/installation/container/?method=docker-compose
|
||||||
# Transcoding Docs
|
# Transcoding: https://jellyfin.org/docs/general/post-install/transcoding/hardware-acceleration/nvidia
|
||||||
# https://jellyfin.org/docs/general/post-install/transcoding/hardware-acceleration/nvidia
|
|
||||||
services:
|
services:
|
||||||
jellyfin:
|
jellyfin:
|
||||||
image: jellyfin/jellyfin
|
|
||||||
container_name: jellyfin
|
container_name: jellyfin
|
||||||
user: uid:gid
|
image: lscr.io/linuxserver/jellyfin:latest
|
||||||
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
|
|
||||||
environment:
|
environment:
|
||||||
- JELLYFIN_PublishedServerUrl=http://example.com
|
- PUID=1000
|
||||||
# Optional - may be necessary for docker healthcheck to pass if running in host network mode
|
- PGID=1000
|
||||||
extra_hosts:
|
- TZ=America/Los_Angeles
|
||||||
- 'host.docker.internal:host-gateway'
|
- JELLYFIN_PublishedServerUrl=https://flix.fig.systems
|
||||||
runtime: nvidia
|
volumes:
|
||||||
deploy:
|
- ./config:/config
|
||||||
resources:
|
- ./cache:/cache
|
||||||
reservations:
|
# Media folders (read-only)
|
||||||
devices:
|
- /media/movies:/media/movies:ro
|
||||||
- driver: nvidia
|
- /media/tv:/media/tv:ro
|
||||||
count: all
|
- /media/music:/media/music:ro
|
||||||
capabilities: [gpu]
|
- /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
|
||||||
|
|
|
||||||
28
compose/media/frontend/jellyseer/compose.yaml
Normal file
28
compose/media/frontend/jellyseer/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
27
compose/services/FreshRSS/compose.yaml
Normal file
27
compose/services/FreshRSS/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -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
|
|
||||||
28
compose/services/booklore/compose.yaml
Normal file
28
compose/services/booklore/compose.yaml
Normal file
|
|
@ -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
|
||||||
30
compose/services/calibre-web/compose.yaml
Normal file
30
compose/services/calibre-web/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
29
compose/services/filebrowser/compose.yaml
Normal file
29
compose/services/filebrowser/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
services:
|
|
||||||
filebrowser:
|
|
||||||
image:
|
|
||||||
container_name: filebrowser
|
|
||||||
restart: unless-stopped
|
|
||||||
# ports:
|
|
||||||
# - ":"
|
|
||||||
# volumes:
|
|
||||||
# - ./data:/data
|
|
||||||
# environment:
|
|
||||||
# - VARIABLE=value
|
|
||||||
|
|
@ -1,29 +1,64 @@
|
||||||
# https://docs.linkwarden.app/self-hosting/installation
|
# Linkwarden - Collaborative bookmark manager
|
||||||
|
# Docs: https://docs.linkwarden.app/self-hosting/installation
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
|
||||||
image: postgres:16-alpine
|
|
||||||
env_file: .env
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- ./pgdata:/var/lib/postgresql/data
|
|
||||||
linkwarden:
|
linkwarden:
|
||||||
|
container_name: linkwarden
|
||||||
|
image: ghcr.io/linkwarden/linkwarden:latest
|
||||||
env_file: .env
|
env_file: .env
|
||||||
environment:
|
environment:
|
||||||
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
|
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@linkwarden-postgres:5432/postgres
|
||||||
restart: always
|
- TZ=America/Los_Angeles
|
||||||
# build: . # uncomment to build from source
|
|
||||||
image: ghcr.io/linkwarden/linkwarden:latest # comment to build from source
|
|
||||||
ports:
|
|
||||||
- 3000:3000
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data/data
|
- ./data:/data/data
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- linkwarden-postgres
|
||||||
- meilisearch
|
- linkwarden-meilisearch
|
||||||
meilisearch:
|
|
||||||
image: getmeili/meilisearch:v1.12.8
|
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
networks:
|
||||||
- .env
|
- 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:
|
volumes:
|
||||||
- ./meili_data:/meili_data
|
- ./meili_data:/meili_data
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- linkwarden_internal
|
||||||
|
|
||||||
|
networks:
|
||||||
|
homelab:
|
||||||
|
external: true
|
||||||
|
linkwarden_internal:
|
||||||
|
name: linkwarden_internal
|
||||||
|
driver: bridge
|
||||||
|
|
|
||||||
30
compose/services/lubelogger/compose.yaml
Normal file
30
compose/services/lubelogger/compose.yaml
Normal file
|
|
@ -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:
|
||||||
|
|
@ -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:
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
|
# MicroBin - Encrypted pastebin with file upload support
|
||||||
|
# Docs: https://github.com/szabodanika/microbin
|
||||||
|
|
||||||
services:
|
services:
|
||||||
microbin:
|
microbin:
|
||||||
|
container_name: microbin
|
||||||
image: danielszabo99/microbin:latest
|
image: danielszabo99/microbin:latest
|
||||||
restart: always
|
env_file: .env
|
||||||
ports:
|
|
||||||
- "${MICROBIN_PORT}:8080"
|
|
||||||
volumes:
|
|
||||||
- ./microbin-data:/app/microbin_data
|
|
||||||
environment:
|
environment:
|
||||||
MICROBIN_BASIC_AUTH_USERNAME: ${MICROBIN_BASIC_AUTH_USERNAME}
|
MICROBIN_BASIC_AUTH_USERNAME: ${MICROBIN_BASIC_AUTH_USERNAME}
|
||||||
MICROBIN_BASIC_AUTH_PASSWORD: ${MICROBIN_BASIC_AUTH_PASSWORD}
|
MICROBIN_BASIC_AUTH_PASSWORD: ${MICROBIN_BASIC_AUTH_PASSWORD}
|
||||||
|
|
@ -45,4 +45,20 @@ services:
|
||||||
MICROBIN_ENCRYPTION_SERVER_SIDE: ${MICROBIN_ENCRYPTION_SERVER_SIDE}
|
MICROBIN_ENCRYPTION_SERVER_SIDE: ${MICROBIN_ENCRYPTION_SERVER_SIDE}
|
||||||
MICROBIN_MAX_FILE_SIZE_ENCRYPTED_MB: ${MICROBIN_MAX_FILE_SIZE_ENCRYPTED_MB}
|
MICROBIN_MAX_FILE_SIZE_ENCRYPTED_MB: ${MICROBIN_MAX_FILE_SIZE_ENCRYPTED_MB}
|
||||||
MICROBIN_MAX_FILE_SIZE_UNENCRYPTED_MB: ${MICROBIN_MAX_FILE_SIZE_UNENCRYPTED_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
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,76 @@
|
||||||
|
# RSSHub - RSS feed generator for everything
|
||||||
|
# Docs: https://docs.rsshub.app/
|
||||||
|
|
||||||
services:
|
services:
|
||||||
rsshub:
|
rsshub:
|
||||||
# two ways to enable puppeteer:
|
container_name: rsshub
|
||||||
# * comment out marked lines, then use this image instead: diygod/rsshub:chromium-bundled
|
# Using chromium-bundled image for full puppeteer support
|
||||||
# * (consumes more disk space and memory) leave everything unchanged
|
|
||||||
image: diygod/rsshub:chromium-bundled
|
image: diygod/rsshub:chromium-bundled
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- 1200:1200
|
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
CACHE_TYPE: redis
|
CACHE_TYPE: redis
|
||||||
REDIS_URL: redis://redis:6379/
|
REDIS_URL: redis://rsshub-redis:6379/
|
||||||
PUPPETEER_WS_ENDPOINT: ws://browserless:3000 # marked
|
PUPPETEER_WS_ENDPOINT: ws://rsshub-browserless:3000
|
||||||
healthcheck:
|
TZ: America/Los_Angeles
|
||||||
test:
|
restart: always
|
||||||
- CMD
|
networks:
|
||||||
- curl
|
- homelab
|
||||||
- -f
|
- rsshub_internal
|
||||||
- http://localhost:1200/healthz
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- rsshub-redis
|
||||||
- browserless # marked
|
- rsshub-browserless
|
||||||
browserless:
|
|
||||||
# marked
|
|
||||||
image: browserless/chrome # marked
|
|
||||||
restart: always # marked
|
|
||||||
ulimits:
|
|
||||||
# marked
|
|
||||||
core:
|
|
||||||
# marked
|
|
||||||
hard: 0 # marked
|
|
||||||
soft: 0 # marked
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test: ["CMD", "curl", "-f", "http://localhost:1200/healthz"]
|
||||||
- CMD
|
|
||||||
- curl
|
|
||||||
- -f
|
|
||||||
- http://localhost:3000/pressure
|
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
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
|
image: redis:alpine
|
||||||
restart: always
|
restart: always
|
||||||
|
networks:
|
||||||
|
- rsshub_internal
|
||||||
volumes:
|
volumes:
|
||||||
- redis-data:/data
|
- redis-data:/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
- CMD
|
|
||||||
- redis-cli
|
|
||||||
- ping
|
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
start_period: 5s
|
start_period: 5s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
homelab:
|
||||||
|
external: true
|
||||||
|
rsshub_internal:
|
||||||
|
name: rsshub_internal
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
redis-data: null
|
redis-data:
|
||||||
|
|
|
||||||
58
compose/services/vikunja/compose.yaml
Normal file
58
compose/services/vikunja/compose.yaml
Normal file
|
|
@ -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
|
||||||
|
|
@ -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://<the public ip or host where Vikunja is reachable>
|
|
||||||
VIKUNJA_DATABASE_HOST: db
|
|
||||||
VIKUNJA_DATABASE_PASSWORD: changeme
|
|
||||||
VIKUNJA_DATABASE_TYPE: postgres
|
|
||||||
VIKUNJA_DATABASE_USER: vikunja
|
|
||||||
VIKUNJA_DATABASE_DATABASE: vikunja
|
|
||||||
VIKUNJA_SERVICE_JWTSECRET: <a super secure random secret>
|
|
||||||
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
|
|
||||||
Loading…
Reference in a new issue