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
149 changes: 42 additions & 107 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,122 +1,57 @@
# =============================================================================
# HomeLab Stack — Environment Configuration
# Copy this file to .env and fill in your values
# Run: cp .env.example .env && ./scripts/setup-env.sh
# Homelab Stack — Environment Configuration
# =============================================================================

# -----------------------------------------------------------------------------
# GENERAL
# -----------------------------------------------------------------------------
# ── General ──────────────────────────────────────────────────────────────────
DOMAIN=home.example.com
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
CN_MODE=false

# -----------------------------------------------------------------------------
# TRAEFIK
# -----------------------------------------------------------------------------
# ── Traefik (proxy) ────────────────────────────────────────────────────────────
ACME_EMAIL=admin@example.com
TRAEFIK_DASHBOARD_USER=admin
# Generate password hash: echo $(htpasswd -nb admin yourpassword) | sed -e s/\$/\$\$/g
TRAEFIK_DASHBOARD_PASSWORD_HASH=

# -----------------------------------------------------------------------------
# PORTAINER
# -----------------------------------------------------------------------------
# No config needed — admin password set on first login

# -----------------------------------------------------------------------------
# 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}

# OAuth2 clients — auto-filled by scripts/setup-authentik.sh
GRAFANA_OAUTH_CLIENT_ID=
GRAFANA_OAUTH_CLIENT_SECRET=
GITEA_OAUTH_CLIENT_ID=
GITEA_OAUTH_CLIENT_SECRET=
# ── Portainer ─────────────────────────────────────────────────────────────────
PORTAINER_ADMIN_PASSWORD=changeme

# ── Databases ────────────────────────────────────────────────────────────────
POSTGRES_ROOT_PASSWORD=changeme
REDIS_PASSWORD=changeme
MARIADB_ROOT_PASSWORD=changeme

# ── Productivity Stack ───────────────────────────────────────────────────────
GITEA_DB_PASSWORD=changeme
GITEA_OAUTH2_JWT_SECRET=changeme
VAULTWARDEN_ADMIN_TOKEN=changeme
VAULTWARDEN_DB_PASSWORD=changeme
OUTLINE_SECRET_KEY=changeme
OUTLINE_UTILS_SECRET=changeme
OUTLINE_DB_PASSWORD=changeme
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
BOOKSTACK_APP_KEY=base64:changeme
BOOKSTACK_DB_PASSWORD=changeme
BOOKSTACK_AUTH_METHOD=standard
BOOKSTACK_OIDC_CLIENT_ID=
BOOKSTACK_OIDC_CLIENT_SECRET=

# Per-service database credentials
GITEA_DB_PASSWORD=
NEXTCLOUD_DB_PASSWORD=
OUTLINE_DB_PASSWORD=
AUTHENTIK_DB_PASSWORD=
# ── AI Stack ────────────────────────────────────────────────────────────────
WEBUI_SECRET_KEY=changeme

# -----------------------------------------------------------------------------
# GRAFANA
# -----------------------------------------------------------------------------
# ── Monitoring Stack ──────────────────────────────────────────────────────────
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
GRAFANA_ADMIN_PASSWORD=changeme
GRAFANA_OAUTH_CLIENT_ID=
GRAFANA_OAUTH_CLIENT_SECRET=

# -----------------------------------------------------------------------------
# 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
# ── Authentik (SSO) ─────────────────────────────────────────────────────────
AUTHENTIK_DOMAIN=sso.example.com
AUTHENTIK_SECRET_KEY=changeme
AUTHENTIK_ERROR_REPORTING=false
AUTHENTIK_POSTGRESQL__PASSWORD=changeme
AUTHENTIK_REDIS__PASSWORD=changeme

# -----------------------------------------------------------------------------
# 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
# ── Backup Stack ────────────────────────────────────────────────────────────
DUPLICATI_PASSWORD=changeme
RESTIC_PASSWORD=changeme
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