Merge pull request #3 from efigueroa/claude/gitops-home-services-011CUqEzDETA2BqAzYUcXtjt

Claude/gitops home services
This commit is contained in:
Eduardo Figueroa 2025-11-06 11:40:25 -08:00 committed by GitHub
commit 165c72818c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 4316 additions and 795 deletions

View file

@ -5,9 +5,13 @@ LLDAP_LDAP_BASE_DN=dc=fig,dc=systems
# Admin user configuration # Admin user configuration
LLDAP_LDAP_USER_DN=admin LLDAP_LDAP_USER_DN=admin
LLDAP_LDAP_USER_EMAIL=admin@edfig.dev LLDAP_LDAP_USER_EMAIL=admin@edfig.dev
# Use a strong password (at least 16 characters, mix of letters, numbers, symbols)
# Example format: MyS3cur3P@ssw0rd!2024#HomeL@b
LLDAP_LDAP_USER_PASS=changeme_please_set_secure_password LLDAP_LDAP_USER_PASS=changeme_please_set_secure_password
# JWT secret for session management (change this!) # JWT secret for session management (64+ character random string)
# Generate with: openssl rand -hex 32
# Example format: a1b2c3d4e5f67890abcdef1234567890a1b2c3d4e5f67890abcdef1234567890
LLDAP_JWT_SECRET=changeme_please_set_random_secret LLDAP_JWT_SECRET=changeme_please_set_random_secret
# Database URL (SQLite by default) # Database URL (SQLite by default)

View file

@ -10,6 +10,8 @@ TZ=America/Los_Angeles
LDAP_ADDRESS=ldap://lldap:3890 LDAP_ADDRESS=ldap://lldap:3890
LDAP_BASE_DN=dc=fig,dc=systems LDAP_BASE_DN=dc=fig,dc=systems
LDAP_BIND_DN=uid=admin,ou=people,dc=fig,dc=systems LDAP_BIND_DN=uid=admin,ou=people,dc=fig,dc=systems
# Must match LLDAP_LDAP_USER_PASS in lldap/.env
# Example format: MyS3cur3P@ssw0rd!2024#HomeL@b
LDAP_BIND_PASSWORD=changeme_please_set_secure_password LDAP_BIND_PASSWORD=changeme_please_set_secure_password
LDAP_SEARCH_FILTER=(uid=%s) LDAP_SEARCH_FILTER=(uid=%s)
LDAP_INSECURE=true LDAP_INSECURE=true
@ -20,6 +22,8 @@ LDAP_INSECURE=true
# USERS= # USERS=
# Session configuration # Session configuration
# Generate with: openssl rand -hex 32
# Example format: b2c3d4e5f67890abcdef1234567890a1b2c3d4e5f67890abcdef1234567890ab
SESSION_SECRET=changeme_please_set_random_session_secret SESSION_SECRET=changeme_please_set_random_session_secret
SESSION_MAX_AGE=86400 SESSION_MAX_AGE=86400

View file

@ -0,0 +1,11 @@
# qBittorrent Configuration
# User and Group IDs (run 'id' command to find yours)
PUID=1000
PGID=1000
# Timezone
TZ=America/Los_Angeles
# WebUI Port
WEBUI_PORT=8080

View file

@ -5,11 +5,8 @@ services:
qbittorrent: qbittorrent:
container_name: qbittorrent container_name: qbittorrent
image: lscr.io/linuxserver/qbittorrent:latest image: lscr.io/linuxserver/qbittorrent:latest
environment: env_file:
- PUID=1000 - .env
- PGID=1000
- TZ=America/Los_Angeles
- WEBUI_PORT=8080
volumes: volumes:
- ./config:/config - ./config:/config
- /media/downloads:/downloads - /media/downloads:/downloads

View file

@ -0,0 +1,8 @@
# Radarr Configuration
# User and Group IDs (run 'id' command to find yours)
PUID=1000
PGID=1000
# Timezone
TZ=America/Los_Angeles

View file

@ -5,10 +5,8 @@ services:
radarr: radarr:
container_name: radarr container_name: radarr
image: lscr.io/linuxserver/radarr:latest image: lscr.io/linuxserver/radarr:latest
environment: env_file:
- PUID=1000 - .env
- PGID=1000
- TZ=America/Los_Angeles
volumes: volumes:
- ./config:/config - ./config:/config
# Media library # Media library

View file

@ -0,0 +1,8 @@
# SABnzbd Configuration
# User and Group IDs (run 'id' command to find yours)
PUID=1000
PGID=1000
# Timezone
TZ=America/Los_Angeles

View file

@ -5,10 +5,8 @@ services:
sabnzbd: sabnzbd:
container_name: sabnzbd container_name: sabnzbd
image: lscr.io/linuxserver/sabnzbd:latest image: lscr.io/linuxserver/sabnzbd:latest
environment: env_file:
- PUID=1000 - .env
- PGID=1000
- TZ=America/Los_Angeles
volumes: volumes:
- ./config:/config - ./config:/config
- /media/downloads:/downloads - /media/downloads:/downloads

View file

@ -0,0 +1,8 @@
# Sonarr Configuration
# User and Group IDs (run 'id' command to find yours)
PUID=1000
PGID=1000
# Timezone
TZ=America/Los_Angeles

View file

@ -5,10 +5,8 @@ services:
sonarr: sonarr:
container_name: sonarr container_name: sonarr
image: lscr.io/linuxserver/sonarr:latest image: lscr.io/linuxserver/sonarr:latest
environment: env_file:
- PUID=1000 - .env
- PGID=1000
- TZ=America/Los_Angeles
volumes: volumes:
- ./config:/config - ./config:/config
# Media library # Media library

View file

@ -14,7 +14,9 @@ IMMICH_VERSION=V2.1.0
# Connection secret for postgres. You should change it to a random password # Connection secret for postgres. You should change it to a random password
# Please use only the characters `A-Za-z0-9`, without special characters or spaces # Please use only the characters `A-Za-z0-9`, without special characters or spaces
#DB_PASSWORD=postgres # Generate with: openssl rand -base64 32 | tr -d /=+ | cut -c1-32
# Example format: aB3dEf7HiJ9kLmN2oPqR5sTuV8wXyZ1
DB_PASSWORD=changeme_please_set_secure_password
# The values below this line do not need to be changed # The values below this line do not need to be changed
################################################################################### ###################################################################################

View file

@ -77,13 +77,8 @@ services:
database: database:
container_name: immich_postgres container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23 image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
environment: env_file:
POSTGRES_PASSWORD: ${DB_PASSWORD} - .env
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: '--data-checksums'
# Uncomment the DB_STORAGE_TYPE: 'HDD' var if your database isn't stored on SSDs
# DB_STORAGE_TYPE: 'HDD'
volumes: volumes:
# Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file # Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data - ${DB_DATA_LOCATION}:/var/lib/postgresql/data

View file

@ -0,0 +1,27 @@
# Jellyfin Configuration
# User and Group IDs (run 'id' command to find yours)
PUID=1000
PGID=1000
# Timezone
TZ=America/Los_Angeles
# Published server URL (for DLNA and discovery)
JELLYFIN_PublishedServerUrl=https://flix.fig.systems
# NVIDIA GPU Transcoding (for GTX 1070)
# Uncomment the lines below in compose.yaml to enable GPU transcoding:
# 1. Uncomment 'runtime: nvidia' line
# 2. Uncomment the 'deploy.resources.reservations.devices' section
#
# Prerequisites:
# - Install NVIDIA Container Toolkit on host:
# sudo apt install nvidia-container-toolkit
# sudo nvidia-ctk runtime configure --runtime=docker
# sudo systemctl restart docker
#
# - Verify GPU is available: docker run --rm --gpus all nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia-smi
#
# In Jellyfin UI after enabling:
# Dashboard → Playback → Transcoding → Hardware acceleration: NVIDIA NVENC

View file

@ -6,11 +6,8 @@ services:
jellyfin: jellyfin:
container_name: jellyfin container_name: jellyfin
image: lscr.io/linuxserver/jellyfin:latest image: lscr.io/linuxserver/jellyfin:latest
environment: env_file:
- PUID=1000 - .env
- PGID=1000
- TZ=America/Los_Angeles
- JELLYFIN_PublishedServerUrl=https://flix.fig.systems
volumes: volumes:
- ./config:/config - ./config:/config
- ./cache:/cache - ./cache:/cache
@ -35,7 +32,9 @@ services:
# Note: Jellyfin has its own auth system, SSO middleware disabled by default # 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) # Uncomment the line below to enable SSO (requires users to auth via tinyauth first)
# traefik.http.routers.jellyfin.middlewares: tinyauth # traefik.http.routers.jellyfin.middlewares: tinyauth
# Uncomment for NVIDIA GPU transcoding
# Uncomment for NVIDIA GPU transcoding (GTX 1070)
# Requires NVIDIA Container Toolkit installed on host
# runtime: nvidia # runtime: nvidia
# deploy: # deploy:
# resources: # resources:

View file

@ -0,0 +1,11 @@
# Jellyseerr Configuration
# Log Level (debug, info, warn, error)
LOG_LEVEL=info
# Timezone
TZ=America/Los_Angeles
# User and Group IDs
PUID=1000
PGID=1000

View file

@ -5,11 +5,8 @@ services:
jellyseerr: jellyseerr:
container_name: jellyseerr container_name: jellyseerr
image: fallenbagel/jellyseerr:latest image: fallenbagel/jellyseerr:latest
environment: env_file:
- LOG_LEVEL=info - .env
- TZ=America/Los_Angeles
- PUID=1000
- PGID=1000
volumes: volumes:
- ./config:/app/config - ./config:/app/config
restart: unless-stopped restart: unless-stopped

View file

@ -0,0 +1,8 @@
# FreshRSS Configuration
# Timezone
TZ=America/Los_Angeles
# User and Group IDs
PUID=1000
PGID=1000

View file

@ -5,23 +5,7 @@ services:
freshrss: freshrss:
container_name: freshrss container_name: freshrss
image: lscr.io/linuxserver/freshrss:latest 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: env_file:
homelab:
external: true - .env

View file

@ -1,6 +1,11 @@
# Backrest Configuration # Backrest Configuration
# Backrest provides a web UI for managing Restic backups # Backrest provides a web UI for managing Restic backups
# Application Settings
BACKREST_DATA=/data
BACKREST_CONFIG=/config/config.json
XDG_CACHE_HOME=/cache
# Timezone # Timezone
TZ=America/Los_Angeles TZ=America/Los_Angeles

View file

@ -15,11 +15,8 @@ services:
- /home/user/homelab/compose/media/frontend/immich/upload:/backups/immich:ro - /home/user/homelab/compose/media/frontend/immich/upload:/backups/immich:ro
- /home/user/homelab/compose:/backups/homelab-config:ro - /home/user/homelab/compose:/backups/homelab-config:ro
environment: env_file:
- BACKREST_DATA=/data - .env
- BACKREST_CONFIG=/config/config.json
- XDG_CACHE_HOME=/cache
- TZ=${TZ:-America/Los_Angeles}
labels: labels:
# Traefik # Traefik

View file

@ -0,0 +1,8 @@
# Booklore Configuration
# Timezone
TZ=America/Los_Angeles
# User and Group IDs
PUID=1000
PGID=1000

View file

@ -5,24 +5,7 @@ services:
booklore: booklore:
container_name: booklore container_name: booklore
image: ghcr.io/lorebooks/booklore:latest 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: env_file:
homelab:
external: true - .env

View file

@ -0,0 +1,11 @@
# Calibre-web Configuration
# Timezone
TZ=America/Los_Angeles
# User and Group IDs
PUID=1000
PGID=1000
# Docker mods (optional - for ebook conversion)
# DOCKER_MODS=linuxserver/mods:universal-calibre

View file

@ -5,26 +5,7 @@ services:
calibre-web: calibre-web:
container_name: calibre-web container_name: calibre-web
image: lscr.io/linuxserver/calibre-web:latest 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: env_file:
homelab:
external: true - .env

View file

@ -0,0 +1,8 @@
# File Browser Configuration
# Timezone
TZ=America/Los_Angeles
# User and Group IDs
PUID=1000
PGID=1000

View file

@ -5,25 +5,7 @@ services:
filebrowser: filebrowser:
container_name: filebrowser container_name: filebrowser
image: filebrowser/filebrowser:latest 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: env_file:
homelab:
external: true - .env

View file

@ -0,0 +1,14 @@
# Homarr Configuration
# Timezone
TZ=America/Los_Angeles
# Base path (if behind reverse proxy with path)
# BASE_URL=/dashboard
# Port (default: 7575)
PORT=7575
# Authentication
# AUTH_PROVIDER=oidc # For SSO integration
# DEFAULT_COLOR_SCHEME=dark

View file

@ -7,51 +7,6 @@ services:
container_name: homarr container_name: homarr
image: ghcr.io/ajnart/homarr:latest image: ghcr.io/ajnart/homarr:latest
environment: env_file:
# Timezone
- TZ=America/Los_Angeles
# Base path (if behind reverse proxy with path) - .env
# - BASE_URL=/dashboard
# Port (default: 7575)
- PORT=7575
# Authentication
# - AUTH_PROVIDER=oidc # For SSO integration
# - DEFAULT_COLOR_SCHEME=dark
volumes:
# Configuration and data
- ./config:/app/data/configs
- ./data:/data
- ./icons:/app/public/icons
# Docker socket for auto-discovery
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
networks:
- homelab
labels:
traefik.enable: true
# Web UI routing
traefik.http.routers.homarr.rule: Host(`home.fig.systems`) || Host(`home.edfig.dev`)
traefik.http.routers.homarr.entrypoints: websecure
traefik.http.routers.homarr.tls.certresolver: letsencrypt
traefik.http.services.homarr.loadbalancer.server.port: 7575
# SSO Protection (optional - dashboard may be public)
# traefik.http.routers.homarr.middlewares: tinyauth
# Homarr Labels for custom configuration
homarr.name: Homarr Dashboard
homarr.group: Infrastructure
homarr.icon: /icons/homarr.png
networks:
homelab:
external: true

View file

@ -1,473 +1,65 @@
NEXTAUTH_URL=http://localhost:3000/api/v1/auth # Linkwarden Configuration
NEXTAUTH_SECRET= # Docs: https://docs.linkwarden.app/self-hosting/environment-variables
# Manual installation database settings # NextAuth Configuration
# Example: DATABASE_URL=postgresql://user:password@localhost:5432/linkwarden NEXTAUTH_URL=https://links.fig.systems
DATABASE_URL= # Generate with: openssl rand -hex 32
# Example format: e4f5g6h789012abcdef345678901a2b3c4d5e6f78901abcdef2345678901abcde
# Docker installation database settings NEXTAUTH_SECRET=changeme_please_set_random_secret_key
POSTGRES_PASSWORD=
# Database Configuration
# Additional Optional Settings # Generate with: openssl rand -base64 32 | tr -d /=+ | cut -c1-32
PAGINATION_TAKE_COUNT= # Example format: eF7gH0iI3jK5lM8nO1pQ4rS7tU0vW3xY
STORAGE_FOLDER= POSTGRES_PASSWORD=changeme_please_set_secure_postgres_password
AUTOSCROLL_TIMEOUT= POSTGRES_USER=postgres
NEXT_PUBLIC_DISABLE_REGISTRATION= POSTGRES_DB=postgres
NEXT_PUBLIC_CREDENTIALS_ENABLED= DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@linkwarden-postgres:5432/postgres
DISABLE_NEW_SSO_USERS=
MAX_LINKS_PER_USER= # Meilisearch (search engine)
ARCHIVE_TAKE_COUNT= # Generate with: openssl rand -hex 16
BROWSER_TIMEOUT= # Example format: f6g7h8i901234abcdef567890a1b2c3d
IGNORE_UNAUTHORIZED_CA= MEILI_MASTER_KEY=changeme_please_set_meili_master_key
IGNORE_HTTPS_ERRORS=
IGNORE_URL_SIZE_LIMIT= # Timezone
NEXT_PUBLIC_DEMO= TZ=America/Los_Angeles
NEXT_PUBLIC_DEMO_USERNAME=
NEXT_PUBLIC_DEMO_PASSWORD= # Optional: Registration Control
NEXT_PUBLIC_ADMIN= # NEXT_PUBLIC_DISABLE_REGISTRATION=true
NEXT_PUBLIC_MAX_FILE_BUFFER=
PDF_MAX_BUFFER= # Optional: Credentials Authentication
SCREENSHOT_MAX_BUFFER= # NEXT_PUBLIC_CREDENTIALS_ENABLED=true
READABILITY_MAX_BUFFER=
PREVIEW_MAX_BUFFER= # Optional: Pagination
MONOLITH_MAX_BUFFER= # PAGINATION_TAKE_COUNT=20
MONOLITH_CUSTOM_OPTIONS=
IMPORT_LIMIT= # Optional: Storage folder (for screenshots/PDFs)
PLAYWRIGHT_LAUNCH_OPTIONS_EXECUTABLE_PATH= # STORAGE_FOLDER=data
PLAYWRIGHT_WS_URL=
MAX_WORKERS= # Optional: Limits
DISABLE_PRESERVATION= # MAX_LINKS_PER_USER=unlimited
NEXT_PUBLIC_RSS_POLLING_INTERVAL_MINUTES= # NEXT_PUBLIC_MAX_FILE_BUFFER=10485760 # 10MB in bytes
RSS_SUBSCRIPTION_LIMIT_PER_USER= # PDF_MAX_BUFFER=10485760
TEXT_CONTENT_LIMIT= # SCREENSHOT_MAX_BUFFER=10485760
SEARCH_FILTER_LIMIT=
INDEX_TAKE_COUNT= # Optional: Browser timeout for archiving (in milliseconds)
MEILI_TIMEOUT= # BROWSER_TIMEOUT=30000
# AUTOSCROLL_TIMEOUT=30
# AI Settings
NEXT_PUBLIC_OLLAMA_ENDPOINT_URL= # Optional: Archive settings
OLLAMA_MODEL= # ARCHIVE_TAKE_COUNT=5
# https://ai-sdk.dev/providers/openai-compatible-providers # Optional: Security
OPENAI_API_KEY= # IGNORE_UNAUTHORIZED_CA=false
OPENAI_MODEL= # IGNORE_HTTPS_ERRORS=false
# Optional: Set a custom OpenAI base URL and name (for third-party providers) # IGNORE_URL_SIZE_LIMIT=false
CUSTOM_OPENAI_BASE_URL=
CUSTOM_OPENAI_NAME= # Optional: SSO Settings
# DISABLE_NEW_SSO_USERS=false
# https://sdk.vercel.ai/providers/ai-sdk-providers/azure
AZURE_API_KEY= # Optional: Demo Mode
AZURE_RESOURCE_NAME= # NEXT_PUBLIC_DEMO=false
AZURE_MODEL= # NEXT_PUBLIC_DEMO_USERNAME=
# NEXT_PUBLIC_DEMO_PASSWORD=
# https://sdk.vercel.ai/providers/ai-sdk-providers/anthropic
ANTHROPIC_API_KEY= # Optional: Admin Panel
ANTHROPIC_MODEL= # NEXT_PUBLIC_ADMIN=false
# https://github.com/OpenRouterTeam/ai-sdk-provider
OPENROUTER_API_KEY=
OPENROUTER_MODEL=
# https://ai-sdk.dev/providers/ai-sdk-providers/perplexity
PERPLEXITY_API_KEY=
PERPLEXITY_MODEL=
# MeiliSearch Settings
MEILI_HOST=
MEILI_MASTER_KEY=
# AWS S3 Settings
SPACES_KEY=
SPACES_SECRET=
SPACES_ENDPOINT=
SPACES_BUCKET_NAME=
SPACES_REGION=
SPACES_FORCE_PATH_STYLE=
# SMTP Settings
NEXT_PUBLIC_EMAIL_PROVIDER=
EMAIL_FROM=
EMAIL_SERVER=
BASE_URL=
# Proxy settings
PROXY=
PROXY_USERNAME=
PROXY_PASSWORD=
PROXY_BYPASS=
# PDF archive settings
PDF_MARGIN_TOP=
PDF_MARGIN_BOTTOM=
#################
# SSO Providers #
#################
# 42 School
NEXT_PUBLIC_FORTYTWO_ENABLED=
FORTYTWO_CUSTOM_NAME=
FORTYTWO_CLIENT_ID=
FORTYTWO_CLIENT_SECRET=
# Apple
NEXT_PUBLIC_APPLE_ENABLED=
APPLE_CUSTOM_NAME=
APPLE_ID=
APPLE_SECRET=
# Atlassian
NEXT_PUBLIC_ATLASSIAN_ENABLED=
ATLASSIAN_CUSTOM_NAME=
ATLASSIAN_CLIENT_ID=
ATLASSIAN_CLIENT_SECRET=
ATLASSIAN_SCOPE=
# Auth0
NEXT_PUBLIC_AUTH0_ENABLED=
AUTH0_CUSTOM_NAME=
AUTH0_ISSUER=
AUTH0_CLIENT_SECRET=
AUTH0_CLIENT_ID=
# Authelia
NEXT_PUBLIC_AUTHELIA_ENABLED=""
AUTHELIA_CLIENT_ID=""
AUTHELIA_CLIENT_SECRET=""
AUTHELIA_WELLKNOWN_URL=""
# Authentik
NEXT_PUBLIC_AUTHENTIK_ENABLED=
AUTHENTIK_CUSTOM_NAME=
AUTHENTIK_ISSUER=
AUTHENTIK_CLIENT_ID=
AUTHENTIK_CLIENT_SECRET=
# Azure AD B2C
NEXT_PUBLIC_AZURE_AD_B2C_ENABLED=
AZURE_AD_B2C_TENANT_NAME=
AZURE_AD_B2C_CLIENT_ID=
AZURE_AD_B2C_CLIENT_SECRET=
AZURE_AD_B2C_PRIMARY_USER_FLOW=
# Azure AD
NEXT_PUBLIC_AZURE_AD_ENABLED=
AZURE_AD_CLIENT_ID=
AZURE_AD_CLIENT_SECRET=
AZURE_AD_TENANT_ID=
# Battle.net
NEXT_PUBLIC_BATTLENET_ENABLED=
BATTLENET_CUSTOM_NAME=
BATTLENET_CLIENT_ID=
BATTLENET_CLIENT_SECRET=
BATTLENET_ISSUER=
# Box
NEXT_PUBLIC_BOX_ENABLED=
BOX_CUSTOM_NAME=
BOX_CLIENT_ID=
BOX_CLIENT_SECRET=
# Bungie
NEXT_PUBLIC_BUNGIE_ENABLED=
BUNGIE_CUSTOM_NAME=
BUNGIE_CLIENT_ID=
BUNGIE_CLIENT_SECRET=
BUNGIE_API_KEY=
# Cognito
NEXT_PUBLIC_COGNITO_ENABLED=
COGNITO_CUSTOM_NAME=
COGNITO_CLIENT_ID=
COGNITO_CLIENT_SECRET=
COGNITO_ISSUER=
# Coinbase
NEXT_PUBLIC_COINBASE_ENABLED=
COINBASE_CUSTOM_NAME=
COINBASE_CLIENT_ID=
COINBASE_CLIENT_SECRET=
# Discord
NEXT_PUBLIC_DISCORD_ENABLED=
DISCORD_CUSTOM_NAME=
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
# Dropbox
NEXT_PUBLIC_DROPBOX_ENABLED=
DROPBOX_CUSTOM_NAME=
DROPBOX_CLIENT_ID=
DROPBOX_CLIENT_SECRET=
# DuendeIndentityServer6
NEXT_PUBLIC_DUENDE_IDS6_ENABLED=
DUENDE_IDS6_CUSTOM_NAME=
DUENDE_IDS6_CLIENT_ID=
DUENDE_IDS6_CLIENT_SECRET=
DUENDE_IDS6_ISSUER=
# EVE Online
NEXT_PUBLIC_EVEONLINE_ENABLED=
EVEONLINE_CUSTOM_NAME=
EVEONLINE_CLIENT_ID=
EVEONLINE_CLIENT_SECRET=
# Facebook
NEXT_PUBLIC_FACEBOOK_ENABLED=
FACEBOOK_CUSTOM_NAME=
FACEBOOK_CLIENT_ID=
FACEBOOK_CLIENT_SECRET=
# FACEIT
NEXT_PUBLIC_FACEIT_ENABLED=
FACEIT_CUSTOM_NAME=
FACEIT_CLIENT_ID=
FACEIT_CLIENT_SECRET=
# Foursquare
NEXT_PUBLIC_FOURSQUARE_ENABLED=
FOURSQUARE_CUSTOM_NAME=
FOURSQUARE_CLIENT_ID=
FOURSQUARE_CLIENT_SECRET=
FOURSQUARE_APIVERSION=
# Freshbooks
NEXT_PUBLIC_FRESHBOOKS_ENABLED=
FRESHBOOKS_CUSTOM_NAME=
FRESHBOOKS_CLIENT_ID=
FRESHBOOKS_CLIENT_SECRET=
# FusionAuth
NEXT_PUBLIC_FUSIONAUTH_ENABLED=
FUSIONAUTH_CUSTOM_NAME=
FUSIONAUTH_CLIENT_ID=
FUSIONAUTH_CLIENT_SECRET=
FUSIONAUTH_ISSUER=
FUSIONAUTH_TENANT_ID=
# GitHub
NEXT_PUBLIC_GITHUB_ENABLED=
GITHUB_CUSTOM_NAME=
GITHUB_ID=
GITHUB_SECRET=
# GitLab
NEXT_PUBLIC_GITLAB_ENABLED=
GITLAB_CUSTOM_NAME=
GITLAB_CLIENT_ID=
GITLAB_CLIENT_SECRET=
GITLAB_AUTH_URL=
# Google
NEXT_PUBLIC_GOOGLE_ENABLED=
GOOGLE_CUSTOM_NAME=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# HubSpot
NEXT_PUBLIC_HUBSPOT_ENABLED=
HUBSPOT_CUSTOM_NAME=
HUBSPOT_CLIENT_ID=
HUBSPOT_CLIENT_SECRET=
# IdentityServer4
NEXT_PUBLIC_IDS4_ENABLED=
IDS4_CUSTOM_NAME=
IDS4_CLIENT_ID=
IDS4_CLIENT_SECRET=
IDS4_ISSUER=
# Kakao
NEXT_PUBLIC_KAKAO_ENABLED=
KAKAO_CUSTOM_NAME=
KAKAO_CLIENT_ID=
KAKAO_CLIENT_SECRET=
# Keycloak
NEXT_PUBLIC_KEYCLOAK_ENABLED=
KEYCLOAK_CUSTOM_NAME=
KEYCLOAK_ISSUER=
KEYCLOAK_CLIENT_ID=
KEYCLOAK_CLIENT_SECRET=
# LINE
NEXT_PUBLIC_LINE_ENABLED=
LINE_CUSTOM_NAME=
LINE_CLIENT_ID=
LINE_CLIENT_SECRET=
# LinkedIn
NEXT_PUBLIC_LINKEDIN_ENABLED=
LINKEDIN_CUSTOM_NAME=
LINKEDIN_CLIENT_ID=
LINKEDIN_CLIENT_SECRET=
# Mailchimp
NEXT_PUBLIC_MAILCHIMP_ENABLED=
MAILCHIMP_CUSTOM_NAME=
MAILCHIMP_CLIENT_ID=
MAILCHIMP_CLIENT_SECRET=
# Mail.ru
NEXT_PUBLIC_MAILRU_ENABLED=
MAILRU_CUSTOM_NAME=
MAILRU_CLIENT_ID=
MAILRU_CLIENT_SECRET=
# Naver
NEXT_PUBLIC_NAVER_ENABLED=
NAVER_CUSTOM_NAME=
NAVER_CLIENT_ID=
NAVER_CLIENT_SECRET=
# Netlify
NEXT_PUBLIC_NETLIFY_ENABLED=
NETLIFY_CUSTOM_NAME=
NETLIFY_CLIENT_ID=
NETLIFY_CLIENT_SECRET=
# Okta
NEXT_PUBLIC_OKTA_ENABLED=
OKTA_CUSTOM_NAME=
OKTA_CLIENT_ID=
OKTA_CLIENT_SECRET=
OKTA_ISSUER=
# OneLogin
NEXT_PUBLIC_ONELOGIN_ENABLED=
ONELOGIN_CUSTOM_NAME=
ONELOGIN_CLIENT_ID=
ONELOGIN_CLIENT_SECRET=
ONELOGIN_ISSUER=
# Osso
NEXT_PUBLIC_OSSO_ENABLED=
OSSO_CUSTOM_NAME=
OSSO_CLIENT_ID=
OSSO_CLIENT_SECRET=
OSSO_ISSUER=
# osu!
NEXT_PUBLIC_OSU_ENABLED=
OSU_CUSTOM_NAME=
OSU_CLIENT_ID=
OSU_CLIENT_SECRET=
# Patreon
NEXT_PUBLIC_PATREON_ENABLED=
PATREON_CUSTOM_NAME=
PATREON_CLIENT_ID=
PATREON_CLIENT_SECRET=
# Pinterest
NEXT_PUBLIC_PINTEREST_ENABLED=
PINTEREST_CUSTOM_NAME=
PINTEREST_CLIENT_ID=
PINTEREST_CLIENT_SECRET=
# Pipedrive
NEXT_PUBLIC_PIPEDRIVE_ENABLED=
PIPEDRIVE_CUSTOM_NAME=
PIPEDRIVE_CLIENT_ID=
PIPEDRIVE_CLIENT_SECRET=
# Reddit
NEXT_PUBLIC_REDDIT_ENABLED=
REDDIT_CUSTOM_NAME=
REDDIT_CLIENT_ID=
REDDIT_CLIENT_SECRET=
# Salesforce
NEXT_PUBLIC_SALESFORCE_ENABLED=
SALESFORCE_CUSTOM_NAME=
SALESFORCE_CLIENT_ID=
SALESFORCE_CLIENT_SECRET=
# Slack
NEXT_PUBLIC_SLACK_ENABLED=
SLACK_CUSTOM_NAME=
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
# Spotify
NEXT_PUBLIC_SPOTIFY_ENABLED=
SPOTIFY_CUSTOM_NAME=
SPOTIFY_CLIENT_ID=
SPOTIFY_CLIENT_SECRET=
# Strava
NEXT_PUBLIC_STRAVA_ENABLED=
STRAVA_CUSTOM_NAME=
STRAVA_CLIENT_ID=
STRAVA_CLIENT_SECRET=
# Synology
NEXT_PUBLIC_SYNOLOGY_ENABLED=
SYNOLOGY_CUSTOM_NAME=
SYNOLOGY_CLIENT_ID=
SYNOLOGY_CLIENT_SECRET=
SYNOLOGY_WELLKNOWN_URL=
# Todoist
NEXT_PUBLIC_TODOIST_ENABLED=
TODOIST_CUSTOM_NAME=
TODOIST_CLIENT_ID=
TODOIST_CLIENT_SECRET=
# Twitch
NEXT_PUBLIC_TWITCH_ENABLED=
TWITCH_CUSTOM_NAME=
TWITCH_CLIENT_ID=
TWITCH_CLIENT_SECRET=
# United Effects
NEXT_PUBLIC_UNITED_EFFECTS_ENABLED=
UNITED_EFFECTS_CUSTOM_NAME=
UNITED_EFFECTS_CLIENT_ID=
UNITED_EFFECTS_CLIENT_SECRET=
UNITED_EFFECTS_ISSUER=
# VK
NEXT_PUBLIC_VK_ENABLED=
VK_CUSTOM_NAME=
VK_CLIENT_ID=
VK_CLIENT_SECRET=
# Wikimedia
NEXT_PUBLIC_WIKIMEDIA_ENABLED=
WIKIMEDIA_CUSTOM_NAME=
WIKIMEDIA_CLIENT_ID=
WIKIMEDIA_CLIENT_SECRET=
# Wordpress.com
NEXT_PUBLIC_WORDPRESS_ENABLED=
WORDPRESS_CUSTOM_NAME=
WORDPRESS_CLIENT_ID=
WORDPRESS_CLIENT_SECRET=
# Yandex
NEXT_PUBLIC_YANDEX_ENABLED=
YANDEX_CUSTOM_NAME=
YANDEX_CLIENT_ID=
YANDEX_CLIENT_SECRET=
# Zitadel
NEXT_PUBLIC_ZITADEL_ENABLED=
ZITADEL_CUSTOM_NAME=
ZITADEL_CLIENT_ID=
ZITADEL_CLIENT_SECRET=
ZITADEL_ISSUER=
# Zoho
NEXT_PUBLIC_ZOHO_ENABLED=
ZOHO_CUSTOM_NAME=
ZOHO_CLIENT_ID=
ZOHO_CLIENT_SECRET=
# Zoom
NEXT_PUBLIC_ZOOM_ENABLED=
ZOOM_CUSTOM_NAME=
ZOOM_CLIENT_ID=
ZOOM_CLIENT_SECRET=

View file

@ -6,9 +6,6 @@ services:
container_name: linkwarden container_name: linkwarden
image: ghcr.io/linkwarden/linkwarden:latest image: ghcr.io/linkwarden/linkwarden:latest
env_file: .env env_file: .env
environment:
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@linkwarden-postgres:5432/postgres
- TZ=America/Los_Angeles
volumes: volumes:
- ./data:/data/data - ./data:/data/data
depends_on: depends_on:
@ -31,8 +28,6 @@ services:
container_name: linkwarden-postgres container_name: linkwarden-postgres
image: postgres:16-alpine image: postgres:16-alpine
env_file: .env env_file: .env
environment:
- TZ=America/Los_Angeles
volumes: volumes:
- ./pgdata:/var/lib/postgresql/data - ./pgdata:/var/lib/postgresql/data
restart: always restart: always
@ -48,8 +43,6 @@ services:
container_name: linkwarden-meilisearch container_name: linkwarden-meilisearch
image: getmeili/meilisearch:v1.12.8 image: getmeili/meilisearch:v1.12.8
env_file: .env env_file: .env
environment:
- TZ=America/Los_Angeles
volumes: volumes:
- ./meili_data:/meili_data - ./meili_data:/meili_data
restart: always restart: always

View file

@ -0,0 +1,15 @@
# LubeLogger Configuration
# Timezone
TZ=America/Los_Angeles
# LC_ALL locale setting
LC_ALL=en_US.UTF-8
# LANG locale setting
LANG=en_US.UTF-8
# Enable OpenID (for SSO integration)
# ENABLE_OPENID=true
# OPENID_CLIENT_ID=your-client-id
# OPENID_CLIENT_SECRET=your-client-secret

View file

@ -5,26 +5,7 @@ services:
lubelogger: lubelogger:
container_name: lubelogger container_name: lubelogger
image: ghcr.io/hargata/lubelogger:latest 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: env_file:
homelab:
external: true
volumes: - .env
data:
keys:

View file

@ -6,49 +6,6 @@ services:
container_name: microbin container_name: microbin
image: danielszabo99/microbin:latest image: danielszabo99/microbin:latest
env_file: .env env_file: .env
environment:
MICROBIN_BASIC_AUTH_USERNAME: ${MICROBIN_BASIC_AUTH_USERNAME}
MICROBIN_BASIC_AUTH_PASSWORD: ${MICROBIN_BASIC_AUTH_PASSWORD}
MICROBIN_ADMIN_USERNAME: ${MICROBIN_ADMIN_USERNAME}
MICROBIN_ADMIN_PASSWORD: ${MICROBIN_ADMIN_PASSWORD}
MICROBIN_EDITABLE: ${MICROBIN_EDITABLE}
MICROBIN_FOOTER_TEXT: ${MICROBIN_FOOTER_TEXT}
MICROBIN_HIDE_FOOTER: ${MICROBIN_HIDE_FOOTER}
MICROBIN_HIDE_HEADER: ${MICROBIN_HIDE_HEADER}
MICROBIN_HIDE_LOGO: ${MICROBIN_HIDE_LOGO}
MICROBIN_NO_LISTING: ${MICROBIN_NO_LISTING}
MICROBIN_HIGHLIGHTSYNTAX: ${MICROBIN_HIGHLIGHTSYNTAX}
MICROBIN_BIND: ${MICROBIN_BIND}
MICROBIN_PRIVATE: ${MICROBIN_PRIVATE}
MICROBIN_PURE_HTML: ${MICROBIN_PURE_HTML}
MICROBIN_DATA_DIR: ${MICROBIN_DATA_DIR}
MICROBIN_JSON_DB: ${MICROBIN_JSON_DB}
MICROBIN_PUBLIC_PATH: ${MICROBIN_PUBLIC_PATH}
MICROBIN_SHORT_PATH: ${MICROBIN_SHORT_PATH}
MICROBIN_READONLY: ${MICROBIN_READONLY}
MICROBIN_UPLOADER_PASSWORD: ${MICROBIN_UPLOADER_PASSWORD}
MICROBIN_SHOW_READ_STATS: ${MICROBIN_SHOW_READ_STATS}
MICROBIN_TITLE: ${MICROBIN_TITLE}
MICROBIN_THREADS: ${MICROBIN_THREADS}
MICROBIN_GC_DAYS: ${MICROBIN_GC_DAYS}
MICROBIN_ENABLE_BURN_AFTER: ${MICROBIN_ENABLE_BURN_AFTER}
MICROBIN_DEFAULT_BURN_AFTER: ${MICROBIN_DEFAULT_BURN_AFTER}
MICROBIN_WIDE: ${MICROBIN_WIDE}
MICROBIN_QR: ${MICROBIN_QR}
MICROBIN_ETERNAL_PASTA: ${MICROBIN_ETERNAL_PASTA}
MICROBIN_ENABLE_READONLY: ${MICROBIN_ENABLE_READONLY}
MICROBIN_DEFAULT_EXPIRY: ${MICROBIN_DEFAULT_EXPIRY}
MICROBIN_NO_FILE_UPLOAD: ${MICROBIN_NO_FILE_UPLOAD}
MICROBIN_CUSTOM_CSS: ${MICROBIN_CUSTOM_CSS}
MICROBIN_HASH_IDS: ${MICROBIN_HASH_IDS}
MICROBIN_ENCRYPTION_CLIENT_SIDE: ${MICROBIN_ENCRYPTION_CLIENT_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_UNENCRYPTED_MB: ${MICROBIN_MAX_FILE_SIZE_UNENCRYPTED_MB}
volumes:
- ./microbin-data:/app/microbin_data
restart: always
networks:
- homelab - homelab
labels: labels:
traefik.enable: true traefik.enable: true

View file

@ -0,0 +1,23 @@
# RSSHub Configuration
# Node environment
NODE_ENV=production
# Cache type (memory or redis)
CACHE_TYPE=memory
# Cache expiration time in seconds (default: 5 minutes)
CACHE_EXPIRE=300
# Timezone
TZ=America/Los_Angeles
# Optional: Redis configuration (if using redis cache)
# CACHE_TYPE=redis
# REDIS_URL=redis://redis:6379/
# Optional: Access control
# ACCESS_KEY=your_access_key_here
# Optional: Logging
# LOGGER_LEVEL=info # debug, info, warn, error

View file

@ -6,71 +6,7 @@ services:
container_name: rsshub container_name: rsshub
# Using chromium-bundled image for full puppeteer support # Using chromium-bundled image for full puppeteer support
image: diygod/rsshub:chromium-bundled image: diygod/rsshub:chromium-bundled
environment:
NODE_ENV: production
CACHE_TYPE: redis
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:
- rsshub-redis
- rsshub-browserless
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:1200/healthz"]
interval: 30s
timeout: 10s
retries: 3
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: env_file:
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: - .env
container_name: rsshub-redis
image: redis:alpine
restart: always
networks:
- rsshub_internal
volumes:
- redis-data:/data
healthcheck:
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:

View file

@ -0,0 +1,28 @@
# Vikunja Configuration
# Public URL
VIKUNJA_SERVICE_PUBLICURL=https://tasks.fig.systems
# Database Configuration
VIKUNJA_DATABASE_HOST=vikunja-db
VIKUNJA_DATABASE_TYPE=postgres
VIKUNJA_DATABASE_USER=vikunja
VIKUNJA_DATABASE_DATABASE=vikunja
# Generate with: openssl rand -base64 32 | tr -d /=+ | cut -c1-32
# Example format: cD5eF8gH1jK3lM6nO9pQ2rS5tU8vW1xY
VIKUNJA_DATABASE_PASSWORD=changeme_please_set_secure_password
# JWT Secret for session management (64+ character random string)
# Generate with: openssl rand -hex 32
# Example format: c2d3e4f567890abcdef1234567890a1b2c3d4e5f67890abcdef1234567890abc
VIKUNJA_SERVICE_JWTSECRET=changeme_please_set_random_jwt_secret
# Timezone
TZ=America/Los_Angeles
# Database environment variables (for postgres container)
POSTGRES_USER=vikunja
POSTGRES_DB=vikunja
# Must match VIKUNJA_DATABASE_PASSWORD above
# Example format: cD5eF8gH1jK3lM6nO9pQ2rS5tU8vW1xY
POSTGRES_PASSWORD=changeme_please_set_secure_password

View file

@ -5,15 +5,8 @@ services:
vikunja: vikunja:
container_name: vikunja container_name: vikunja
image: vikunja/vikunja:latest image: vikunja/vikunja:latest
environment: env_file:
VIKUNJA_SERVICE_PUBLICURL: https://tasks.fig.systems - .env
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: volumes:
- ./files:/app/vikunja/files - ./files:/app/vikunja/files
depends_on: depends_on:
@ -35,11 +28,8 @@ services:
vikunja-db: vikunja-db:
container_name: vikunja-db container_name: vikunja-db
image: postgres:18 image: postgres:18
environment: env_file:
POSTGRES_PASSWORD: changeme_please_set_secure_password - .env
POSTGRES_USER: vikunja
POSTGRES_DB: vikunja
TZ: America/Los_Angeles
volumes: volumes:
- ./db:/var/lib/postgresql/data - ./db:/var/lib/postgresql/data
restart: unless-stopped restart: unless-stopped

92
docs/README.md Normal file
View file

@ -0,0 +1,92 @@
# Homelab Documentation
Welcome to the homelab documentation! This folder contains comprehensive guides for setting up, configuring, and maintaining your self-hosted services.
## 📚 Documentation Structure
### Quick Start
- [Getting Started](./getting-started.md) - First-time setup walkthrough
- [Quick Reference](./quick-reference.md) - Common commands and URLs
### Configuration
- [Environment Variables & Secrets](./guides/secrets-management.md) - How to configure secure secrets
- [DNS Configuration](./guides/dns-setup.md) - Setting up domain names
- [SSL/TLS Certificates](./guides/ssl-certificates.md) - Let's Encrypt configuration
- [GPU Acceleration](./guides/gpu-setup.md) - NVIDIA GPU setup for Jellyfin and Immich
### Services
- [Service Overview](./services/README.md) - All available services
- [SSO Configuration](./services/sso-setup.md) - Single Sign-On with LLDAP and Tinyauth
- [Media Stack](./services/media-stack.md) - Jellyfin, Sonarr, Radarr setup
- [Backup Solutions](./services/backup.md) - Backrest configuration
### Troubleshooting
- [Common Issues](./troubleshooting/common-issues.md) - Frequent problems and solutions
- [FAQ](./troubleshooting/faq.md) - Frequently asked questions
- [Debugging Guide](./troubleshooting/debugging.md) - How to diagnose problems
### Operations
- [Maintenance](./operations/maintenance.md) - Regular maintenance tasks
- [Updates](./operations/updates.md) - Updating services
- [Backups](./operations/backups.md) - Backup and restore procedures
- [Monitoring](./operations/monitoring.md) - Service monitoring
## 🚀 Quick Links
### First Time Setup
1. [Prerequisites](./getting-started.md#prerequisites)
2. [Configure Secrets](./guides/secrets-management.md)
3. [Setup DNS](./guides/dns-setup.md)
4. [Deploy Services](./getting-started.md#deployment)
### Common Tasks
- [Add a new service](./guides/adding-services.md)
- [Generate secure passwords](./guides/secrets-management.md#generating-secrets)
- [Enable GPU acceleration](./guides/gpu-setup.md)
- [Backup configuration](./operations/backups.md)
- [Update a service](./operations/updates.md)
### Troubleshooting
- [Service won't start](./troubleshooting/common-issues.md#service-wont-start)
- [SSL certificate errors](./troubleshooting/common-issues.md#ssl-errors)
- [SSO not working](./troubleshooting/common-issues.md#sso-issues)
- [Can't access service](./troubleshooting/common-issues.md#access-issues)
## 📖 Documentation Conventions
Throughout this documentation:
- `command` - Commands to run in terminal
- **Bold** - Important concepts or UI elements
- `https://service.fig.systems` - Example URLs
- ⚠️ - Warning or important note
- 💡 - Tip or helpful information
- ✅ - Verified working configuration
## 🔐 Security Notes
Before deploying to production:
1. ✅ Change all passwords in `.env` files
2. ✅ Configure DNS records
3. ✅ Verify SSL certificates are working
4. ✅ Enable backups
5. ✅ Review security settings
## 🆘 Getting Help
If you encounter issues:
1. Check [Common Issues](./troubleshooting/common-issues.md)
2. Review [FAQ](./troubleshooting/faq.md)
3. Check service logs: `docker compose logs servicename`
4. Review the [Debugging Guide](./troubleshooting/debugging.md)
## 📝 Contributing to Documentation
Found an error or have a suggestion? Documentation improvements are welcome!
- Keep guides clear and concise
- Include examples and code snippets
- Test all commands before documenting
- Update the table of contents when adding new files
## 🔄 Last Updated
This documentation is automatically maintained and reflects the current state of the homelab repository.

497
docs/getting-started.md Normal file
View file

@ -0,0 +1,497 @@
# Getting Started with Homelab
This guide will walk you through setting up your homelab from scratch.
## Prerequisites
### Hardware Requirements
- **Server/VM**: Linux server with Docker support
- **CPU**: 2+ cores recommended
- **RAM**: 8GB minimum, 16GB+ recommended
- **Storage**: 100GB+ for Docker containers and config
- **Optional GPU**: NVIDIA GPU for hardware transcoding (Jellyfin, Immich)
### Software Requirements
- **Operating System**: Ubuntu 22.04 or similar Linux distribution
- **Docker**: Version 24.0+
- **Docker Compose**: Version 2.20+
- **Git**: For cloning the repository
- **Domain Names**: `*.fig.systems` and `*.edfig.dev` (or your domains)
### Network Requirements
- **Ports**: 80 and 443 accessible from internet (for Let's Encrypt)
- **DNS**: Ability to create A records for your domains
- **Static IP**: Recommended for your homelab server
## Step 1: Prepare Your Server
### Install Docker and Docker Compose
```bash
# Update package index
sudo apt update
# Install dependencies
sudo apt install -y ca-certificates curl gnupg lsb-release
# Add Docker's official GPG key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Set up the repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Add your user to docker group (logout and login after this)
sudo usermod -aG docker $USER
# Verify installation
docker --version
docker compose version
```
### Create Media Directory Structure
```bash
# Create media folders
sudo mkdir -p /media/{audiobooks,books,comics,complete,downloads,homemovies,incomplete,movies,music,photos,tv}
# Set ownership (replace with your username)
sudo chown -R $(whoami):$(whoami) /media
# Verify structure
tree -L 1 /media
```
## Step 2: Clone the Repository
```bash
# Clone the repository
cd ~
git clone https://github.com/efigueroa/homelab.git
cd homelab
# Checkout the main branch
git checkout main # or your target branch
```
## Step 3: Configure DNS
You need to point your domains to your server's IP address.
### Option 1: Wildcard DNS (Recommended)
Add these A records to your DNS provider:
```
*.fig.systems A YOUR_SERVER_IP
*.edfig.dev A YOUR_SERVER_IP
```
### Option 2: Individual Records
Create A records for each service:
```
traefik.fig.systems A YOUR_SERVER_IP
lldap.fig.systems A YOUR_SERVER_IP
auth.fig.systems A YOUR_SERVER_IP
home.fig.systems A YOUR_SERVER_IP
backup.fig.systems A YOUR_SERVER_IP
flix.fig.systems A YOUR_SERVER_IP
photos.fig.systems A YOUR_SERVER_IP
# ... and so on for all services
```
### Verify DNS
Wait a few minutes for DNS propagation, then verify:
```bash
# Test DNS resolution
dig traefik.fig.systems +short
dig lldap.fig.systems +short
# Should return your server IP
```
## Step 4: Configure Environment Variables
Each service needs its environment variables configured with secure values.
### Generate Secure Secrets
Use these commands to generate secure values:
```bash
# For JWT secrets and session secrets (64 characters)
openssl rand -hex 32
# For passwords (32 alphanumeric characters)
openssl rand -base64 32 | tr -d /=+ | cut -c1-32
# For API keys (32 characters)
openssl rand -hex 16
```
### Update Core Services
**LLDAP** (`compose/core/lldap/.env`):
```bash
cd compose/core/lldap
nano .env
# Update these values:
LLDAP_LDAP_USER_PASS=<your-strong-password>
LLDAP_JWT_SECRET=<output-from-openssl-rand-hex-32>
```
**Tinyauth** (`compose/core/tinyauth/.env`):
```bash
cd ../tinyauth
nano .env
# Update these values (LDAP_BIND_PASSWORD must match LLDAP_LDAP_USER_PASS):
LDAP_BIND_PASSWORD=<same-as-LLDAP_LDAP_USER_PASS>
SESSION_SECRET=<output-from-openssl-rand-hex-32>
```
**Immich** (`compose/media/frontend/immich/.env`):
```bash
cd ../../media/frontend/immich
nano .env
# Update:
DB_PASSWORD=<output-from-openssl-rand-base64>
```
### Update All Other Services
Go through each service's `.env` file and replace all `changeme_*` values:
```bash
# Find all files that need updating
grep -r "changeme_" ~/homelab/compose
# Or update them individually
cd ~/homelab/compose/services/linkwarden
nano .env # Update NEXTAUTH_SECRET, POSTGRES_PASSWORD, MEILI_MASTER_KEY
cd ../vikunja
nano .env # Update VIKUNJA_DATABASE_PASSWORD, VIKUNJA_SERVICE_JWTSECRET, POSTGRES_PASSWORD
```
💡 **Tip**: Keep your secrets in a password manager!
See [Secrets Management Guide](./guides/secrets-management.md) for detailed instructions.
## Step 5: Create Docker Network
```bash
# Create the external homelab network
docker network create homelab
# Verify it was created
docker network ls | grep homelab
```
## Step 6: Deploy Services
Deploy services in order, starting with core infrastructure:
### Deploy Core Infrastructure
```bash
cd ~/homelab
# Deploy Traefik (reverse proxy)
cd compose/core/traefik
docker compose up -d
# Check logs to ensure it starts successfully
docker compose logs -f
# Wait for "Server configuration reloaded" message, then Ctrl+C
```
```bash
# Deploy LLDAP (user directory)
cd ../lldap
docker compose up -d
docker compose logs -f
# Access: https://lldap.fig.systems
# Default login: admin / <your LLDAP_LDAP_USER_PASS>
```
```bash
# Deploy Tinyauth (SSO)
cd ../tinyauth
docker compose up -d
docker compose logs -f
# Access: https://auth.fig.systems
```
### Create LLDAP Users
Before deploying other services, create your user in LLDAP:
1. Go to https://lldap.fig.systems
2. Login with admin credentials
3. Create your user:
- Username: `edfig` (or your choice)
- Email: `admin@edfig.dev`
- Password: strong password
- Add to `lldap_admin` group
### Deploy Media Services
```bash
cd ~/homelab/compose/media/frontend
# Jellyfin
cd jellyfin
docker compose up -d
# Access: https://flix.fig.systems
# Immich
cd ../immich
docker compose up -d
# Access: https://photos.fig.systems
# Jellyseerr
cd ../jellyseer
docker compose up -d
# Access: https://requests.fig.systems
```
```bash
# Media automation
cd ~/homelab/compose/media/automation
cd sonarr && docker compose up -d && cd ..
cd radarr && docker compose up -d && cd ..
cd sabnzbd && docker compose up -d && cd ..
cd qbittorrent && docker compose up -d && cd ..
```
### Deploy Utility Services
```bash
cd ~/homelab/compose/services
# Dashboard (start with this - it shows all your services!)
cd homarr && docker compose up -d && cd ..
# Access: https://home.fig.systems
# Backup manager
cd backrest && docker compose up -d && cd ..
# Access: https://backup.fig.systems
# Other services
cd linkwarden && docker compose up -d && cd ..
cd vikunja && docker compose up -d && cd ..
cd lubelogger && docker compose up -d && cd ..
cd calibre-web && docker compose up -d && cd ..
cd booklore && docker compose up -d && cd ..
cd FreshRSS && docker compose up -d && cd ..
cd rsshub && docker compose up -d && cd ..
cd microbin && docker compose up -d && cd ..
cd filebrowser && docker compose up -d && cd ..
```
### Quick Deploy All (Alternative)
If you've configured everything and want to deploy all at once:
```bash
cd ~/homelab
# Create a deployment script
cat > deploy-all.sh << 'SCRIPT'
#!/bin/bash
set -e
echo "Deploying homelab services..."
# Core
echo "==> Core Infrastructure"
cd compose/core/traefik && docker compose up -d && cd ../../..
sleep 5
cd compose/core/lldap && docker compose up -d && cd ../../..
sleep 5
cd compose/core/tinyauth && docker compose up -d && cd ../../..
# Media
echo "==> Media Services"
cd compose/media/frontend/immich && docker compose up -d && cd ../../../..
cd compose/media/frontend/jellyfin && docker compose up -d && cd ../../../..
cd compose/media/frontend/jellyseer && docker compose up -d && cd ../../../..
cd compose/media/automation/sonarr && docker compose up -d && cd ../../../..
cd compose/media/automation/radarr && docker compose up -d && cd ../../../..
cd compose/media/automation/sabnzbd && docker compose up -d && cd ../../../..
cd compose/media/automation/qbittorrent && docker compose up -d && cd ../../../..
# Utility
echo "==> Utility Services"
cd compose/services/homarr && docker compose up -d && cd ../..
cd compose/services/backrest && docker compose up -d && cd ../..
cd compose/services/linkwarden && docker compose up -d && cd ../..
cd compose/services/vikunja && docker compose up -d && cd ../..
cd compose/services/lubelogger && docker compose up -d && cd ../..
cd compose/services/calibre-web && docker compose up -d && cd ../..
cd compose/services/booklore && docker compose up -d && cd ../..
cd compose/services/FreshRSS && docker compose up -d && cd ../..
cd compose/services/rsshub && docker compose up -d && cd ../..
cd compose/services/microbin && docker compose up -d && cd ../..
cd compose/services/filebrowser && docker compose up -d && cd ../..
echo "==> Deployment Complete!"
echo "Access your dashboard at: https://home.fig.systems"
SCRIPT
chmod +x deploy-all.sh
./deploy-all.sh
```
## Step 7: Verify Deployment
### Check All Containers Are Running
```bash
# List all containers
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Check for any stopped containers
docker ps -a --filter "status=exited"
```
### Verify SSL Certificates
```bash
# Test SSL certificate
curl -I https://home.fig.systems
# Should show HTTP/2 200 and valid SSL cert
```
### Access Services
Visit your dashboard: **https://home.fig.systems**
This should show all your services with their status!
### Test SSO
1. Go to any SSO-protected service (e.g., https://tasks.fig.systems)
2. You should be redirected to https://auth.fig.systems
3. Login with your LLDAP credentials
4. You should be redirected back to the service
## Step 8: Initial Service Configuration
### Jellyfin Setup
1. Go to https://flix.fig.systems
2. Select language and create admin account
3. Add media libraries:
- Movies: `/media/movies`
- TV Shows: `/media/tv`
- Music: `/media/music`
- Photos: `/media/photos`
### Immich Setup
1. Go to https://photos.fig.systems
2. Create admin account
3. Upload some photos to test
4. Configure storage in Settings
### Sonarr/Radarr Setup
1. Go to https://sonarr.fig.systems and https://radarr.fig.systems
2. Complete initial setup wizard
3. Add indexers (for finding content)
4. Add download clients:
- SABnzbd: http://sabnzbd:8080
- qBittorrent: http://qbittorrent:8080
5. Configure root folders:
- Sonarr: `/media/tv`
- Radarr: `/media/movies`
### Jellyseerr Setup
1. Go to https://requests.fig.systems
2. Sign in with Jellyfin
3. Connect to Sonarr and Radarr
4. Configure user permissions
### Backrest Setup
1. Go to https://backup.fig.systems
2. Add Backblaze B2 repository (see [Backup Guide](./services/backup.md))
3. Create backup plan for Immich photos
4. Schedule automated backups
## Step 9: Optional Configurations
### Enable GPU Acceleration
If you have an NVIDIA GPU, see [GPU Setup Guide](./guides/gpu-setup.md).
### Configure Backups
See [Backup Operations Guide](./operations/backups.md).
### Add More Services
See [Adding Services Guide](./guides/adding-services.md).
## Next Steps
- ✅ [Set up automated backups](./operations/backups.md)
- ✅ [Configure monitoring](./operations/monitoring.md)
- ✅ [Review security settings](./guides/security.md)
- ✅ [Enable GPU acceleration](./guides/gpu-setup.md) (optional)
- ✅ [Configure media automation](./services/media-stack.md)
## Troubleshooting
If you encounter issues during setup, see:
- [Common Issues](./troubleshooting/common-issues.md)
- [FAQ](./troubleshooting/faq.md)
- [Debugging Guide](./troubleshooting/debugging.md)
## Quick Command Reference
```bash
# View all running containers
docker ps
# View logs for a service
cd compose/path/to/service
docker compose logs -f
# Restart a service
docker compose restart
# Stop a service
docker compose down
# Update and restart a service
docker compose pull
docker compose up -d
# View resource usage
docker stats
```
## Getting Help
- Check the [FAQ](./troubleshooting/faq.md)
- Review service-specific guides in [docs/services/](./services/)
- Check container logs for errors
- Verify DNS and SSL certificates
Welcome to your homelab! 🎉

725
docs/guides/gpu-setup.md Normal file
View file

@ -0,0 +1,725 @@
# NVIDIA GPU Acceleration Setup (GTX 1070)
This guide covers setting up NVIDIA GPU acceleration for your homelab running on **Proxmox 9 (Debian 13)** with an **NVIDIA GTX 1070**.
## Overview
GPU acceleration provides significant benefits:
- **Jellyfin**: Hardware video transcoding (H.264, HEVC)
- **Immich**: Faster ML inference (face recognition, object detection)
- **Performance**: 10-20x faster transcoding vs CPU
- **Efficiency**: Lower power consumption, CPU freed for other tasks
**Your Hardware:**
- **GPU**: NVIDIA GTX 1070 (Pascal architecture)
- **Capabilities**: NVENC (encoding), NVDEC (decoding), CUDA
- **Max Concurrent Streams**: 2 (can be unlocked)
- **Supported Codecs**: H.264, HEVC (H.265)
## Architecture Overview
```
Proxmox Host (Debian 13)
├─ NVIDIA Drivers (host)
├─ NVIDIA Container Toolkit
└─ Docker VM/LXC
├─ GPU passthrough
└─ Jellyfin/Immich containers
└─ Hardware transcoding
```
## Part 1: Proxmox Host Setup
### Step 1.1: Enable IOMMU (for GPU Passthrough)
**Edit GRUB configuration:**
```bash
# SSH into Proxmox host
ssh root@proxmox-host
# Edit GRUB config
nano /etc/default/grub
```
**Find this line:**
```
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
```
**Replace with (Intel CPU):**
```
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"
```
**Or (AMD CPU):**
```
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt"
```
**Update GRUB and reboot:**
```bash
update-grub
reboot
```
**Verify IOMMU is enabled:**
```bash
dmesg | grep -e DMAR -e IOMMU
# Should see: "IOMMU enabled"
```
### Step 1.2: Load VFIO Modules
**Edit modules:**
```bash
nano /etc/modules
```
**Add these lines:**
```
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
```
**Update initramfs:**
```bash
update-initramfs -u -k all
reboot
```
### Step 1.3: Find GPU PCI ID
```bash
lspci -nn | grep -i nvidia
# Example output:
# 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP104 [GeForce GTX 1070] [10de:1b81] (rev a1)
# 01:00.1 Audio device [0403]: NVIDIA Corporation GP104 High Definition Audio Controller [10de:10f0] (rev a1)
```
**Note the IDs**: `10de:1b81` and `10de:10f0` (your values may differ)
### Step 1.4: Configure VFIO
**Create VFIO config:**
```bash
nano /etc/modprobe.d/vfio.conf
```
**Add (replace with your IDs from above):**
```
options vfio-pci ids=10de:1b81,10de:10f0
softdep nvidia pre: vfio-pci
```
**Blacklist nouveau (open-source NVIDIA driver):**
```bash
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf
```
**Update and reboot:**
```bash
update-initramfs -u -k all
reboot
```
**Verify GPU is bound to VFIO:**
```bash
lspci -nnk -d 10de:1b81
# Should show:
# Kernel driver in use: vfio-pci
```
## Part 2: VM/LXC Setup
### Option A: Using VM (Recommended for Docker)
**Create Ubuntu 24.04 VM with GPU passthrough:**
1. **Create VM in Proxmox UI**:
- OS: Ubuntu 24.04 Server
- CPU: 4+ cores
- RAM: 16GB+
- Disk: 100GB+
2. **Add PCI Device** (GPU):
- Hardware → Add → PCI Device
- Device: Select your GTX 1070 (01:00.0)
- ✅ All Functions
- ✅ Primary GPU (if no other GPU)
- ✅ PCI-Express
3. **Add PCI Device** (GPU Audio):
- Hardware → Add → PCI Device
- Device: NVIDIA Audio (01:00.1)
- ✅ All Functions
4. **Machine Settings**:
- Machine: q35
- BIOS: OVMF (UEFI)
- Add EFI Disk
5. **Start VM** and install Ubuntu
### Option B: Using LXC (Advanced, Less Stable)
**Note**: LXC with GPU is less reliable. VM recommended.
If you insist on LXC:
```bash
# Edit LXC config
nano /etc/pve/lxc/VMID.conf
# Add:
lxc.cgroup2.devices.allow: c 195:* rwm
lxc.cgroup2.devices.allow: c 509:* rwm
lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file
```
**For this guide, we'll use VM (Option A)**.
## Part 3: VM Guest Setup (Debian 13)
Now we're inside the Ubuntu/Debian VM where Docker runs.
### Step 3.1: Install NVIDIA Drivers
**SSH into your Docker VM:**
```bash
ssh user@docker-vm
```
**Update system:**
```bash
sudo apt update
sudo apt upgrade -y
```
**Debian 13 - Install NVIDIA drivers:**
```bash
# Add non-free repositories
sudo nano /etc/apt/sources.list
# Add 'non-free non-free-firmware' to each line, example:
deb http://deb.debian.org/debian bookworm main non-free non-free-firmware
deb http://deb.debian.org/debian bookworm-updates main non-free non-free-firmware
# Update and install
sudo apt update
sudo apt install -y linux-headers-$(uname -r)
sudo apt install -y nvidia-driver nvidia-smi
# Reboot
sudo reboot
```
**Verify driver installation:**
```bash
nvidia-smi
# Should show:
# +-----------------------------------------------------------------------------+
# | NVIDIA-SMI 535.xx.xx Driver Version: 535.xx.xx CUDA Version: 12.2 |
# |-------------------------------+----------------------+----------------------+
# | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
# | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
# |===============================+======================+======================|
# | 0 NVIDIA GeForce ... Off | 00000000:01:00.0 Off | N/A |
# | 30% 35C P8 10W / 150W | 0MiB / 8192MiB | 0% Default |
# +-------------------------------+----------------------+----------------------+
```
**Success!** Your GTX 1070 is now accessible in the VM.
### Step 3.2: Install NVIDIA Container Toolkit
**Add NVIDIA Container Toolkit repository:**
```bash
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
```
**Install toolkit:**
```bash
sudo apt update
sudo apt install -y nvidia-container-toolkit
```
**Configure Docker to use NVIDIA runtime:**
```bash
sudo nvidia-ctk runtime configure --runtime=docker
```
**Restart Docker:**
```bash
sudo systemctl restart docker
```
**Verify Docker can access GPU:**
```bash
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi
# Should show nvidia-smi output from inside container
```
**Success!** Docker can now use your GPU.
## Part 4: Configure Jellyfin for GPU Transcoding
### Step 4.1: Update Jellyfin Compose File
**Edit compose file:**
```bash
cd ~/homelab/compose/media/frontend/jellyfin
nano compose.yaml
```
**Uncomment the GPU sections:**
```yaml
services:
jellyfin:
container_name: jellyfin
image: lscr.io/linuxserver/jellyfin:latest
env_file:
- .env
volumes:
- ./config:/config
- ./cache:/cache
- /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"
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
# UNCOMMENT THESE LINES FOR GTX 1070:
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
networks:
homelab:
external: true
```
**Restart Jellyfin:**
```bash
docker compose down
docker compose up -d
```
**Check logs:**
```bash
docker compose logs -f
# Should see lines about NVENC/CUDA being detected
```
### Step 4.2: Enable in Jellyfin UI
1. Go to https://flix.fig.systems
2. Dashboard → Playback → Transcoding
3. **Hardware acceleration**: NVIDIA NVENC
4. **Enable hardware decoding for**:
- ✅ H264
- ✅ HEVC
- ✅ VC1
- ✅ VP8
- ✅ MPEG2
5. **Enable hardware encoding**
6. **Enable encoding in HEVC format**
7. Save
### Step 4.3: Test Transcoding
1. Play a video in Jellyfin web UI
2. Click Settings (gear icon) → Quality
3. Select a lower bitrate to force transcoding
4. In another terminal:
```bash
nvidia-smi
# While video is transcoding, should see:
# GPU utilization: 20-40%
# Memory usage: 500-1000MB
```
**Success!** Jellyfin is using your GTX 1070!
## Part 5: Configure Immich for GPU Acceleration
Immich can use GPU for two purposes:
1. **ML Inference** (face recognition, object detection)
2. **Video Transcoding**
### Step 5.1: ML Inference (CUDA)
**Edit Immich compose file:**
```bash
cd ~/homelab/compose/media/frontend/immich
nano compose.yaml
```
**Change ML image to CUDA version:**
Find this line:
```yaml
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
```
Change to:
```yaml
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-cuda
```
**Add GPU support:**
```yaml
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-cuda
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
networks:
- immich_internal
# ADD THESE LINES:
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
```
### Step 5.2: Video Transcoding (NVENC)
**For video transcoding, add to immich-server:**
```yaml
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
# ... existing config ...
# ADD THESE LINES:
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
```
**Restart Immich:**
```bash
docker compose down
docker compose up -d
```
### Step 5.3: Enable in Immich UI
1. Go to https://photos.fig.systems
2. Administration → Settings → Video Transcoding
3. **Transcoding**: h264 (NVENC)
4. **Hardware Acceleration**: NVIDIA
5. Save
6. Administration → Settings → Machine Learning
7. **Facial Recognition**: Enabled
8. **Object Detection**: Enabled
9. Should automatically use CUDA
### Step 5.4: Test ML Inference
1. Upload photos with faces
2. In terminal:
```bash
nvidia-smi
# While processing, should see:
# GPU utilization: 50-80%
# Memory usage: 2-4GB
```
**Success!** Immich is using GPU for ML inference!
## Part 6: Performance Tuning
### GTX 1070 Specific Settings
**Jellyfin optimal settings:**
- Hardware acceleration: NVIDIA NVENC
- Target transcode bandwidth: Let clients decide
- Enable hardware encoding: Yes
- Prefer OS native DXVA or VA-API hardware decoders: No
- Allow encoding in HEVC format: Yes (GTX 1070 supports HEVC)
**Immich optimal settings:**
- Transcoding: h264 or hevc
- Target resolution: 1080p (for GTX 1070)
- CRF: 23 (good balance)
- Preset: fast
### Unlock NVENC Stream Limit
GTX 1070 is limited to 2 concurrent transcoding streams. You can unlock unlimited streams:
**Install patch:**
```bash
# Inside Docker VM
git clone https://github.com/keylase/nvidia-patch.git
cd nvidia-patch
sudo bash ./patch.sh
# Reboot
sudo reboot
```
**Verify:**
```bash
nvidia-smi
# Now supports unlimited concurrent streams
```
⚠️ **Note**: This is a hack that modifies NVIDIA driver. Use at your own risk.
### Monitor GPU Usage
**Real-time monitoring:**
```bash
watch -n 1 nvidia-smi
```
**Check GPU usage from Docker:**
```bash
docker stats $(docker ps --format '{{.Names}}' | grep -E 'jellyfin|immich')
```
## Troubleshooting
### GPU Not Detected in VM
**Check from Proxmox host:**
```bash
lspci | grep -i nvidia
```
**Check from VM:**
```bash
lspci | grep -i nvidia
nvidia-smi
```
**If not visible in VM:**
1. Verify IOMMU is enabled (`dmesg | grep IOMMU`)
2. Check PCI passthrough is configured correctly
3. Ensure VM is using q35 machine type
4. Verify BIOS is OVMF (UEFI)
### Docker Can't Access GPU
**Error**: `could not select device driver "" with capabilities: [[gpu]]`
**Fix:**
```bash
# Reconfigure NVIDIA runtime
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
# Test again
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi
```
### Jellyfin Shows "No Hardware Acceleration Available"
**Check:**
```bash
# Verify container has GPU access
docker exec jellyfin nvidia-smi
# Check Jellyfin logs
docker logs jellyfin | grep -i nvenc
```
**Fix:**
1. Ensure `runtime: nvidia` is uncommented
2. Verify `deploy.resources.reservations.devices` is configured
3. Restart container: `docker compose up -d`
### Transcoding Fails with "Failed to Open GPU"
**Check:**
```bash
# GPU might be busy
nvidia-smi
# Kill processes using GPU
sudo fuser -v /dev/nvidia*
```
### Low GPU Utilization During Transcoding
**Normal**: GTX 1070 is powerful. 20-40% utilization is expected for single stream.
**To max out GPU:**
- Transcode multiple streams simultaneously
- Use higher resolution source (4K)
- Enable HEVC encoding
## Performance Benchmarks (GTX 1070)
**Typical Performance:**
- **4K HEVC → 1080p H.264**: ~120-150 FPS (real-time)
- **1080p H.264 → 720p H.264**: ~300-400 FPS
- **Concurrent streams**: 4-6 (after unlocking limit)
- **Power draw**: 80-120W during transcoding
- **Temperature**: 55-65°C
**Compare to CPU (typical 4-core):**
- **4K HEVC → 1080p H.264**: ~10-15 FPS
- CPU would be at 100% utilization
- GPU: 10-15x faster!
## Monitoring and Maintenance
### Create GPU Monitoring Dashboard
**Install nvtop (nvidia-top):**
```bash
sudo apt install nvtop
```
**Run:**
```bash
nvtop
```
Shows real-time GPU usage, memory, temperature, processes.
### Check GPU Health
```bash
# Temperature
nvidia-smi --query-gpu=temperature.gpu --format=csv
# Memory usage
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
# Fan speed
nvidia-smi --query-gpu=fan.speed --format=csv
# Power draw
nvidia-smi --query-gpu=power.draw,power.limit --format=csv
```
### Automated Monitoring
Add to cron:
```bash
crontab -e
# Add:
*/5 * * * * nvidia-smi --query-gpu=utilization.gpu,memory.used,temperature.gpu --format=csv,noheader >> /var/log/gpu-stats.log
```
## Next Steps
✅ GPU is now configured for Jellyfin and Immich!
**Recommended:**
1. Test transcoding with various file formats
2. Upload photos to Immich and verify ML inference works
3. Monitor GPU temperature and utilization
4. Consider unlocking NVENC stream limit
5. Set up automated monitoring
**Optional:**
- Configure Tdarr for batch transcoding using GPU
- Set up Plex (also supports NVENC)
- Use GPU for other workloads (AI, rendering)
## Reference
### Quick Command Reference
```bash
# Check GPU from host (Proxmox)
lspci | grep -i nvidia
# Check GPU from VM
nvidia-smi
# Test Docker GPU access
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi
# Monitor GPU real-time
watch -n 1 nvidia-smi
# Check Jellyfin GPU usage
docker exec jellyfin nvidia-smi
# Restart Jellyfin with GPU
cd ~/homelab/compose/media/frontend/jellyfin
docker compose down && docker compose up -d
# View GPU processes
nvidia-smi pmon
# GPU temperature
nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader
```
### GTX 1070 Specifications
- **Architecture**: Pascal (GP104)
- **CUDA Cores**: 1920
- **Memory**: 8GB GDDR5
- **Memory Bandwidth**: 256 GB/s
- **TDP**: 150W
- **NVENC**: 6th generation (H.264, HEVC)
- **NVDEC**: 2nd generation
- **Concurrent Streams**: 2 (unlockable to unlimited)
---
**Your GTX 1070 is now accelerating your homelab! 🚀**

View file

@ -0,0 +1,567 @@
# Secrets and Environment Variables Management
This guide explains how to properly configure and manage secrets in your homelab.
## Overview
Every service uses environment variables stored in `.env` files for configuration. This approach:
- ✅ Keeps secrets out of version control
- ✅ Makes configuration changes easy
- ✅ Follows Docker Compose best practices
- ✅ Provides clear examples of what each secret should look like
## Finding What Needs Configuration
### Search for Placeholder Values
All secrets that need changing are marked with `changeme_`:
```bash
# Find all files with placeholder secrets
grep -r "changeme_" ~/homelab/compose
# Output shows exactly what needs updating:
compose/core/lldap/.env:LLDAP_LDAP_USER_PASS=changeme_please_set_secure_password
compose/core/lldap/.env:LLDAP_JWT_SECRET=changeme_please_set_random_secret
compose/core/tinyauth/.env:LDAP_BIND_PASSWORD=changeme_please_set_secure_password
...
```
### Count What's Left to Configure
```bash
# Count how many secrets still need updating
grep -r "changeme_" ~/homelab/compose | wc -l
# Goal: 0
```
## Generating Secrets
Each `.env` file includes comments showing:
1. What the secret is for
2. How to generate it
3. What format it should be in
### Common Secret Types
#### 1. JWT Secrets (64 characters)
**Used by**: LLDAP, Vikunja, NextAuth
**Generate:**
```bash
openssl rand -hex 32
```
**Example output:**
```
a1b2c3d4e5f67890abcdef1234567890a1b2c3d4e5f67890abcdef1234567890
```
**Where to use:**
- `LLDAP_JWT_SECRET`
- `VIKUNJA_SERVICE_JWTSECRET`
- `NEXTAUTH_SECRET`
- `SESSION_SECRET`
#### 2. Database Passwords (32 alphanumeric)
**Used by**: Postgres, Immich, Vikunja, Linkwarden
**Generate:**
```bash
openssl rand -base64 32 | tr -d /=+ | cut -c1-32
```
**Example output:**
```
aB3dEf7HiJ9kLmN2oPqR5sTuV8wXyZ1
```
**Where to use:**
- `DB_PASSWORD` (Immich)
- `POSTGRES_PASSWORD` (Vikunja, Linkwarden)
- `VIKUNJA_DATABASE_PASSWORD`
#### 3. Strong Passwords (16+ characters, mixed)
**Used by**: LLDAP admin, service admin accounts
**Generate:**
```bash
# Option 1: Using pwgen (install: apt install pwgen)
pwgen -s 20 1
# Option 2: Using openssl
openssl rand -base64 20 | tr -d /=+
# Option 3: Manual (recommended for main admin password)
# Create something memorable but strong
# Example format: MyS3cur3P@ssw0rd!2024#HomeL@b
```
**Where to use:**
- `LLDAP_LDAP_USER_PASS`
- `LDAP_BIND_PASSWORD` (must match LLDAP_LDAP_USER_PASS!)
#### 4. API Keys / Master Keys (32 characters)
**Used by**: Meilisearch, various APIs
**Generate:**
```bash
openssl rand -hex 16
```
**Example output:**
```
f6g7h8i901234abcdef567890a1b2c3d
```
**Where to use:**
- `MEILI_MASTER_KEY`
## Service-Specific Configuration
### Core Services
#### LLDAP (`compose/core/lldap/.env`)
```bash
# Edit the file
cd ~/homelab/compose/core/lldap
nano .env
```
**Required secrets:**
```env
# Admin password - use a STRONG password you'll remember
# Example: MyS3cur3P@ssw0rd!2024#HomeL@b
LLDAP_LDAP_USER_PASS=changeme_please_set_secure_password
# JWT secret - generate with: openssl rand -hex 32
# Example: a1b2c3d4e5f67890abcdef1234567890a1b2c3d4e5f67890abcdef1234567890
LLDAP_JWT_SECRET=changeme_please_set_random_secret
```
**Generate and update:**
```bash
# Generate JWT secret
echo "LLDAP_JWT_SECRET=$(openssl rand -hex 32)"
# Choose a strong password for LLDAP_LDAP_USER_PASS
# Write it down - you'll need it for Tinyauth too!
```
#### Tinyauth (`compose/core/tinyauth/.env`)
```bash
cd ~/homelab/compose/core/tinyauth
nano .env
```
**Required secrets:**
```env
# MUST match LLDAP_LDAP_USER_PASS from lldap/.env
LDAP_BIND_PASSWORD=changeme_please_set_secure_password
# Session secret - generate with: openssl rand -hex 32
SESSION_SECRET=changeme_please_set_random_session_secret
```
**⚠️ CRITICAL**: `LDAP_BIND_PASSWORD` must exactly match `LLDAP_LDAP_USER_PASS`!
```bash
# Generate session secret
echo "SESSION_SECRET=$(openssl rand -hex 32)"
```
### Media Services
#### Immich (`compose/media/frontend/immich/.env`)
```bash
cd ~/homelab/compose/media/frontend/immich
nano .env
```
**Required secrets:**
```env
# Database password - generate with: openssl rand -base64 32 | tr -d /=+ | cut -c1-32
DB_PASSWORD=changeme_please_set_secure_password
```
```bash
# Generate
echo "DB_PASSWORD=$(openssl rand -base64 32 | tr -d /=+ | cut -c1-32)"
```
### Utility Services
#### Linkwarden (`compose/services/linkwarden/.env`)
```bash
cd ~/homelab/compose/services/linkwarden
nano .env
```
**Required secrets:**
```env
# NextAuth secret - generate with: openssl rand -hex 32
NEXTAUTH_SECRET=changeme_please_set_random_secret_key
# Postgres password - generate with: openssl rand -base64 32 | tr -d /=+ | cut -c1-32
POSTGRES_PASSWORD=changeme_please_set_secure_postgres_password
# Meilisearch master key - generate with: openssl rand -hex 16
MEILI_MASTER_KEY=changeme_please_set_meili_master_key
```
```bash
# Generate all three
echo "NEXTAUTH_SECRET=$(openssl rand -hex 32)"
echo "POSTGRES_PASSWORD=$(openssl rand -base64 32 | tr -d /=+ | cut -c1-32)"
echo "MEILI_MASTER_KEY=$(openssl rand -hex 16)"
```
#### Vikunja (`compose/services/vikunja/.env`)
```bash
cd ~/homelab/compose/services/vikunja
nano .env
```
**Required secrets:**
```env
# Database password (used in two places - must match!)
VIKUNJA_DATABASE_PASSWORD=changeme_please_set_secure_password
POSTGRES_PASSWORD=changeme_please_set_secure_password # Same value!
# JWT secret - generate with: openssl rand -hex 32
VIKUNJA_SERVICE_JWTSECRET=changeme_please_set_random_jwt_secret
```
**⚠️ CRITICAL**: Both password fields must match!
```bash
# Generate
DB_PASS=$(openssl rand -base64 32 | tr -d /=+ | cut -c1-32)
echo "VIKUNJA_DATABASE_PASSWORD=$DB_PASS"
echo "POSTGRES_PASSWORD=$DB_PASS"
echo "VIKUNJA_SERVICE_JWTSECRET=$(openssl rand -hex 32)"
```
## Automated Configuration Script
Create a script to generate all secrets at once:
```bash
#!/bin/bash
# save as: ~/homelab/generate-secrets.sh
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${YELLOW}Homelab Secrets Generator${NC}\n"
echo "This script will help you generate secure secrets for your homelab."
echo "You'll need to manually copy these values into the respective .env files."
echo ""
# LLDAP
echo -e "${GREEN}=== LLDAP (compose/core/lldap/.env) ===${NC}"
echo "LLDAP_JWT_SECRET=$(openssl rand -hex 32)"
echo "LLDAP_LDAP_USER_PASS=<choose-a-strong-password-manually>"
echo ""
# Tinyauth
echo -e "${GREEN}=== Tinyauth (compose/core/tinyauth/.env) ===${NC}"
echo "LDAP_BIND_PASSWORD=<same-as-LLDAP_LDAP_USER_PASS-above>"
echo "SESSION_SECRET=$(openssl rand -hex 32)"
echo ""
# Immich
echo -e "${GREEN}=== Immich (compose/media/frontend/immich/.env) ===${NC}"
echo "DB_PASSWORD=$(openssl rand -base64 32 | tr -d /=+ | cut -c1-32)"
echo ""
# Linkwarden
echo -e "${GREEN}=== Linkwarden (compose/services/linkwarden/.env) ===${NC}"
echo "NEXTAUTH_SECRET=$(openssl rand -hex 32)"
echo "POSTGRES_PASSWORD=$(openssl rand -base64 32 | tr -d /=+ | cut -c1-32)"
echo "MEILI_MASTER_KEY=$(openssl rand -hex 16)"
echo ""
# Vikunja
VIKUNJA_PASS=$(openssl rand -base64 32 | tr -d /=+ | cut -c1-32)
echo -e "${GREEN}=== Vikunja (compose/services/vikunja/.env) ===${NC}"
echo "VIKUNJA_DATABASE_PASSWORD=$VIKUNJA_PASS"
echo "POSTGRES_PASSWORD=$VIKUNJA_PASS # Must match above!"
echo "VIKUNJA_SERVICE_JWTSECRET=$(openssl rand -hex 32)"
echo ""
echo -e "${YELLOW}Done! Copy these values into your .env files.${NC}"
echo ""
echo "Don't forget to:"
echo "1. Choose a strong LLDAP_LDAP_USER_PASS manually"
echo "2. Use the same password for LDAP_BIND_PASSWORD in tinyauth"
echo "3. Save all secrets in a password manager"
```
**Usage:**
```bash
chmod +x ~/homelab/generate-secrets.sh
~/homelab/generate-secrets.sh > secrets.txt
# Review and copy secrets
cat secrets.txt
# Keep this file safe or delete after copying to .env files
```
## Security Best Practices
### 1. Use a Password Manager
Store all secrets in a password manager:
- **1Password**: Great for teams
- **Bitwarden**: Self-hostable option
- **KeePassXC**: Offline, open-source
Create an entry for each service with:
- Service name
- URL
- All secrets from `.env` file
- Admin credentials
### 2. Never Commit Secrets
The repository `.gitignore` already excludes `.env` files, but double-check:
```bash
# Verify .env files are ignored
git status
# Should NOT show any .env files
```
### 3. Backup Your Secrets
```bash
# Create encrypted backup of all .env files
cd ~/homelab
tar czf env-backup-$(date +%Y%m%d).tar.gz $(find compose -name ".env")
# Encrypt with GPG
gpg -c env-backup-$(date +%Y%m%d).tar.gz
# Store encrypted file safely
mv env-backup-*.tar.gz.gpg ~/backups/
# Delete unencrypted tar
rm env-backup-*.tar.gz
```
### 4. Rotate Secrets Regularly
Change critical secrets periodically:
- **Admin passwords**: Every 90 days
- **JWT secrets**: Every 180 days
- **Database passwords**: When personnel changes
### 5. Limit Secret Access
- Don't share raw secrets over email/chat
- Use password manager's sharing features
- Delete shared secrets when no longer needed
## Verification
### Check All Secrets Are Set
```bash
# Should return 0 (no changeme_ values left)
grep -r "changeme_" ~/homelab/compose | wc -l
```
### Test Service Startup
```bash
# Start a service and check for password errors
cd ~/homelab/compose/core/lldap
docker compose up -d
docker compose logs
# Should NOT see:
# - "invalid password"
# - "authentication failed"
# - "secret not set"
```
### Verify SSO Works
1. Start LLDAP and Tinyauth
2. Access protected service (e.g., https://tasks.fig.systems)
3. Should redirect to auth.fig.systems
4. Login with LLDAP credentials
5. Should redirect back to service
If this works, your LLDAP ↔ Tinyauth passwords match! ✅
## Common Mistakes
### ❌ Using Weak Passwords
**Don't:**
```env
LLDAP_LDAP_USER_PASS=password123
```
**Do:**
```env
LLDAP_LDAP_USER_PASS=MyS3cur3P@ssw0rd!2024#HomeL@b
```
### ❌ Mismatched Passwords
**Don't:**
```env
# In lldap/.env
LLDAP_LDAP_USER_PASS=password1
# In tinyauth/.env
LDAP_BIND_PASSWORD=password2 # Different!
```
**Do:**
```env
# In lldap/.env
LLDAP_LDAP_USER_PASS=MyS3cur3P@ssw0rd!2024#HomeL@b
# In tinyauth/.env
LDAP_BIND_PASSWORD=MyS3cur3P@ssw0rd!2024#HomeL@b # Same!
```
### ❌ Using Same Secret Everywhere
**Don't:**
```env
# Same secret in multiple places
LLDAP_JWT_SECRET=abc123
NEXTAUTH_SECRET=abc123
SESSION_SECRET=abc123
```
**Do:**
```env
# Unique secret for each
LLDAP_JWT_SECRET=a1b2c3d4e5f67890...
NEXTAUTH_SECRET=f6g7h8i9j0k1l2m3...
SESSION_SECRET=x9y8z7w6v5u4t3s2...
```
### ❌ Forgetting to Update Both Password Fields
In Vikunja `.env`, both must match:
```env
# Both must be the same!
VIKUNJA_DATABASE_PASSWORD=aB3dEf7HiJ9kLmN2oPqR5sTuV8wXyZ1
POSTGRES_PASSWORD=aB3dEf7HiJ9kLmN2oPqR5sTuV8wXyZ1
```
## Troubleshooting
### "Authentication failed" in Tinyauth
**Cause**: LDAP_BIND_PASSWORD doesn't match LLDAP_LDAP_USER_PASS
**Fix**:
```bash
# Check LLDAP password
grep LLDAP_LDAP_USER_PASS ~/homelab/compose/core/lldap/.env
# Check Tinyauth password
grep LDAP_BIND_PASSWORD ~/homelab/compose/core/tinyauth/.env
# They should be identical!
```
### "Invalid JWT" errors
**Cause**: JWT_SECRET is too short or invalid format
**Fix**:
```bash
# Regenerate with proper length
openssl rand -hex 32
# Update in .env file
```
### "Database connection failed"
**Cause**: Database password mismatch
**Fix**:
```bash
# Check both password fields match
grep -E "(POSTGRES_PASSWORD|DATABASE_PASSWORD)" compose/services/vikunja/.env
# Both should be identical
```
## Next Steps
Once all secrets are configured:
1. ✅ [Deploy services](../getting-started.md#step-6-deploy-services)
2. ✅ [Configure SSO](../services/sso-setup.md)
3. ✅ [Set up backups](../operations/backups.md)
4. ✅ Store secrets in password manager
5. ✅ Create encrypted backup of .env files
## Reference
### Quick Command Reference
```bash
# Generate 64-char hex
openssl rand -hex 32
# Generate 32-char password
openssl rand -base64 32 | tr -d /=+ | cut -c1-32
# Generate 32-char hex
openssl rand -hex 16
# Find all changeme_ values
grep -r "changeme_" compose/
# Count remaining secrets to configure
grep -r "changeme_" compose/ | wc -l
# Backup all .env files (encrypted)
tar czf env-files.tar.gz $(find compose -name ".env")
gpg -c env-files.tar.gz
```
### Secret Types Quick Reference
| Secret Type | Command | Example Length | Used By |
|-------------|---------|----------------|---------|
| JWT Secret | `openssl rand -hex 32` | 64 chars | LLDAP, Vikunja, NextAuth |
| Session Secret | `openssl rand -hex 32` | 64 chars | Tinyauth |
| DB Password | `openssl rand -base64 32 \| tr -d /=+ \| cut -c1-32` | 32 chars | Postgres, Immich |
| API Key | `openssl rand -hex 16` | 32 chars | Meilisearch |
| Admin Password | Manual | 16+ chars | LLDAP admin |
---
**Remember**: Strong, unique secrets are your first line of defense. Take the time to generate them properly! 🔐

567
docs/quick-reference.md Normal file
View file

@ -0,0 +1,567 @@
# Quick Reference Guide
Fast reference for common tasks and commands.
## Service URLs
All services accessible via:
- Primary domain: `*.fig.systems`
- Secondary domain: `*.edfig.dev`
### Core Services
```
https://traefik.fig.systems # Reverse proxy dashboard
https://lldap.fig.systems # User directory
https://auth.fig.systems # SSO authentication
```
### Dashboard & Management
```
https://home.fig.systems # Homarr dashboard (START HERE!)
https://backup.fig.systems # Backrest backup manager
```
### Media Services
```
https://flix.fig.systems # Jellyfin media server
https://photos.fig.systems # Immich photo library
https://requests.fig.systems # Jellyseerr media requests
https://sonarr.fig.systems # TV show automation
https://radarr.fig.systems # Movie automation
https://sabnzbd.fig.systems # Usenet downloader
https://qbt.fig.systems # qBittorrent client
```
### Utility Services
```
https://links.fig.systems # Linkwarden bookmarks
https://tasks.fig.systems # Vikunja task management
https://garage.fig.systems # LubeLogger vehicle tracking
https://books.fig.systems # Calibre-web ebook library
https://booklore.fig.systems # Book tracking
https://rss.fig.systems # FreshRSS reader
https://files.fig.systems # File Browser
```
## Common Commands
### Docker Compose
```bash
# Start service
cd ~/homelab/compose/path/to/service
docker compose up -d
# View logs
docker compose logs -f
# Restart service
docker compose restart
# Stop service
docker compose down
# Update and restart
docker compose pull
docker compose up -d
# Rebuild service
docker compose up -d --force-recreate
```
### Docker Management
```bash
# List all containers
docker ps
# List all containers (including stopped)
docker ps -a
# View logs
docker logs <container_name>
docker logs -f <container_name> # Follow logs
# Execute command in container
docker exec -it <container_name> bash
# View resource usage
docker stats
# Remove stopped containers
docker container prune
# Remove unused images
docker image prune -a
# Remove unused volumes (CAREFUL!)
docker volume prune
# Complete cleanup
docker system prune -a --volumes
```
### Service Management
```bash
# Start all core services
cd ~/homelab/compose/core
for dir in traefik lldap tinyauth; do
cd $dir && docker compose up -d && cd ..
done
# Stop all services
cd ~/homelab
find compose -name "compose.yaml" -execdir docker compose down \;
# Restart single service
cd ~/homelab/compose/services/servicename
docker compose restart
# View all running containers
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
```
### System Checks
```bash
# Check all containers
docker ps --format "table {{.Names}}\t{{.Status}}"
# Check network
docker network inspect homelab
# Check disk usage
docker system df
df -h
# Check logs for errors
docker compose logs --tail=100 | grep -i error
# Test DNS resolution
dig home.fig.systems +short
# Test SSL
curl -I https://home.fig.systems
```
## Secret Generation
```bash
# JWT/Session secrets (64 char)
openssl rand -hex 32
# Database passwords (32 char alphanumeric)
openssl rand -base64 32 | tr -d /=+ | cut -c1-32
# API keys (32 char hex)
openssl rand -hex 16
# Find what needs updating
grep -r "changeme_" ~/homelab/compose
```
## Troubleshooting
### Service Won't Start
```bash
# Check logs
docker compose logs
# Check container status
docker compose ps
# Check for port conflicts
sudo netstat -tulpn | grep :80
sudo netstat -tulpn | grep :443
# Recreate container
docker compose down
docker compose up -d
```
### SSL Certificate Issues
```bash
# Check Traefik logs
docker logs traefik | grep -i certificate
# Check Let's Encrypt logs
docker logs traefik | grep -i letsencrypt
# Verify DNS
dig home.fig.systems +short
# Test port 80 accessibility
curl -I http://home.fig.systems
```
### SSO Not Working
```bash
# Check LLDAP
docker logs lldap
# Check Tinyauth
docker logs tinyauth
# Verify passwords match
grep LLDAP_LDAP_USER_PASS ~/homelab/compose/core/lldap/.env
grep LDAP_BIND_PASSWORD ~/homelab/compose/core/tinyauth/.env
# Test LDAP connection
docker exec tinyauth nc -zv lldap 3890
```
### Database Connection Failures
```bash
# Check database container
docker ps | grep postgres
# View database logs
docker logs <db_container_name>
# Test connection from app container
docker exec <app_container> nc -zv <db_container> 5432
# Verify password in .env
cat .env | grep POSTGRES_PASSWORD
```
## File Locations
### Configuration
```
~/homelab/compose/ # All services
~/homelab/compose/core/ # Core infrastructure
~/homelab/compose/media/ # Media services
~/homelab/compose/services/ # Utility services
```
### Service Data
```
compose/<service>/config/ # Service configuration
compose/<service>/data/ # Service data
compose/<service>/db/ # Database files
compose/<service>/.env # Environment variables
```
### Media Files
```
/media/movies/ # Movies
/media/tv/ # TV shows
/media/music/ # Music
/media/photos/ # Photos
/media/books/ # Books
/media/downloads/ # Active downloads
/media/complete/ # Completed downloads
```
### Logs
```
docker logs <container_name> # Container logs
compose/<service>/logs/ # Service-specific logs (if configured)
/var/lib/docker/volumes/ # Volume data
```
## Network
### Create Network
```bash
docker network create homelab
```
### Inspect Network
```bash
docker network inspect homelab
```
### Connect Container to Network
```bash
docker network connect homelab <container_name>
```
## GPU (NVIDIA GTX 1070)
### Check GPU Status
```bash
nvidia-smi
```
### Test GPU in Docker
```bash
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi
```
### Monitor GPU Usage
```bash
watch -n 1 nvidia-smi
```
### Check GPU in Container
```bash
docker exec jellyfin nvidia-smi
docker exec immich_machine_learning nvidia-smi
```
## Backup
### Backup Configuration Files
```bash
cd ~/homelab
tar czf homelab-config-$(date +%Y%m%d).tar.gz \
$(find compose -name ".env") \
$(find compose -name "compose.yaml")
```
### Backup Service Data
```bash
# Example: Backup Immich
cd ~/homelab/compose/media/frontend/immich
tar czf immich-backup-$(date +%Y%m%d).tar.gz upload/ config/
```
### Restore Configuration
```bash
tar xzf homelab-config-YYYYMMDD.tar.gz
```
## Updates
### Update Single Service
```bash
cd ~/homelab/compose/path/to/service
docker compose pull
docker compose up -d
```
### Update All Services
```bash
cd ~/homelab
for dir in $(find compose -name "compose.yaml" -exec dirname {} \;); do
echo "Updating $dir"
cd $dir
docker compose pull
docker compose up -d
cd ~/homelab
done
```
### Update Docker
```bash
sudo apt update
sudo apt upgrade docker-ce docker-ce-cli containerd.io
```
## Performance
### Check Resource Usage
```bash
# Overall system
htop
# Docker containers
docker stats
# Disk usage
df -h
docker system df
# Network usage
iftop
```
### Clean Up Disk Space
```bash
# Docker cleanup
docker system prune -a
# Remove old logs
sudo journalctl --vacuum-time=7d
# Find large files
du -h /media | sort -rh | head -20
```
## DNS Configuration
### Cloudflare Example
```
Type: A
Name: *
Content: YOUR_SERVER_IP
Proxy: Off (disable for Let's Encrypt)
TTL: Auto
```
### Local DNS (Pi-hole/hosts file)
```
192.168.1.100 home.fig.systems
192.168.1.100 flix.fig.systems
192.168.1.100 photos.fig.systems
# ... etc
```
## Environment Variables
### List All Services with Secrets
```bash
find ~/homelab/compose -name ".env" -exec echo {} \;
```
### Check for Unconfigured Secrets
```bash
grep -r "changeme_" ~/homelab/compose | wc -l
# Should be 0
```
### Backup All .env Files
```bash
cd ~/homelab
tar czf env-files-$(date +%Y%m%d).tar.gz $(find compose -name ".env")
gpg -c env-files-$(date +%Y%m%d).tar.gz
```
## Monitoring
### Service Health
```bash
# Check all containers are running
docker ps --format "{{.Names}}: {{.Status}}" | grep -v "Up"
# Check for restarts
docker ps --format "{{.Names}}: {{.Status}}" | grep "Restarting"
# Check logs for errors
docker compose logs --tail=100 | grep -i error
```
### SSL Certificate Expiry
```bash
# Check cert expiry
echo | openssl s_client -servername home.fig.systems -connect home.fig.systems:443 2>/dev/null | openssl x509 -noout -dates
```
### Disk Space
```bash
# Overall
df -h
# Docker
docker system df
# Media
du -sh /media/*
```
## Common File Paths
```bash
# Core services
~/homelab/compose/core/traefik/
~/homelab/compose/core/lldap/
~/homelab/compose/core/tinyauth/
# Media
~/homelab/compose/media/frontend/jellyfin/
~/homelab/compose/media/frontend/immich/
~/homelab/compose/media/automation/sonarr/
# Utilities
~/homelab/compose/services/homarr/
~/homelab/compose/services/backrest/
~/homelab/compose/services/linkwarden/
# Documentation
~/homelab/docs/
~/homelab/README.md
```
## Port Reference
```
80 - HTTP (Traefik)
443 - HTTPS (Traefik)
3890 - LLDAP
6881 - qBittorrent (TCP/UDP)
8096 - Jellyfin
2283 - Immich
```
## Default Credentials
⚠️ **Change these immediately after first login!**
### qBittorrent
```
Username: admin
Password: adminadmin
```
### Microbin
```
Check compose/services/microbin/.env
MICROBIN_ADMIN_USERNAME
MICROBIN_ADMIN_PASSWORD
```
### All Other Services
Use SSO (LLDAP) or create admin account on first visit.
## Quick Deployment
### Deploy Everything
```bash
cd ~/homelab
chmod +x deploy-all.sh
./deploy-all.sh
```
### Deploy Core Only
```bash
cd ~/homelab/compose/core/traefik && docker compose up -d
cd ../lldap && docker compose up -d
cd ../tinyauth && docker compose up -d
```
### Deploy Media Stack
```bash
cd ~/homelab/compose/media/frontend
for dir in */; do cd "$dir" && docker compose up -d && cd ..; done
cd ~/homelab/compose/media/automation
for dir in */; do cd "$dir" && docker compose up -d && cd ..; done
```
## Emergency Procedures
### Stop All Services
```bash
cd ~/homelab
find compose -name "compose.yaml" -execdir docker compose down \;
```
### Remove All Containers (Nuclear Option)
```bash
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)
```
### Reset Network
```bash
docker network rm homelab
docker network create homelab
```
### Reset Service
```bash
cd ~/homelab/compose/path/to/service
docker compose down -v # REMOVES VOLUMES!
docker compose up -d
```
---
**For detailed guides, see the [docs folder](./README.md).**

366
docs/services/README.md Normal file
View file

@ -0,0 +1,366 @@
# Services Overview
Complete list of all services in the homelab with descriptions and use cases.
## Core Infrastructure (Required)
### Traefik
- **URL**: https://traefik.fig.systems
- **Purpose**: Reverse proxy with automatic SSL/TLS
- **Why**: Routes all traffic, manages Let's Encrypt certificates
- **Required**: ✅ Yes - Nothing works without this
### LLDAP
- **URL**: https://lldap.fig.systems
- **Purpose**: Lightweight LDAP directory for user management
- **Why**: Centralized user database for SSO
- **Required**: ✅ Yes (if using SSO)
- **Default Login**: admin / <your LLDAP_LDAP_USER_PASS>
### Tinyauth
- **URL**: https://auth.fig.systems
- **Purpose**: SSO forward authentication middleware
- **Why**: Single login for all services
- **Required**: ✅ Yes (if using SSO)
## Dashboard & Management
### Homarr
- **URL**: https://home.fig.systems
- **Purpose**: Service dashboard with auto-discovery
- **Why**: See all your services in one place, monitor status
- **Required**: ⬜ No, but highly recommended
- **Features**:
- Auto-discovers Docker containers
- Customizable widgets
- Service status monitoring
- Integration with media services
### Backrest
- **URL**: https://backup.fig.systems
- **Purpose**: Backup management with web UI (uses Restic)
- **Why**: Encrypted, deduplicated backups to Backblaze B2
- **Required**: ⬜ No, but critical for data safety
- **Features**:
- Web-based backup management
- Scheduled backups
- File browsing and restore
- Encryption at rest
- S3-compatible storage support
## Media Services
### Jellyfin
- **URL**: https://flix.fig.systems
- **Purpose**: Media server (Netflix alternative)
- **Why**: Watch your movies/TV shows anywhere
- **Required**: ⬜ No
- **Features**:
- Stream to any device
- Hardware transcoding (with GPU)
- Live TV & DVR
- Mobile apps available
- Subtitle support
### Immich
- **URL**: https://photos.fig.systems
- **Purpose**: Photo and video management (Google Photos alternative)
- **Why**: Self-hosted photo library with ML features
- **Required**: ⬜ No
- **Features**:
- Face recognition (with GPU)
- Object detection
- Mobile apps with auto-upload
- Timeline view
- Album organization
### Jellyseerr
- **URL**: https://requests.fig.systems
- **Purpose**: Media request management
- **Why**: Let users request movies/shows
- **Required**: ⬜ No (only if using Sonarr/Radarr)
- **Features**:
- Request movies and TV shows
- Integration with Jellyfin
- User permissions
- Notification system
## Media Automation
### Sonarr
- **URL**: https://sonarr.fig.systems
- **Purpose**: TV show automation
- **Why**: Automatically download and organize TV shows
- **Required**: ⬜ No
- **Features**:
- Episode tracking
- Automatic downloading
- Quality management
- Calendar view
### Radarr
- **URL**: https://radarr.fig.systems
- **Purpose**: Movie automation
- **Why**: Automatically download and organize movies
- **Required**: ⬜ No
- **Features**:
- Movie tracking
- Automatic downloading
- Quality profiles
- Collection management
### SABnzbd
- **URL**: https://sabnzbd.fig.systems
- **Purpose**: Usenet downloader
- **Why**: Download from Usenet newsgroups
- **Required**: ⬜ No (only if using Usenet)
- **Features**:
- Fast downloads
- Automatic verification and repair
- Category-based processing
- Password support
### qBittorrent
- **URL**: https://qbt.fig.systems
- **Purpose**: BitTorrent client
- **Why**: Download torrents
- **Required**: ⬜ No (only if using torrents)
- **Features**:
- Web-based UI
- RSS support
- Sequential downloading
- IP filtering
## Productivity Services
### Linkwarden
- **URL**: https://links.fig.systems
- **Purpose**: Bookmark manager
- **Why**: Save and organize web links
- **Required**: ⬜ No
- **Features**:
- Collaborative bookmarking
- Full-text search
- Screenshots and PDFs
- Tags and collections
- Browser extensions
### Vikunja
- **URL**: https://tasks.fig.systems
- **Purpose**: Task management (Todoist alternative)
- **Why**: Track tasks and projects
- **Required**: ⬜ No
- **Features**:
- Kanban boards
- Lists and sub-tasks
- Due dates and reminders
- Collaboration
- CalDAV support
### FreshRSS
- **URL**: https://rss.fig.systems
- **Purpose**: RSS/Atom feed reader
- **Why**: Aggregate news and blogs
- **Required**: ⬜ No
- **Features**:
- Web-based reader
- Mobile apps via API
- Filtering and search
- Multi-user support
## Specialized Services
### LubeLogger
- **URL**: https://garage.fig.systems
- **Purpose**: Vehicle maintenance tracker
- **Why**: Track mileage, maintenance, costs
- **Required**: ⬜ No
- **Features**:
- Service records
- Fuel tracking
- Cost analysis
- Reminder system
- Export data
### Calibre-web
- **URL**: https://books.fig.systems
- **Purpose**: Ebook library manager
- **Why**: Manage and read ebooks
- **Required**: ⬜ No
- **Features**:
- Web-based ebook reader
- Format conversion
- Metadata management
- Send to Kindle
- OPDS support
### Booklore
- **URL**: https://booklore.fig.systems
- **Purpose**: Book tracking and reviews
- **Why**: Track reading progress and reviews
- **Required**: ⬜ No
- **Features**:
- Reading lists
- Progress tracking
- Reviews and ratings
- Import from Goodreads
### RSSHub
- **URL**: https://rsshub.fig.systems
- **Purpose**: RSS feed generator
- **Why**: Generate RSS feeds for sites without them
- **Required**: ⬜ No
- **Features**:
- 1000+ source support
- Custom routes
- Filter and transform feeds
### MicroBin
- **URL**: https://paste.fig.systems
- **Purpose**: Encrypted pastebin with file upload
- **Why**: Share code snippets and files
- **Required**: ⬜ No
- **Features**:
- Encryption support
- File uploads
- Burn after reading
- Custom expiry
- Password protection
### File Browser
- **URL**: https://files.fig.systems
- **Purpose**: Web-based file manager
- **Why**: Browse and manage media files
- **Required**: ⬜ No
- **Features**:
- Upload/download files
- Preview images and videos
- Text editor
- File sharing
- User permissions
## Service Categories
### Minimum Viable Setup
Just want to get started? Deploy these:
1. Traefik
2. LLDAP
3. Tinyauth
4. Homarr
### Media Enthusiast Setup
For streaming media:
1. Core services (above)
2. Jellyfin
3. Sonarr
4. Radarr
5. qBittorrent
6. Jellyseerr
### Complete Homelab
Everything:
1. Core services
2. All media services
3. All productivity services
4. Backrest for backups
## Resource Requirements
### Light (2 Core, 4GB RAM)
- Core services
- Homarr
- 2-3 utility services
### Medium (4 Core, 8GB RAM)
- Core services
- Media services (without transcoding)
- Most utility services
### Heavy (6+ Core, 16GB+ RAM)
- All services
- GPU transcoding
- Multiple concurrent users
## Quick Deploy Checklist
**Before deploying a service:**
- ✅ Core infrastructure is running
- ✅ `.env` file configured with secrets
- ✅ DNS record created
- ✅ Understand what the service does
- ✅ Know how to configure it
**After deploying:**
- ✅ Check container is running: `docker ps`
- ✅ Check logs: `docker compose logs`
- ✅ Access web UI and complete setup
- ✅ Test SSO if applicable
- ✅ Add to Homarr dashboard
## Service Dependencies
```
Traefik (required for all)
├── LLDAP
│ └── Tinyauth
│ └── All SSO-protected services
├── Jellyfin
│ └── Jellyseerr
│ ├── Sonarr
│ └── Radarr
│ ├── SABnzbd
│ └── qBittorrent
├── Immich
│ └── Backrest (for backups)
└── All other services
```
## When to Use Each Service
### Use Jellyfin if:
- You have a movie/TV collection
- Want to stream from anywhere
- Have family/friends who want access
- Want apps on all devices
### Use Immich if:
- You want Google Photos alternative
- Have lots of photos to manage
- Want ML features (face recognition)
- Have mobile devices
### Use Sonarr/Radarr if:
- You watch a lot of TV/movies
- Want automatic downloads
- Don't want to manually search
- Want quality control
### Use Backrest if:
- You care about your data (you should!)
- Want encrypted cloud backups
- Have important photos/documents
- Want easy restore process
### Use Linkwarden if:
- You save lots of bookmarks
- Want full-text search
- Share links with team
- Want offline archives
### Use Vikunja if:
- You need task management
- Work with teams
- Want Kanban boards
- Need CalDAV for calendar integration
## Next Steps
1. Review which services you actually need
2. Start with core + 2-3 services
3. Deploy and configure each fully
4. Add more services gradually
5. Monitor resource usage
---
**Remember**: You don't need all services. Start small and add what you actually use!

View file

@ -0,0 +1,707 @@
# Common Issues and Solutions
This guide covers the most common problems you might encounter and how to fix them.
## Table of Contents
- [Service Won't Start](#service-wont-start)
- [SSL/TLS Certificate Errors](#ssltls-certificate-errors)
- [SSO Authentication Issues](#sso-authentication-issues)
- [Access Issues](#access-issues)
- [Performance Problems](#performance-problems)
- [Database Errors](#database-errors)
- [Network Issues](#network-issues)
- [GPU Problems](#gpu-problems)
## Service Won't Start
### Symptom
Container exits immediately or shows "Exited (1)" status.
### Diagnosis
```bash
cd ~/homelab/compose/path/to/service
# Check container status
docker compose ps
# View logs
docker compose logs
# Check for specific errors
docker compose logs | grep -i error
```
### Common Causes and Fixes
#### 1. Environment Variables Not Set
**Error in logs:**
```
Error: POSTGRES_PASSWORD is not set
Error: required environment variable 'XXX' is missing
```
**Fix:**
```bash
# Check .env file exists
ls -la .env
# Check for changeme_ values
grep "changeme_" .env
# Update with proper secrets (see secrets guide)
nano .env
# Restart
docker compose up -d
```
#### 2. Port Already in Use
**Error in logs:**
```
Error: bind: address already in use
Error: failed to bind to port 80: address already in use
```
**Fix:**
```bash
# Find what's using the port
sudo netstat -tulpn | grep :80
sudo netstat -tulpn | grep :443
# Stop conflicting service
sudo systemctl stop apache2 # Example
sudo systemctl stop nginx # Example
# Or change port in compose.yaml
```
#### 3. Network Not Created
**Error in logs:**
```
network homelab declared as external, but could not be found
```
**Fix:**
```bash
# Create network
docker network create homelab
# Verify
docker network ls | grep homelab
# Restart service
docker compose up -d
```
#### 4. Volume Permission Issues
**Error in logs:**
```
Permission denied: '/config'
mkdir: cannot create directory '/data': Permission denied
```
**Fix:**
```bash
# Check directory ownership
ls -la ./config ./data
# Fix ownership (replace 1000:1000 with your UID:GID)
sudo chown -R 1000:1000 ./config ./data
# Restart
docker compose up -d
```
#### 5. Dependency Not Running
**Error in logs:**
```
Failed to connect to database
Connection refused: postgres:5432
```
**Fix:**
```bash
# Start dependency first
cd ~/homelab/compose/path/to/dependency
docker compose up -d
# Wait for it to be healthy
docker compose logs -f
# Then start the service
cd ~/homelab/compose/path/to/service
docker compose up -d
```
## SSL/TLS Certificate Errors
### Symptom
Browser shows "Your connection is not private" or "NET::ERR_CERT_AUTHORITY_INVALID"
### Diagnosis
```bash
# Check Traefik logs
docker logs traefik | grep -i certificate
docker logs traefik | grep -i letsencrypt
docker logs traefik | grep -i error
# Test certificate
echo | openssl s_client -servername home.fig.systems -connect home.fig.systems:443 2>/dev/null | openssl x509 -noout -dates
```
### Common Causes and Fixes
#### 1. DNS Not Configured
**Fix:**
```bash
# Test DNS resolution
dig home.fig.systems +short
# Should return your server's IP
# If not, configure DNS A records:
# *.fig.systems -> YOUR_SERVER_IP
```
#### 2. Port 80 Not Accessible
Let's Encrypt needs port 80 for HTTP-01 challenge.
**Fix:**
```bash
# Test from external network
curl -I http://home.fig.systems
# Check firewall
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Check port forwarding on router
# Ensure ports 80 and 443 are forwarded to server
```
#### 3. Rate Limiting
Let's Encrypt has limits: 5 certificates per domain per week.
**Fix:**
```bash
# Check Traefik logs for rate limit errors
docker logs traefik | grep -i "rate limit"
# Wait for rate limit to reset (1 week)
# Or use Let's Encrypt staging environment for testing
# Enable staging in traefik/compose.yaml:
# - --certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
```
#### 4. First Startup - Certificates Not Yet Generated
**Fix:**
```bash
# Wait 2-5 minutes for certificate generation
docker logs traefik -f
# Look for:
# "Certificate obtained for domain"
```
#### 5. Certificate Expired
Traefik should auto-renew, but if manual renewal needed:
**Fix:**
```bash
# Remove old certificates
cd ~/homelab/compose/core/traefik
rm -rf ./acme.json
# Restart Traefik
docker compose restart
# Wait for new certificates
docker logs traefik -f
```
## SSO Authentication Issues
### Symptom
- Can't login to SSO-protected services
- Redirected to auth page but login fails
- "Invalid credentials" error
### Diagnosis
```bash
# Check LLDAP is running
docker ps | grep lldap
# Check Tinyauth is running
docker ps | grep tinyauth
# View logs
docker logs lldap
docker logs tinyauth
```
### Common Causes and Fixes
#### 1. Password Mismatch
LDAP_BIND_PASSWORD must match LLDAP_LDAP_USER_PASS.
**Fix:**
```bash
# Check both passwords
grep LLDAP_LDAP_USER_PASS ~/homelab/compose/core/lldap/.env
grep LDAP_BIND_PASSWORD ~/homelab/compose/core/tinyauth/.env
# They must be EXACTLY the same!
# If different, update tinyauth/.env
cd ~/homelab/compose/core/tinyauth
nano .env
# Set LDAP_BIND_PASSWORD to match LLDAP_LDAP_USER_PASS
# Restart Tinyauth
docker compose restart
```
#### 2. User Doesn't Exist in LLDAP
**Fix:**
```bash
# Access LLDAP web UI
# Go to: https://lldap.fig.systems
# Login with admin credentials
# Username: admin
# Password: <your LLDAP_LDAP_USER_PASS>
# Create user:
# - Click "Create user"
# - Set username, email, password
# - Add to "lldap_admin" group
# Try logging in again
```
#### 3. LLDAP or Tinyauth Not Running
**Fix:**
```bash
# Start LLDAP
cd ~/homelab/compose/core/lldap
docker compose up -d
# Wait for it to be ready
docker compose logs -f
# Start Tinyauth
cd ~/homelab/compose/core/tinyauth
docker compose up -d
docker compose logs -f
```
#### 4. Network Issue Between Tinyauth and LLDAP
**Fix:**
```bash
# Test connection
docker exec tinyauth nc -zv lldap 3890
# Should show: Connection to lldap 3890 port [tcp/*] succeeded!
# If not, check both are on homelab network
docker network inspect homelab
```
## Access Issues
### Symptom
- Can't access service from browser
- Connection timeout
- "This site can't be reached"
### Diagnosis
```bash
# Test from server
curl -I https://home.fig.systems
# Test DNS
dig home.fig.systems +short
# Check container is running
docker ps | grep servicename
# Check Traefik routing
docker logs traefik | grep servicename
```
### Common Causes and Fixes
#### 1. Service Not Running
**Fix:**
```bash
cd ~/homelab/compose/path/to/service
docker compose up -d
docker compose logs -f
```
#### 2. Traefik Not Running
**Fix:**
```bash
cd ~/homelab/compose/core/traefik
docker compose up -d
docker compose logs -f
```
#### 3. DNS Not Resolving
**Fix:**
```bash
# Check DNS
dig service.fig.systems +short
# Should return your server IP
# If not, add/update DNS A record
```
#### 4. Firewall Blocking
**Fix:**
```bash
# Check firewall
sudo ufw status
# Allow if needed
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
```
#### 5. Wrong Traefik Labels
**Fix:**
```bash
# Check compose.yaml has correct labels
cd ~/homelab/compose/path/to/service
cat compose.yaml | grep -A 10 "labels:"
# Should have:
# traefik.enable: true
# traefik.http.routers.servicename.rule: Host(`service.fig.systems`)
# etc.
```
## Performance Problems
### Symptom
- Services running slowly
- High CPU/RAM usage
- System unresponsive
### Diagnosis
```bash
# Overall system
htop
# Docker resources
docker stats
# Disk usage
df -h
docker system df
```
### Common Causes and Fixes
#### 1. Insufficient RAM
**Fix:**
```bash
# Check RAM usage
free -h
# If low, either:
# 1. Add more RAM
# 2. Stop unused services
# 3. Add resource limits to compose files
# Example resource limit:
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 1G
```
#### 2. Disk Full
**Fix:**
```bash
# Check disk usage
df -h
# Clean Docker
docker system prune -a
# Remove old logs
sudo journalctl --vacuum-time=7d
# Check media folder
du -sh /media/*
```
#### 3. Too Many Services Running
**Fix:**
```bash
# Stop unused services
cd ~/homelab/compose/services/unused-service
docker compose down
# Or deploy only what you need
```
#### 4. Database Not Optimized
**Fix:**
```bash
# For postgres services, add to .env:
POSTGRES_INITDB_ARGS=--data-checksums
# Increase shared buffers (if enough RAM):
# Edit compose.yaml, add to postgres:
command: postgres -c shared_buffers=256MB -c max_connections=200
```
## Database Errors
### Symptom
- "Connection refused" to database
- "Authentication failed for user"
- "Database does not exist"
### Diagnosis
```bash
# Check database container
docker ps | grep postgres
# View database logs
docker logs <postgres_container_name>
# Test connection from app
docker exec <app_container> nc -zv <db_container> 5432
```
### Common Causes and Fixes
#### 1. Password Mismatch
**Fix:**
```bash
# Check passwords match in .env
cat .env | grep PASSWORD
# For example, in Vikunja:
# VIKUNJA_DATABASE_PASSWORD and POSTGRES_PASSWORD must match!
# Update if needed
nano .env
docker compose down
docker compose up -d
```
#### 2. Database Not Initialized
**Fix:**
```bash
# Remove database and reinitialize
docker compose down
rm -rf ./db/ # CAREFUL: This deletes all data!
docker compose up -d
```
#### 3. Database Still Starting
**Fix:**
```bash
# Wait for database to be ready
docker logs <postgres_container> -f
# Look for "database system is ready to accept connections"
# Then restart app
docker compose restart <app_service>
```
## Network Issues
### Symptom
- Containers can't communicate
- "Connection refused" between services
### Diagnosis
```bash
# Inspect network
docker network inspect homelab
# Test connectivity
docker exec container1 ping container2
docker exec container1 nc -zv container2 PORT
```
### Common Causes and Fixes
#### 1. Containers Not on Same Network
**Fix:**
```bash
# Check compose.yaml has networks section
networks:
homelab:
external: true
# Ensure service is using the network
services:
servicename:
networks:
- homelab
```
#### 2. Network Doesn't Exist
**Fix:**
```bash
docker network create homelab
docker compose up -d
```
#### 3. DNS Resolution Between Containers
**Fix:**
```bash
# Use container name, not localhost
# Wrong: http://localhost:5432
# Right: http://postgres:5432
# Or use service name from compose.yaml
```
## GPU Problems
### Symptom
- "No hardware acceleration available"
- GPU not detected in container
- "Failed to open GPU"
### Diagnosis
```bash
# Check GPU on host
nvidia-smi
# Check GPU in container
docker exec jellyfin nvidia-smi
# Check Docker GPU runtime
docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi
```
### Common Causes and Fixes
#### 1. NVIDIA Container Toolkit Not Installed
**Fix:**
```bash
# Install toolkit
sudo apt install nvidia-container-toolkit
# Configure runtime
sudo nvidia-ctk runtime configure --runtime=docker
# Restart Docker
sudo systemctl restart docker
```
#### 2. Runtime Not Specified in Compose
**Fix:**
```bash
# Edit compose.yaml
nano compose.yaml
# Uncomment:
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
# Restart
docker compose up -d
```
#### 3. GPU Already in Use
**Fix:**
```bash
# Check processes using GPU
nvidia-smi
# Kill process if needed
sudo kill <PID>
# Restart service
docker compose restart
```
#### 4. GPU Not Passed Through to VM (Proxmox)
**Fix:**
```bash
# From Proxmox host, check GPU passthrough
lspci | grep -i nvidia
# From VM, check GPU visible
lspci | grep -i nvidia
# If not visible, reconfigure passthrough (see GPU guide)
```
## Getting More Help
If your issue isn't listed here:
1. **Check service-specific logs**:
```bash
cd ~/homelab/compose/path/to/service
docker compose logs --tail=200
```
2. **Search container logs for errors**:
```bash
docker compose logs | grep -i error
docker compose logs | grep -i fail
```
3. **Check FAQ**: See [FAQ](./faq.md)
4. **Debugging Guide**: See [Debugging Guide](./debugging.md)
5. **Service Documentation**: Check service's official documentation
---
**Most issues can be solved by checking logs and environment variables!**

484
docs/troubleshooting/faq.md Normal file
View file

@ -0,0 +1,484 @@
# Frequently Asked Questions (FAQ)
Common questions and answers about the homelab setup.
## General Questions
### Q: What is this homelab setup?
**A:** This is a GitOps-based infrastructure for self-hosting services using Docker Compose. It includes:
- 20+ pre-configured services (media, productivity, utilities)
- Automatic SSL/TLS with Let's Encrypt via Traefik
- Single Sign-On (SSO) with LLDAP and Tinyauth
- Automated backups with Backrest
- Service discovery dashboard with Homarr
### Q: What are the minimum hardware requirements?
**A:**
- **CPU**: 2+ cores (4+ recommended)
- **RAM**: 8GB minimum (16GB+ recommended)
- **Storage**: 100GB for containers, additional space for media
- **Network**: Static IP recommended, ports 80 and 443 accessible
- **GPU** (Optional): NVIDIA GPU for hardware transcoding
### Q: Do I need my own domain name?
**A:** Yes, you need at least one domain (two configured by default: `fig.systems` and `edfig.dev`). You can:
- Register a domain from any registrar
- Update all compose files to use your domain
- Configure wildcard DNS (`*.yourdomain.com`)
### Q: Can I run this on a Raspberry Pi?
**A:** Partially. ARM64 architecture is supported by most services, but:
- Performance will be limited
- No GPU acceleration available
- Some services may not have ARM images
- 8GB RAM minimum recommended (Pi 4 or Pi 5)
### Q: How much does this cost to run?
**A:**
- **Server**: $0 (if using existing hardware) or $5-20/month (VPS)
- **Domain**: $10-15/year
- **Backblaze B2**: ~$0.60/month for 100GB photos
- **Electricity**: Varies by hardware and location
- **Total**: $15-30/year minimum
## Setup Questions
### Q: Why won't my services start?
**A:** Common causes:
1. **Environment variables not set**: Check for `changeme_*` in `.env` files
2. **Ports already in use**: Check if 80/443 are available
3. **Network not created**: Run `docker network create homelab`
4. **DNS not configured**: Services need valid DNS records
5. **Insufficient resources**: Check RAM and disk space
**Debug:**
```bash
cd compose/path/to/service
docker compose logs
docker compose ps
```
### Q: How do I know if everything is working?
**A:** Check these indicators:
1. **All containers running**: `docker ps` shows all services
2. **SSL certificates valid**: Visit https://home.fig.systems (no cert errors)
3. **Dashboard accessible**: Homarr shows all services
4. **SSO working**: Can login to protected services
5. **No errors in logs**: `docker compose logs` shows no critical errors
### Q: What order should I deploy services?
**A:** Follow this order:
1. **Core**: Traefik → LLDAP → Tinyauth
2. **Configure**: Create LLDAP users
3. **Media**: Jellyfin → Immich → Jellyseerr → Sonarr → Radarr → Downloaders
4. **Utility**: Homarr → Backrest → Everything else
### Q: Do I need to configure all 20 services?
**A:** No! Deploy only what you need:
- **Core** (required): Traefik, LLDAP, Tinyauth
- **Media** (optional): Jellyfin, Immich, Sonarr, Radarr
- **Utility** (pick what you want): Homarr, Backrest, Linkwarden, Vikunja, etc.
## Configuration Questions
### Q: What secrets do I need to change?
**A:** Search for `changeme_*` in all `.env` files:
```bash
grep -r "changeme_" compose/
```
Critical secrets:
- **LLDAP_LDAP_USER_PASS**: Admin password for LLDAP
- **LLDAP_JWT_SECRET**: 64-character hex string
- **SESSION_SECRET**: 64-character hex string for Tinyauth
- **DB_PASSWORD**: Database passwords (Immich, Vikunja, Linkwarden)
- **NEXTAUTH_SECRET**: NextAuth secret for Linkwarden
- **VIKUNJA_SERVICE_JWTSECRET**: JWT secret for Vikunja
### Q: How do I generate secure secrets?
**A:** Use these commands:
```bash
# 64-character hex (for JWT secrets, session secrets)
openssl rand -hex 32
# 32-character password (for databases)
openssl rand -base64 32 | tr -d /=+ | cut -c1-32
# 32-character hex (for API keys)
openssl rand -hex 16
```
See [Secrets Management Guide](../guides/secrets-management.md) for details.
### Q: Can I change the domains from fig.systems to my own?
**A:** Yes! You need to:
1. Find and replace in all `compose.yaml` files:
```bash
find compose -name "compose.yaml" -exec sed -i 's/fig\.systems/yourdomain.com/g' {} \;
find compose -name "compose.yaml" -exec sed -i 's/edfig\.dev/yourotherdomain.com/g' {} \;
```
2. Update DNS records to point to your server
3. Update `.env` files with new URLs (e.g., `NEXTAUTH_URL`, `VIKUNJA_SERVICE_PUBLICURL`)
### Q: Do all passwords need to match?
**A:** No, but some must match:
- **LLDAP_LDAP_USER_PASS** must equal **LDAP_BIND_PASSWORD** (in tinyauth)
- **VIKUNJA_DATABASE_PASSWORD** must equal **POSTGRES_PASSWORD** (in vikunja)
- **Linkwarden POSTGRES_PASSWORD** is used in DATABASE_URL
All other passwords should be unique!
## SSL/TLS Questions
### Q: Why am I getting SSL certificate errors?
**A:** Common causes:
1. **DNS not configured**: Ensure domains point to your server
2. **Ports not accessible**: Let's Encrypt needs port 80 for HTTP challenge
3. **Rate limiting**: Let's Encrypt has rate limits (5 certs per domain/week)
4. **First startup**: Certs take a few minutes to generate
**Debug:**
```bash
docker logs traefik | grep -i error
docker logs traefik | grep -i certificate
```
### Q: How long do SSL certificates last?
**A:** Let's Encrypt certificates:
- Valid for 90 days
- Traefik auto-renews at 30 days before expiration
- Renewals happen automatically in the background
### Q: Can I use my own SSL certificates?
**A:** Yes, but it requires modifying Traefik configuration. The default Let's Encrypt setup is recommended.
## SSO Questions
### Q: What is SSO and do I need it?
**A:** SSO (Single Sign-On) lets you log in once and access all services:
- **LLDAP**: Stores users and passwords
- **Tinyauth**: Authenticates users before allowing service access
- **Benefits**: One login for all services, centralized user management
- **Optional**: Some services can work without SSO (have their own auth)
### Q: Why can't I log into SSO-protected services?
**A:** Check:
1. **LLDAP is running**: `docker ps | grep lldap`
2. **Tinyauth is running**: `docker ps | grep tinyauth`
3. **User exists in LLDAP**: Go to https://lldap.fig.systems and verify
4. **Passwords match**: LDAP_BIND_PASSWORD = LLDAP_LDAP_USER_PASS
5. **User in correct group**: Check user is in `lldap_admin` group
**Debug:**
```bash
cd compose/core/tinyauth
docker compose logs -f
```
### Q: Can I disable SSO for a service?
**A:** Yes! Comment out the middleware line in compose.yaml:
```yaml
# traefik.http.routers.servicename.middlewares: tinyauth
```
Then restart the service:
```bash
docker compose up -d
```
### Q: How do I reset my LLDAP admin password?
**A:**
1. Stop LLDAP: `cd compose/core/lldap && docker compose down`
2. Update `LLDAP_LDAP_USER_PASS` in `.env`
3. Remove the database: `rm -rf data/`
4. Restart: `docker compose up -d`
5. Recreate users in LLDAP UI
⚠️ **Warning**: This deletes all users!
## Service-Specific Questions
### Q: Jellyfin shows "Playback Error" - what's wrong?
**A:** Common causes:
1. **Media file corrupt**: Test file with VLC
2. **Permissions**: Check file ownership (`ls -la /media/movies`)
3. **Codec not supported**: Enable transcoding or use different file
4. **GPU not configured**: If using GPU, verify NVIDIA Container Toolkit
### Q: Immich won't upload photos - why?
**A:** Check:
1. **Database connected**: `docker logs immich_postgres`
2. **Upload directory writable**: Check permissions on `./upload`
3. **Disk space**: `df -h`
4. **File size limits**: Check browser console for errors
### Q: Why isn't Homarr showing my services?
**A:** Homarr needs:
1. **Docker socket access**: Volume mount `/var/run/docker.sock`
2. **Labels on services**: Each service needs `homarr.name` label
3. **Same network**: Homarr must be on `homelab` network
4. **Time to detect**: Refresh page or wait 30 seconds
### Q: Backrest shows "Repository not initialized" - what do I do?
**A:**
1. Go to https://backup.fig.systems
2. Click "Add Repository"
3. Configure Backblaze B2 settings
4. Click "Initialize Repository"
See [Backup Guide](../services/backup.md) for detailed setup.
### Q: Sonarr/Radarr can't find anything - help!
**A:**
1. **Add indexers**: Settings → Indexers → Add indexer
2. **Configure download client**: Settings → Download Clients → Add
3. **Set root folder**: Series/Movies → Add Root Folder → `/media/tv` or `/media/movies`
4. **Test indexers**: Settings → Indexers → Test
### Q: qBittorrent shows "Unauthorized" - what's the password?
**A:** Default credentials:
- Username: `admin`
- Password: `adminadmin`
⚠️ **Change this immediately** in qBittorrent settings!
## Media Questions
### Q: Where should I put my media files?
**A:** Use the /media directory structure:
- Movies: `/media/movies/Movie Name (Year)/movie.mkv`
- TV: `/media/tv/Show Name/Season 01/episode.mkv`
- Music: `/media/music/Artist/Album/song.flac`
- Photos: `/media/photos/` (any structure)
- Books: `/media/books/` (any structure)
### Q: How do I add more media storage?
**A:**
1. Mount additional drive to `/media2` (or any path)
2. Update compose files to include new volume:
```yaml
volumes:
- /media:/media:ro
- /media2:/media2:ro # Add this
```
3. Restart service: `docker compose up -d`
4. Add new library in service UI
### Q: Can Sonarr/Radarr automatically download shows/movies?
**A:** Yes! That's their purpose:
1. Add indexers (for searching)
2. Add download client (SABnzbd or qBittorrent)
3. Add a series/movie
4. Enable monitoring
5. Sonarr/Radarr will search, download, and organize automatically
### Q: How do I enable hardware transcoding in Jellyfin?
**A:** See [GPU Setup Guide](../guides/gpu-setup.md) for full instructions.
Quick steps:
1. Install NVIDIA Container Toolkit on host
2. Uncomment GPU sections in `jellyfin/compose.yaml`
3. Restart Jellyfin
4. Enable in Jellyfin: Dashboard → Playback → Hardware Acceleration → NVIDIA NVENC
## Network Questions
### Q: Can I access services only from my local network?
**A:** Yes, don't expose ports 80/443 to internet:
1. Use firewall to block external access
2. Use local DNS (Pi-hole, AdGuard Home)
3. Point domains to local IP (192.168.x.x)
4. Use self-signed certs or no HTTPS
**Or** use Traefik's IP allowlist middleware.
### Q: Can I use a VPN with these services?
**A:** Yes, options:
1. **VPN on download clients**: Add VPN container for qBittorrent/SABnzbd
2. **VPN to access homelab**: Use WireGuard/Tailscale to access from anywhere
3. **VPN for entire server**: All traffic goes through VPN (not recommended)
### Q: Why can't I access services from outside my network?
**A:** Check:
1. **Port forwarding**: Ports 80 and 443 forwarded to homelab server
2. **Firewall**: Allow ports 80/443 through firewall
3. **DNS**: Domains point to your public IP
4. **ISP**: Some ISPs block ports 80/443 (use CloudFlare Tunnel)
## Backup Questions
### Q: What should I backup?
**A:** Priority order:
1. **High**: Immich photos (`compose/media/frontend/immich/upload`)
2. **High**: Configuration files (all `.env` files, compose files)
3. **Medium**: Service data directories (`./config`, `./data` in each service)
4. **Low**: Media files (usually have source elsewhere)
### Q: How do I restore from backup?
**A:** See [Backup Operations Guide](../operations/backups.md).
Quick steps:
1. Install fresh homelab setup
2. Restore `.env` files and configs
3. Use Backrest to restore data
4. Restart services
### Q: Does Backrest backup everything automatically?
**A:** Only what you configure:
- Default: Immich photos and homelab configs
- Add more paths in `backrest/compose.yaml` volumes
- Create backup plans in Backrest UI for each path
## Performance Questions
### Q: Services are running slow - how do I optimize?
**A:**
1. **Check resources**: `docker stats` - are you out of RAM/CPU?
2. **Reduce services**: Stop unused services
3. **Use SSD**: Move Docker to SSD storage
4. **Add RAM**: Minimum 8GB, 16GB+ recommended
5. **Enable GPU**: For Jellyfin and Immich
### Q: Docker is using too much disk space - what do I do?
**A:**
```bash
# Check Docker disk usage
docker system df
# Clean up
docker system prune -a --volumes
# WARNING: This removes all stopped containers and unused volumes!
```
Better approach - clean specific services:
```bash
cd compose/path/to/service
docker compose down
docker volume rm $(docker volume ls -q | grep servicename)
docker compose up -d
```
### Q: How do I limit RAM/CPU for a service?
**A:** Add resource limits to compose.yaml:
```yaml
services:
servicename:
deploy:
resources:
limits:
cpus: '2.0'
memory: 4G
reservations:
memory: 2G
```
## Update Questions
### Q: How do I update a service?
**A:**
```bash
cd compose/path/to/service
docker compose pull
docker compose up -d
```
See [Updates Guide](../operations/updates.md) for details.
### Q: How often should I update?
**A:**
- **Security updates**: Weekly
- **Feature updates**: Monthly
- **Major versions**: When stable
Use Watchtower for automatic updates (optional).
### Q: Will updating break my configuration?
**A:** Usually no, but:
- Always backup before major updates
- Check release notes for breaking changes
- Test in staging environment if critical
## Security Questions
### Q: Is this setup secure?
**A:** Reasonably secure with best practices:
- ✅ SSL/TLS encryption
- ✅ SSO authentication
- ✅ Secrets in environment files
- ⚠️ Some services exposed to internet
- ⚠️ Depends on keeping services updated
See [Security Guide](../guides/security.md) for hardening.
### Q: Should I expose my homelab to the internet?
**A:** Depends on your risk tolerance:
- **Yes**: Convenient access from anywhere, Let's Encrypt works
- **No**: More secure, requires VPN for external access
- **Hybrid**: Expose only essential services, use VPN for sensitive ones
### Q: What if someone gets my LLDAP password?
**A:** They can access all SSO-protected services. Mitigations:
- Use strong, unique passwords
- Enable 2FA where supported
- Review LLDAP access logs
- Use fail2ban to block brute force
- Consider VPN-only access
## Troubleshooting
For specific error messages and debugging, see:
- [Common Issues](./common-issues.md)
- [Debugging Guide](./debugging.md)
Still stuck? Check:
1. Service logs: `docker compose logs`
2. Traefik logs: `docker logs traefik`
3. Container status: `docker ps -a`
4. Network connectivity: `docker network inspect homelab`