diff --git a/BOUNTY.md b/BOUNTY.md index 6fc1e0f1..31bb7d37 100644 --- a/BOUNTY.md +++ b/BOUNTY.md @@ -10,7 +10,7 @@ | 2 | [Media Stack — Jellyfin + Sonarr + Radarr + qBittorrent](https://github.com/illbnm/homelab-stack/issues/2) | 🟡 Medium | $160 | 🟢 Open | | 3 | [Storage Stack — Nextcloud + MinIO + FileBrowser](https://github.com/illbnm/homelab-stack/issues/3) | 🟡 Medium | $150 | 🟢 Open | | 4 | [Network Stack — AdGuard + WireGuard + Nginx Proxy Manager](https://github.com/illbnm/homelab-stack/issues/4) | 🟡 Medium | $140 | 🟢 Open | -| 5 | [Productivity Stack — Gitea + Vaultwarden + Outline + BookStack](https://github.com/illbnm/homelab-stack/issues/5) | 🟡 Medium | $170 | 🟢 Open | +| 5 | [Productivity Stack — Gitea + Vaultwarden + Outline + Stirling PDF + Excalidraw](https://github.com/illbnm/homelab-stack/issues/5) | 🟡 Medium | $170 | 🟢 Open | | 6 | [AI Stack — Ollama + Open WebUI + Stable Diffusion](https://github.com/illbnm/homelab-stack/issues/6) | 🔴 Hard | $220 | 🟢 Open | | 7 | [Home Automation — Home Assistant + Node-RED + Zigbee2MQTT](https://github.com/illbnm/homelab-stack/issues/7) | 🟡 Medium | $130 | 🟢 Open | | 8 | [Robustness — 国内网络适配 + 环境鲁棒性](https://github.com/illbnm/homelab-stack/issues/8) | 🔴 Hard | $250 | 🟢 Open | diff --git a/homelab.md b/homelab.md index 0d7f909f..3f020af0 100644 --- a/homelab.md +++ b/homelab.md @@ -71,7 +71,7 @@ homelab-redis Outline/Nextcloud cache")] MariaDB[("MariaDB 11.4 homelab-mariadb -BookStack")] +")\] end subgraph ObsLayer["Observability -- monitoring Stack"] @@ -112,8 +112,10 @@ git.DOMAIN"] vault.DOMAIN"] Outline["Outline 0.80.2 docs.DOMAIN"] - BookStack["BookStack 24.10 -books.DOMAIN"] + StirlingPDF["Stirling PDF 0.30.2 +pdf.DOMAIN"] + Excalidraw["Excalidraw latest-sha +draw.DOMAIN"] end subgraph StorageLayer["Storage Stack"] @@ -177,7 +179,8 @@ home.DOMAIN"] Traefik --> Gitea Traefik --> Vault Traefik --> Outline - Traefik --> BookStack + Traefik --> StirlingPDF + Traefik --> Excalidraw Traefik --> Nextcloud Traefik --> Jellyfin Traefik --> Ollama @@ -193,14 +196,12 @@ home.DOMAIN"] Grafana -->|OIDC| Authentik Outline -->|OIDC| Authentik - BookStack -->|OIDC| Authentik Gitea -->|OAuth2| Authentik Gitea --- PG Vault --- PG Outline --- PG Outline --- Redis - BookStack --- MariaDB Nextcloud --- PG Nextcloud --- Redis @@ -261,11 +262,11 @@ databases ─────────────────────── └─ creates: databases network │ └─ homelab-postgres:5432 ───────────────┼─> gitea, vaultwarden, outline, nextcloud └─ homelab-redis:6379 ──────────────────┼─> outline, nextcloud - └─ homelab-mariadb:3306 ────────────────┼─> bookstack + └─ homelab-mariadb:3306 ────────────────┼─> │ sso (Authentik) ────────────────────────────┤ └─ own postgres + redis (isolated) │ - └─ OIDC provider ───────────────────────┼─> grafana, outline, bookstack + └─ OIDC provider ───────────────────────┼─> grafana, outline └─ OAuth2 provider ─────────────────────┼─> gitea └─ ForwardAuth middleware ──────────────┼─> traefik (all routes) │ @@ -323,7 +324,6 @@ sequenceDiagram |---------|-----------|-------|---------------| | Grafana | Generic OAuth2 | openid profile email | Yes (role via groups) | | Outline | OIDC | openid profile email | Yes | -| BookStack | OIDC | openid profile email | Yes | | Gitea | OAuth2 provider | openid profile email | Yes | | Portainer | ForwardAuth | N/A | Manual first login | | Vaultwarden | ForwardAuth (admin only) | N/A | N/A | @@ -411,7 +411,7 @@ CN mirror: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/goauthentik/server:2 |---------|---------------|------|---------| | PostgreSQL | homelab-postgres | 5432 | Gitea, Vaultwarden, Outline, Nextcloud | | Redis | homelab-redis | 6379 | Outline, Nextcloud | -| MariaDB | homelab-mariadb | 3306 | BookStack | +| MariaDB | homelab-mariadb | 3306 | - | ### monitoring | Service | Image | URL | @@ -430,7 +430,8 @@ CN mirror: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/goauthentik/server:2 | Gitea | gitea/gitea:1.22.3 | git.DOMAIN | homelab-postgres | OAuth2 | | Vaultwarden | vaultwarden/server:1.32.0 | vault.DOMAIN | homelab-postgres | ForwardAuth | | Outline | outlinewiki/outline:0.80.2 | docs.DOMAIN | homelab-postgres+redis | OIDC | -| BookStack | linuxserver/bookstack:24.10 | books.DOMAIN | homelab-mariadb | OIDC | +| Stirling PDF | frooodle/s-pdf:0.30.2 | pdf.DOMAIN | - | ForwardAuth | +| Excalidraw | excalidraw/excalidraw:latest-sha | draw.DOMAIN | - | ForwardAuth | Networks: proxy + databases @@ -522,7 +523,8 @@ Integrations: Alertmanager/Node-RED -> ntfy; Apprise -> multi-channel | git.DOMAIN | Gitea | productivity | | vault.DOMAIN | Vaultwarden | productivity | | docs.DOMAIN | Outline | productivity | -| books.DOMAIN | BookStack | productivity | +| pdf.DOMAIN | Stirling PDF | productivity | +| draw.DOMAIN | Excalidraw | productivity | | nextcloud.DOMAIN | Nextcloud | storage | | minio.DOMAIN | MinIO | storage | | files.DOMAIN | FileBrowser | storage | diff --git a/stacks/databases/.env.example b/stacks/databases/.env.example index ca52ed66..806a51bb 100644 --- a/stacks/databases/.env.example +++ b/stacks/databases/.env.example @@ -9,4 +9,4 @@ NEXTCLOUD_DB_PASSWORD=CHANGE_ME GITEA_DB_PASSWORD=CHANGE_ME OUTLINE_DB_PASSWORD=CHANGE_ME VAULTWARDEN_DB_PASSWORD=CHANGE_ME -BOOKSTACK_DB_PASSWORD=CHANGE_ME + diff --git a/stacks/databases/initdb-mysql/01-init-databases.sql b/stacks/databases/initdb-mysql/01-init-databases.sql index a94dff76..8f74cebb 100644 --- a/stacks/databases/initdb-mysql/01-init-databases.sql +++ b/stacks/databases/initdb-mysql/01-init-databases.sql @@ -1,9 +1,7 @@ -- HomeLab MariaDB init -- Creates databases for services that prefer MySQL/MariaDB -CREATE DATABASE IF NOT EXISTS `bookstack` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -CREATE USER IF NOT EXISTS 'bookstack'@'%' IDENTIFIED BY '${BOOKSTACK_DB_PASSWORD:-changeme}'; -GRANT ALL PRIVILEGES ON `bookstack`.* TO 'bookstack'@'%'; + CREATE DATABASE IF NOT EXISTS `nextcloud_mysql` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER IF NOT EXISTS 'nextcloud'@'%' IDENTIFIED BY '${NEXTCLOUD_DB_PASSWORD:-changeme}'; diff --git a/stacks/databases/initdb/01-init-databases.sh b/stacks/databases/initdb/01-init-databases.sh index f0638a7c..cafe639e 100644 --- a/stacks/databases/initdb/01-init-databases.sh +++ b/stacks/databases/initdb/01-init-databases.sh @@ -30,10 +30,7 @@ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-E CREATE DATABASE vaultwarden OWNER vaultwarden ENCODING 'UTF8'; GRANT ALL PRIVILEGES ON DATABASE vaultwarden TO vaultwarden; - -- BookStack - CREATE USER bookstack WITH PASSWORD '${BOOKSTACK_DB_PASSWORD:-changeme_bookstack}'; - CREATE DATABASE bookstack OWNER bookstack ENCODING 'UTF8'; - GRANT ALL PRIVILEGES ON DATABASE bookstack TO bookstack; + EOSQL echo "[init-postgres] All databases created successfully" diff --git a/stacks/productivity/.env.example b/stacks/productivity/.env.example index 79c59178..93045c9b 100644 --- a/stacks/productivity/.env.example +++ b/stacks/productivity/.env.example @@ -1,4 +1,4 @@ -# Productivity Stack Environment Variables +# Productivity Stack - Environment Variables # Copy to .env and fill ALL values before running. DOMAIN=yourdomain.com @@ -11,28 +11,29 @@ AUTHENTIK_DOMAIN=auth.yourdomain.com GITEA_DB_PASSWORD= VAULTWARDEN_DB_PASSWORD= OUTLINE_DB_PASSWORD= -BOOKSTACK_DB_PASSWORD= # Redis password (must match databases stack .env) REDIS_PASSWORD= -# Secrets generate with: openssl rand -hex 32 +# Secrets - generate with: openssl rand -hex 32 VAULTWARDEN_ADMIN_TOKEN= OUTLINE_SECRET_KEY= OUTLINE_UTILS_SECRET= GITEA_OAUTH2_JWT_SECRET= +GITEA_RUNNER_TOKEN= -# BookStack generate APP_KEY with: echo "base64:$(openssl rand -base64 32)" -BOOKSTACK_APP_KEY= -# Set to 'oidc' to enable SSO (requires OIDC vars below) -BOOKSTACK_AUTH_METHOD=standard +# MinIO S3 credentials for Outline +MINIO_ROOT_USER=minioadmin +MINIO_ROOT_PASSWORD=changeme-minio -# OAuth2 client credentials filled by scripts/setup-authentik.sh -GRAFANA_OAUTH_CLIENT_ID= -GRAFANA_OAUTH_CLIENT_SECRET= +# SMTP configuration for Vaultwarden +SMTP_HOST= +SMTP_PORT=587 +SMTP_USER= +SMTP_PASS= + +# OAuth2 client credentials - filled by scripts/setup-authentik.sh GITEA_OAUTH_CLIENT_ID= GITEA_OAUTH_CLIENT_SECRET= OUTLINE_OAUTH_CLIENT_ID= OUTLINE_OAUTH_CLIENT_SECRET= -BOOKSTACK_OIDC_CLIENT_ID= -BOOKSTACK_OIDC_CLIENT_SECRET= diff --git a/stacks/productivity/docker-compose.yml b/stacks/productivity/docker-compose.yml index 4b295a98..a11029ae 100644 --- a/stacks/productivity/docker-compose.yml +++ b/stacks/productivity/docker-compose.yml @@ -1,6 +1,8 @@ services: gitea: - image: gitea/gitea:1.22.3 + image: gitea/gitea:1.22.2 + # CN mirror fallback (uncomment if inaccessible): + # image: docker.m.daocloud.io/gitea/gitea:1.22.2 container_name: gitea restart: unless-stopped networks: @@ -18,6 +20,7 @@ services: - GITEA__server__ROOT_URL=https://git.${DOMAIN} - GITEA__server__HTTP_PORT=3000 - GITEA__security__INSTALL_LOCK=true + - GITEA__service__DISABLE_REGISTRATION=true - GITEA__mailer__ENABLED=false - GITEA__oauth2__ENABLE=true - GITEA__oauth2__JWT_SECRET=${GITEA_OAUTH2_JWT_SECRET} @@ -36,8 +39,27 @@ services: retries: 3 start_period: 60s + gitea-runner: + image: gitea/act_runner:nightly + # CN mirror fallback (uncomment if inaccessible): + # image: docker.m.daocloud.io/gitea/act_runner:nightly + container_name: gitea-runner + restart: unless-stopped + networks: + - proxy + - databases + environment: + - GITEA_INSTANCE_URL=https://git.${DOMAIN} + - GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_TOKEN} + - GITEA_RUNNER_NAME=homelab-runner + volumes: + - gitea-runner-data:/data + - /var/run/docker.sock:/var/run/docker.sock + vaultwarden: image: vaultwarden/server:1.32.0 + # CN mirror fallback (uncomment if inaccessible): + # image: docker.m.daocloud.io/vaultwarden/server:1.32.0 container_name: vaultwarden restart: unless-stopped networks: @@ -50,6 +72,13 @@ services: - DATABASE_URL=postgresql://vaultwarden:${VAULTWARDEN_DB_PASSWORD}@homelab-postgres:5432/vaultwarden - LOG_LEVEL=warn - TZ=${TZ} + - SMTP_HOST=${SMTP_HOST} + - SMTP_PORT=${SMTP_PORT} + - SMTP_SECURITY=starttls + - SMTP_USERNAME=${SMTP_USER} + - SMTP_PASSWORD=${SMTP_PASS} + - SMTP_FROM=vaultwarden@${DOMAIN} + - SMTP_FROM_NAME=Vaultwarden volumes: - vaultwarden-data:/data labels: @@ -67,6 +96,8 @@ services: outline: image: outlinewiki/outline:0.80.2 + # CN mirror fallback (uncomment if inaccessible): + # image: docker.m.daocloud.io/outlinewiki/outline:0.80.2 container_name: outline restart: unless-stopped networks: @@ -88,11 +119,14 @@ services: - OIDC_LOGOUT_URI=https://${AUTHENTIK_DOMAIN}/application/o/outline/end-session/ - OIDC_DISPLAY_NAME=Authentik - OIDC_SCOPES=openid profile email - - FILE_STORAGE=local - - FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data - - FILE_STORAGE_UPLOAD_MAX_SIZE=26214400 - volumes: - - outline-data:/var/lib/outline/data + - FILE_STORAGE=s3 + - AWS_ACCESS_KEY_ID=${MINIO_ROOT_USER:-minioadmin} + - AWS_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD:-changeme-minio} + - AWS_REGION=us-east-1 + - AWS_S3_UPLOAD_BUCKET_URL=https://s3.${DOMAIN} + - AWS_S3_UPLOAD_BUCKET_NAME=outline + - AWS_S3_FORCE_PATH_STYLE=true + - AWS_S3_ACL=private labels: - traefik.enable=true - "traefik.http.routers.outline.rule=Host(`docs.${DOMAIN}`)" @@ -106,44 +140,42 @@ services: retries: 3 start_period: 60s - bookstack: - image: lscr.io/linuxserver/bookstack:24.10.20241031 - container_name: bookstack + stirling-pdf: + image: frooodle/s-pdf:0.30.2 + # CN mirror fallback (uncomment if inaccessible): + # image: docker.m.daocloud.io/frooodle/s-pdf:0.30.2 + container_name: stirling-pdf restart: unless-stopped networks: - proxy - - databases environment: - - PUID=1000 - - PGID=1000 - - TZ=${TZ} - - APP_URL=https://wiki.${DOMAIN} - - APP_KEY=${BOOKSTACK_APP_KEY} - - DB_HOST=homelab-mariadb - - DB_PORT=3306 - - DB_DATABASE=bookstack - - DB_USERNAME=bookstack - - DB_PASSWORD=${BOOKSTACK_DB_PASSWORD} - - AUTH_METHOD=${BOOKSTACK_AUTH_METHOD:-standard} - - OIDC_CLIENT_ID=${BOOKSTACK_OIDC_CLIENT_ID} - - OIDC_CLIENT_SECRET=${BOOKSTACK_OIDC_CLIENT_SECRET} - - OIDC_ISSUER=https://${AUTHENTIK_DOMAIN}/application/o/bookstack/ - - OIDC_NAME=Authentik - - OIDC_DUMP_USER_DETAILS=false + - DOCKER_ENABLE_SECURITY=false + - TZ=${TZ:-Asia/Shanghai} volumes: - - bookstack-data:/config + - stirling-pdf-trainingData:/usr/share/tesseract-ocr/4.00/tessdata + - stirling-pdf-extraConfigs:/configs + - stirling-pdf-customFiles:/customFiles labels: - traefik.enable=true - - "traefik.http.routers.bookstack.rule=Host(`wiki.${DOMAIN}`)" - - traefik.http.routers.bookstack.entrypoints=websecure - - traefik.http.routers.bookstack.tls=true - - traefik.http.services.bookstack.loadbalancer.server.port=80 - healthcheck: - test: [CMD, wget, -qO-, http://localhost:80/login] - interval: 30s - timeout: 10s - retries: 3 - start_period: 60s + - "traefik.http.routers.stirling-pdf.rule=Host(`pdf.${DOMAIN}`)" + - traefik.http.routers.stirling-pdf.entrypoints=websecure + - traefik.http.routers.stirling-pdf.tls=true + - traefik.http.services.stirling-pdf.loadbalancer.server.port=8080 + + excalidraw: + image: excalidraw/excalidraw:latest-sha + # CN mirror fallback (uncomment if inaccessible): + # image: docker.m.daocloud.io/excalidraw/excalidraw:latest-sha + container_name: excalidraw + restart: unless-stopped + networks: + - proxy + labels: + - traefik.enable=true + - "traefik.http.routers.excalidraw.rule=Host(`draw.${DOMAIN}`)" + - traefik.http.routers.excalidraw.entrypoints=websecure + - traefik.http.routers.excalidraw.tls=true + - traefik.http.services.excalidraw.loadbalancer.server.port=80 networks: proxy: @@ -153,6 +185,8 @@ networks: volumes: gitea-data: + gitea-runner-data: vaultwarden-data: - outline-data: - bookstack-data: + stirling-pdf-trainingData: + stirling-pdf-extraConfigs: + stirling-pdf-customFiles: