Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 70 additions & 110 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,122 +1,82 @@
# =============================================================================
# HomeLab Stack — Environment Configuration
# ============================================
# HomeLab Stack - Environment Configuration
# ============================================
# Copy this file to .env and fill in your values
# Run: cp .env.example .env && ./scripts/setup-env.sh
# =============================================================================
# cp .env.example .env
# ============================================

# -----------------------------------------------------------------------------
# GENERAL
# -----------------------------------------------------------------------------
TZ=Asia/Shanghai
PUID=1000
PGID=1000
DOMAIN=yourdomain.com # Your base domain (e.g. home.example.com)
ACME_EMAIL=you@example.com # Let's Encrypt notification email
# --- Domain & TLS ---
DOMAIN=
ACME_EMAIL=

# -----------------------------------------------------------------------------
# TRAEFIK
# -----------------------------------------------------------------------------
TRAEFIK_DASHBOARD_USER=admin
# Generate password hash: echo $(htpasswd -nb admin yourpassword) | sed -e s/\$/\$\$/g
# --- Traefik Dashboard ---
TRAEFIK_DASHBOARD_USER=
TRAEFIK_DASHBOARD_PASSWORD_HASH=

# -----------------------------------------------------------------------------
# PORTAINER
# -----------------------------------------------------------------------------
# No config needed — admin password set on first login
# --- Timezone ---
TZ=Asia/Shanghai

# --- Portainer ---
PORTAINER_ADMIN_PASSWORD=changeme

# -----------------------------------------------------------------------------
# AUTHENTIK (SSO)
# -----------------------------------------------------------------------------
AUTHENTIK_SECRET_KEY= # REQUIRED: openssl rand -base64 32
AUTHENTIK_POSTGRES_PASSWORD= # REQUIRED: strong random password
AUTHENTIK_REDIS_PASSWORD= # REQUIRED: strong random password
AUTHENTIK_ADMIN_EMAIL=
AUTHENTIK_ADMIN_PASSWORD=
AUTHENTIK_DOMAIN=auth.${DOMAIN}
# --- Databases ---
POSTGRES_ROOT_PASSWORD=
REDIS_PASSWORD=
MARIADB_ROOT_PASSWORD=

# OAuth2 clients — auto-filled by scripts/setup-authentik.sh
# --- Authentik (SSO) ---
AUTHENTIK_DOMAIN=
AUTHENTIK_SECRET_KEY=
AUTHENTIK_BOOTSTRAP_PASSWORD=
AUTHENTIK_BOOTSTRAP_EMAIL=

# --- Monitoring ---
GRAFANA_ADMIN_USER=
GRAFANA_ADMIN_PASSWORD=
GRAFANA_OAUTH_CLIENT_ID=
GRAFANA_OAUTH_CLIENT_SECRET=
GITEA_OAUTH_CLIENT_ID=
GITEA_OAUTH_CLIENT_SECRET=
OUTLINE_OAUTH_CLIENT_ID=
OUTLINE_OAUTH_CLIENT_SECRET=
PORTAINER_OAUTH_CLIENT_ID=
PORTAINER_OAUTH_CLIENT_SECRET=

# -----------------------------------------------------------------------------
# DATABASES (shared stack)
# -----------------------------------------------------------------------------
POSTGRES_PASSWORD= # REQUIRED: master postgres password
REDIS_PASSWORD= # REQUIRED
MARIADB_ROOT_PASSWORD= # REQUIRED

# Per-service database credentials
# --- Productivity ---
GITEA_DB_PASSWORD=
NEXTCLOUD_DB_PASSWORD=
GITEA_OAUTH2_JWT_SECRET=
VAULTWARDEN_ADMIN_TOKEN=
VAULTWARDEN_DB_PASSWORD=
OUTLINE_SECRET_KEY=
OUTLINE_UTILS_SECRET=
OUTLINE_DB_PASSWORD=
AUTHENTIK_DB_PASSWORD=

# -----------------------------------------------------------------------------
# GRAFANA
# -----------------------------------------------------------------------------
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD= # REQUIRED

# -----------------------------------------------------------------------------
# VAULTWARDEN
# -----------------------------------------------------------------------------
VAULTWARDEN_ADMIN_TOKEN= # REQUIRED: openssl rand -base64 48

# -----------------------------------------------------------------------------
# WIREGUARD
# -----------------------------------------------------------------------------
WG_HOST= # Your public IP or domain
WG_PASSWORD= # WireGuard Easy web UI password
WG_PORT=51820

# -----------------------------------------------------------------------------
# CLOUDFLARE DDNS
# -----------------------------------------------------------------------------
CF_API_TOKEN=
CF_ZONE_ID=
CF_RECORD_NAME=

# -----------------------------------------------------------------------------
# NEXTCLOUD
# -----------------------------------------------------------------------------
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD= # REQUIRED

# -----------------------------------------------------------------------------
# MEDIA STACK
# -----------------------------------------------------------------------------
MEDIA_ROOT=/opt/homelab/media # Host path for media files
DOWNLOADS_ROOT=/opt/homelab/downloads

# -----------------------------------------------------------------------------
# OLLAMA / AI
# -----------------------------------------------------------------------------
OLLAMA_GPU_ENABLED=false # Set to true if you have NVIDIA GPU

# -----------------------------------------------------------------------------
# NOTIFICATIONS
# -----------------------------------------------------------------------------
GOTIFY_PASSWORD= # REQUIRED
NTFY_AUTH_ENABLED=true

# -----------------------------------------------------------------------------
# NETWORK PROXY (optional — for CN users with local proxy)
# -----------------------------------------------------------------------------
HTTP_PROXY=
HTTPS_PROXY=
NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
DOCKER_PROXY_ENABLED=false

# -----------------------------------------------------------------------------
# CN MIRROR CONFIG (auto-set by setup-cn-mirrors.sh)
# -----------------------------------------------------------------------------
CN_MODE=false
CN_APT_MIRROR=https://mirrors.aliyun.com/ubuntu
CN_DOCKER_MIRROR=https://docker.m.daocloud.io
OUTLINE_OAUTH_CLIENT_ID=
OUTLINE_OAUTH_CLIENT_SECRET=
BOOKSTACK_APP_KEY=
BOOKSTACK_DB_PASSWORD=
BOOKSTACK_OIDC_CLIENT_ID=
BOOKSTACK_OIDC_CLIENT_SECRET=

# --- AI ---
WEBUI_SECRET_KEY=

# --- Media ---
# (to be filled when media stack is implemented)

# --- Network ---
# AdGuard Home - no additional env vars needed
# WireGuard Easy
WG_HOST= # Public IP or domain of your server (e.g. vpn.yourdomain.com)
WGUI_PASSWORD= # Password for WireGuard Web UI (will be hashed automatically)
WG_PORT=51820 # WireGuard UDP port (default 51820)
WG_DEFAULT_DNS=1.1.1.1 # DNS to push to VPN clients
# Cloudflare DDNS
CF_API_TOKEN= # Cloudflare API token with DNS edit permissions
CF_DOMAINS= # Comma-separated list of domains/subdomains (e.g. example.com,www.example.com)
CF_PROXIED=true # Whether to proxy through Cloudflare (true/false)

# --- Dashboard ---
SECRET_ENCRYPTION_KEY=

# --- Home Automation ---
# (to be filled when home-automation stack is implemented)

# --- Notifications ---
# (to be filled when notifications stack is implemented)

# --- Backup ---
# (to be filled when backup stack is implemented)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ docker compose -f docker-compose.base.yml up -d
| [Storage](stacks/storage/) | Nextcloud, MinIO, FileBrowser, Syncthing | [#3](../../issues/3) |
| [Monitoring](stacks/monitoring/) | Grafana, Prometheus, Loki, Alertmanager, Uptime Kuma | [#4](../../issues/4) |
| [Network](stacks/network/) | AdGuard Home, WireGuard Easy, Cloudflare DDNS, Nginx Proxy Manager | [#5](../../issues/5) |
| [Productivity](stacks/productivity/) | Gitea, Vaultwarden, Outline, Stirling-PDF, IT-Tools | [#6](../../issues/6) |
| [Productivity](stacks/productivity/) | Gitea, Vaultwarden, Outline, BookStack | [#6](../../issues/6) |
| [AI](stacks/ai/) | Ollama, Open WebUI, LocalAI, n8n | [#7](../../issues/7) |
| [Home Automation](stacks/home-automation/) | Home Assistant, Node-RED, Mosquitto, Zigbee2MQTT, ESPHome | [#8](../../issues/8) |
| [SSO / Auth](stacks/sso/) | Authentik, PostgreSQL, Redis | [#9](../../issues/9) |
Expand Down
48 changes: 31 additions & 17 deletions config/alertmanager/alertmanager.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,45 @@
global:
resolve_timeout: 5m
smtp_require_tls: false
smtp_smarthost: '${SMTP_HOST}:${SMTP_PORT}'
smtp_from: '${ALERTMANAGER_EMAIL_FROM}'
smtp_auth_username: '${ALERTMANAGER_EMAIL_USER}'
smtp_auth_password: '${ALERTMANAGER_EMAIL_PASS}'
smtp_require_tls: true

route:
group_by: [alertname, cluster]
receiver: 'default'
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
receiver: default
repeat_interval: 4h
group_by: ['alertname', 'cluster', 'service']
routes:
- match:
- receiver: 'critical'
match:
severity: critical
receiver: default
continue: true
repeat_interval: 1h
- receiver: 'default'
match:
severity: warning

receivers:
- name: default
# Uncomment and configure one of the following:
# webhook_configs:
# - url: http://gotify:80/message?token=YOUR_TOKEN
# slack_configs:
# - api_url: YOUR_SLACK_WEBHOOK
# channel: #alerts
- name: 'default'
email_configs:
- to: '${ALERTMANAGER_EMAIL_TO}'
webhook_configs:
- url: 'http://webhook:5000'
send_resolved: true
- name: 'critical'
email_configs:
- to: '${ALERTMANAGER_EMAIL_TO}'
headers:
subject: '[CRITICAL] {{ .GroupLabels.alertname }}'
webhook_configs:
- url: 'http://webhook:5000'
send_resolved: true

inhibit_rules:
- source_match:
severity: critical
severity: 'critical'
target_match:
severity: warning
equal: [alertname, instance]
severity: 'warning'
equal: ['alertname', 'instance']
9 changes: 9 additions & 0 deletions config/grafana/dashboards/node-exporter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"title": "Node Exporter Full",
"uid": "node-exporter-full",
"schemaVersion": 36,
"version": 1,
"panels": [],
"templating": {},
"time": {}
}
10 changes: 5 additions & 5 deletions config/grafana/provisioning/dashboards/dashboards.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Grafana dashboards provisioning
apiVersion: 1

providers:
- name: homelab
- name: Default
orgId: 1
folder: HomeLab
folder: ''
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: true
editable: true
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true
12 changes: 12 additions & 0 deletions config/grafana/provisioning/dashboards/default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: 1

providers:
- name: 'Default'
orgId: 1
folder: ''
type: file
disableDeletion: true
editable: false
allowUiUpdates: false
options:
path: /var/lib/grafana/dashboards
14 changes: 10 additions & 4 deletions config/grafana/provisioning/datasources/datasources.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
# Grafana datasources provisioning
apiVersion: 1

datasources:
- name: Prometheus
type: prometheus
uid: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false
jsonData:
timeInterval: 15s

- name: Loki
type: loki
uid: loki
access: proxy
url: http://loki:3100
editable: false
jsonData:
maxLines: 1000

- name: Tempo
type: tempo
access: proxy
url: http://tempo:3200
editable: false
10 changes: 10 additions & 0 deletions config/grafana/provisioning/datasources/loki.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: 1

datasources:
- name: Loki
type: loki
access: proxy
url: http://loki:3100
jsonData:
maxLines: 1000
editable: false
9 changes: 9 additions & 0 deletions config/grafana/provisioning/datasources/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: 1

datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false
14 changes: 14 additions & 0 deletions config/grafana/provisioning/datasources/tempo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: 1

datasources:
- name: Tempo
type: tempo
access: proxy
url: http://tempo:3200
jsonData:
httpMethod: GET
serviceMap:
datasourceUid: Prometheus
nodeGraph:
enabled: true
editable: false
Loading