Compare commits

...

4 Commits

Author SHA1 Message Date
James Thompson
6fb3fc65e4 Add in cloudflare ddns and restructure repo 2026-05-19 08:30:25 +00:00
James Thompson
c546fab5e1 Get obidian live sync to work and add doc site 2026-03-23 08:01:38 +00:00
James Thompson
95bdab6b9d Get nextcloud working 2026-03-23 06:34:13 +00:00
James Thompson
28aa6e28fe Wokring traefik
With whoami and gitea working (although I haven't rebuilt yet)
2026-03-23 05:59:53 +00:00
39 changed files with 280 additions and 156 deletions

View File

@@ -4,7 +4,6 @@
# Storage
STORAGE_PATH=/mnt/storage/docker-data
MEDIA_PATH=/mnt/storage
# User
USER_UID=1000
@@ -12,7 +11,6 @@ USER_GID=1000
# Domain
DOMAIN=sjhl.nz
DOMAIN_WWW=__CHANGEME__
# Timezone
TZ=Pacific/Auckland

View File

@@ -7,3 +7,9 @@ repos:
language: system
pass_filenames: false
always_run: true
- id: build-docs-site
name: Build docs site
entry: make docs
language: system
pass_filenames: false
always_run: true

View File

@@ -1,35 +1,50 @@
SERVICES=traefik whoami gitea nextcloud devbox
SERVICES=traefik whoami gitea nextcloud devbox docs-site
SERVICES_DIR=services
.PHONY: up down restart backup init-env env-sync docs generate-docs serve-docs logs status
.PHONY: up down restart backup init-env env-sync docs generate-docs serve-docs logs status up-% down-%
up:
@for svc in $(SERVICES); do \
if [ -f "$$svc/docker-compose.yml" ]; then \
for svc in $(SERVICES); do \
if [ -f "$(SERVICES_DIR)/$$svc/docker-compose.yml" ]; then \
echo "Starting $$svc..."; \
(cd $$svc && docker compose up -d); \
(cd $(SERVICES_DIR)/$$svc && docker compose --env-file ../../.env `if [ -f .env ]; then echo --env-file .env; fi` up -d); \
fi; \
done
done; \
up-%:
@svc=$*; \
if [ -f "$(SERVICES_DIR)/$$svc/docker-compose.yml" ]; then \
echo "Starting $$svc..."; \
(cd $(SERVICES_DIR)/$$svc && docker compose --env-file ../../.env `if [ -f .env ]; then echo --env-file .env; fi` up -d); \
fi
down-%:
@svc=$*; \
if [ -f "$(SERVICES_DIR)/$$svc/docker-compose.yml" ]; then \
echo "Stopping $$svc..."; \
(cd $(SERVICES_DIR)/$$svc && docker compose down); \
fi
down:
@for svc in $(SERVICES); do \
if [ -f "$$svc/docker-compose.yml" ]; then \
if [ -f "$(SERVICES_DIR)/$$svc/docker-compose.yml" ]; then \
echo "Stopping $$svc..."; \
(cd $$svc && docker compose down); \
(cd $(SERVICES_DIR)/$$svc && docker compose down); \
fi; \
done
restart: down up
logs:
@echo "=== Traefik ===" && (cd traefik && docker compose logs --tail=10)
@echo "=== Gitea ===" && (cd gitea && docker compose logs --tail=10)
@echo "=== Nextcloud ===" && (cd nextcloud && docker compose logs --tail=10)
@echo "=== Traefik ===" && (cd $(SERVICES_DIR)/traefik && docker compose logs --tail=10)
@echo "=== Gitea ===" && (cd $(SERVICES_DIR)/gitea && docker compose logs --tail=10)
@echo "=== Nextcloud ===" && (cd $(SERVICES_DIR)/nextcloud && docker compose logs --tail=10)
status:
@for svc in $(SERVICES); do \
if [ -f "$$svc/docker-compose.yml" ]; then \
if [ -f "$(SERVICES_DIR)/$$svc/docker-compose.yml" ]; then \
echo "--- $$svc ---"; \
(cd $$svc && docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"); \
(cd $(SERVICES_DIR)/$$svc && docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"); \
fi; \
done

View File

@@ -1,3 +1,7 @@
> ⚠️ **Early development**
>
> This project is in early development and not all features are working yet. Use with caution.
# homelab-infra
GitOps-managed infrastructure for homelab services using Docker Compose and Traefik for routing.
@@ -28,7 +32,7 @@ Currently includes: Gitea (Git hosting), Nextcloud (cloud storage), Devbox (deve
## Documentation
Full documentation is available at the [MkDocs site](https://homelab.sjhl.nz) or build locally with `make docs`.
Full documentation is available at the [MkDocs site](https://docs.sjhl.nz) or build locally with `make docs`.
## Directory Structure
@@ -39,7 +43,8 @@ homelab-infra/
├── docs/ # MkDocs documentation source
├── mkdocs.yml # MkDocs configuration
├── scripts/ # Utility scripts
└── [service]/ # Per-service configurations
└── services/ # Per-service configurations
└── [service]/
├── docker-compose.yml
├── .env.example
└── README.md

View File

@@ -1,5 +0,0 @@
# check_env_sync
> Python script documentation
::: scripts.check_env_sync

View File

@@ -1,5 +0,0 @@
# generate_docs
> Python script documentation
::: scripts.generate_docs

View File

@@ -1,5 +1,8 @@
# SJHL Documentation
!!! warning "Early development"
This documentation is in early development and not all features are working yet. Use with caution.
Welcome to Seirian & James' homelab documentation! This is a docs site that is built to easily show all the configs we use. MOst of the content is auto-generated from the actual config files, so it should always be up to date. This should be completely publically viewable as all private information is kept in `.env` files that are not committed to Git. It should provide good information on how to recover and rebuild the homelab if needed, and also just be a nice reference for how everything is configured.
## Data Classification
@@ -7,7 +10,7 @@ Welcome to Seirian & James' homelab documentation! This is a docs site that is b
| Type | Example | Git Repo? | Backup? | Location |
|------|---------|-----------|---------|----------|
| **Source Configs** | `docker-compose.yml`, `.env.example`, `Makefile` | Yes | No | `/srv/homelab-infra` |
| **Service Secrets** | `.env` (DB passwords, API keys) | No | Yes | `/srv/homelab-infra/<service>/.env` |
| **Service Secrets** | `.env` (DB passwords, API keys) | No | Yes | `/srv/homelab-infra/services/<service>/.env` |
| **Runtime Configs** | `acme.json`, service configs | No | Yes | `/mnt/storage/docker-data/<service>` |
| **Persistent Data** | DB data, uploads, media | No | Yes | `/mnt/storage/docker-data/<service>` |
@@ -15,7 +18,9 @@ Welcome to Seirian & James' homelab documentation! This is a docs site that is b
| Service | Image | Status |
|---------|-------|--------|
| [cloudflare-ddns](services/cloudflare-ddns.md) | `favonia/cloudflare-ddns:1` | active |
| [devbox](services/devbox.md) | `devbox-devcontainer` | active |
| [docs-site](services/docs-site.md) | `nginx:alpine` | active |
| [gitea](services/gitea.md) | `gitea/gitea:1.24.3` | active |
| [nextcloud](services/nextcloud.md) | `ghcr.io/nextcloud-releases/all-in-one:latest` | active |
| [obsidian-livesync](services/obsidian-livesync.md) | `couchdb:latest` | active |
@@ -28,21 +33,21 @@ Welcome to Seirian & James' homelab documentation! This is a docs site that is b
git clone git@gitea.sjhl.nz:james/homelab-infra.git
cd homelab-infra
# Set up environment
cp .env.example .env
# Edit .env with real values
# Create all missing .env files from templates
make init-env
# Set up service secrets
for svc in traefik gitea nextcloud qbittorrent jellyfin devbox obsidian; do
[ -f "$svc/.env.example" ] && cp "$svc/.env.example" "$svc/.env"
# Edit each .env with real secrets
done
# Edit .env and services/*/.env with real secrets
# Create required Docker networks
docker network create web
# Start everything
# Start and verify everything
make up
make status
# Optional: start/stop one service
# make up-<service>
# make down-<service>
```
## Commands
@@ -115,7 +120,11 @@ homelab-infra/
├── docs/ # MkDocs documentation
├── mkdocs.yml # MkDocs config
├── scripts/ # Utility scripts
└── [service subdirs]/ # All services have their own subdir
└── services/ # Service definitions
└── <service>/ # One folder per service
├── docker-compose.yml
├── .env.example
└── README.md
```
## Data Locations

View File

@@ -1,66 +0,0 @@
# Recovery Reference
This document was generated from `docker inspect` dumps taken after the accidental deletion of `/home/james`. It preserves the last known-good configuration state for rebuilding services.
## Container Summary
### traefik (Reverse Proxy)
- **Image:** `traefik:v3.6`
- **Config path (old):** `/home/james/apps/traefik/`
- **Volumes:** certs, dynamic config, docker.sock (ro)
- **Networks:** `web` (external)
- **Ports:** 80, 443, 8082->8080
- **Let's Encrypt:** HTTP challenge, email `letsencrypt.debug772@passmail.net`
### gitea
- **Image:** `gitea/gitea:1.24.3`
- **Data path (old):** `/mnt/storage/apps/gitea`
- **DB:** SQLite3
- **SSH:** port 222
- **URL:** `https://gitea.sjhl.nz/`
### nextcloud (AIO)
- **Image:** `ghcr.io/nextcloud-releases/all-in-one:latest`
- **Data path (old):** `/mnt/storage/apps/nextcloud`
- **Components:** mastercontainer, apache, nextcloud, database (PostgreSQL 17), redis, collabora, imaginary, whiteboard, notify-push
- **URL:** `https://nextcloud.sjhl.nz`
- **AIO mgmt:** port 8081
- **Apache port:** 11000
### qbittorrent + VPN
- **VPN:** ProtonVPN WireGuard, New Zealand, port forwarding
- **Data path (old):** `/home/james/apps/qbittorrent/`
- **Downloads:** `/mnt/storage/torrents`
- **Components:** gluetun, qbittorrent, jackett
- **Ports:** 8080 (qBittorrent), 9117 (Jackett)
### jellyfin
- **Image:** `jellyfin/jellyfin:10.10.7`
- **Config path (old):** `/home/james/apps/jellyfin-config`
- **Media:** `/mnt/storage`
- **Port:** 8096
- **Network:** default bridge (NOT on `web` network)
- **Note:** Was not behind Traefik in old setup
### devbox
- **Image:** `devbox-devcontainer` (local build)
- **Data path (old):** `/mnt/storage/apps/devbox`
- **Port:** 46573->2222 (SSH)
- **Memory limit:** 10GB, swap 20GB
### obsidian-livesync
- **Image:** `couchdb:latest`
- **Status:** Exited (127) at time of backup
- **Note:** No inspect data captured, container was stopped
## Recovery Path Mapping
| Old Path | New Path |
|----------|----------|
| `/home/james/apps/traefik/` | `/mnt/storage/docker-data/traefik/` |
| `/home/james/apps/qbittorrent/` | `/mnt/storage/docker-data/qbittorrent/` |
| `/home/james/apps/jellyfin-config` | `/mnt/storage/docker-data/jellyfin/config` |
| `/mnt/storage/apps/gitea` | `/mnt/storage/docker-data/gitea` |
| `/mnt/storage/apps/nextcloud` | `/mnt/storage/docker-data/nextcloud` |
| `/mnt/storage/apps/devbox` | `/mnt/storage/docker-data/devbox` |
| `/mnt/storage/torrents` | `/mnt/storage/torrents` (unchanged) |

View File

@@ -0,0 +1,15 @@
# cloudflare-ddns
> Below are the configuration files for this service. For details on how to deploy or customize, refer to the README above or the official documentation for the service.
## Docker Compose Configuration
```yaml
--8<-- "services/cloudflare-ddns/docker-compose.yml"
```
## Environment Variables (`.env.example`)
```bash
--8<-- "services/cloudflare-ddns/.env.example"
```

View File

@@ -5,11 +5,11 @@
## Docker Compose Configuration
```yaml
--8<-- "devbox/docker-compose.yml"
--8<-- "services/devbox/docker-compose.yml"
```
## Environment Variables (`.env.example`)
```bash
--8<-- "devbox/.env.example"
--8<-- "services/devbox/.env.example"
```

View File

@@ -0,0 +1,10 @@
# docs-site
--8<-- "services/docs-site/README.md"
> Below are the configuration files for this service. For details on how to deploy or customize, refer to the README above or the official documentation for the service.
## Docker Compose Configuration
```yaml
--8<-- "services/docs-site/docker-compose.yml"
```

View File

@@ -5,11 +5,11 @@
## Docker Compose Configuration
```yaml
--8<-- "gitea/docker-compose.yml"
--8<-- "services/gitea/docker-compose.yml"
```
## Environment Variables (`.env.example`)
```bash
--8<-- "gitea/.env.example"
--8<-- "services/gitea/.env.example"
```

View File

@@ -5,11 +5,11 @@
## Docker Compose Configuration
```yaml
--8<-- "nextcloud/docker-compose.yml"
--8<-- "services/nextcloud/docker-compose.yml"
```
## Environment Variables (`.env.example`)
```bash
--8<-- "nextcloud/.env.example"
--8<-- "services/nextcloud/.env.example"
```

View File

@@ -1,15 +1,16 @@
# obsidian-livesync
--8<-- "services/obsidian-livesync/README.md"
> Below are the configuration files for this service. For details on how to deploy or customize, refer to the README above or the official documentation for the service.
## Docker Compose Configuration
```yaml
--8<-- "obsidian-livesync/docker-compose.yml"
--8<-- "services/obsidian-livesync/docker-compose.yml"
```
## Environment Variables (`.env.example`)
```bash
--8<-- "obsidian-livesync/.env.example"
--8<-- "services/obsidian-livesync/.env.example"
```

View File

@@ -1,16 +1,16 @@
# traefik
--8<-- "traefik/README.md"
--8<-- "services/traefik/README.md"
> Below are the configuration files for this service. For details on how to deploy or customize, refer to the README above or the official documentation for the service.
## Docker Compose Configuration
```yaml
--8<-- "traefik/docker-compose.yml"
--8<-- "services/traefik/docker-compose.yml"
```
## Environment Variables (`.env.example`)
```bash
--8<-- "traefik/.env.example"
--8<-- "services/traefik/.env.example"
```

View File

@@ -5,5 +5,5 @@
## Docker Compose Configuration
```yaml
--8<-- "whoami/docker-compose.yml"
--8<-- "services/whoami/docker-compose.yml"
```

View File

@@ -9,9 +9,10 @@ markdown_extensions:
- .
nav:
- Home: index.md
- Recovery Reference: recovery.md
- Services:
- Cloudflare Ddns: services/cloudflare-ddns.md
- Devbox: services/devbox.md
- Docs Site: services/docs-site.md
- Gitea: services/gitea.md
- Nextcloud: services/nextcloud.md
- Obsidian Livesync: services/obsidian-livesync.md

View File

@@ -1,15 +0,0 @@
services:
couchdb:
image: couchdb:latest
container_name: obsidian-livesync
restart: unless-stopped
ports:
- "${COUCHDB_PORT:-5984}:5984"
volumes:
- ${STORAGE_PATH}/obsidian:/opt/couchdb/data
env_file:
- ../.env
- .env
environment:
- COUCHDB_USER=${COUCHDB_USER:-admin}
- COUCHDB_PASSWORD=${COUCHDB_PASSWORD}

View File

@@ -4,12 +4,11 @@ Auto-generate markdown docs from docker-compose.yml files.
Usage: python3 scripts/generate_docs.py
"""
import yaml
import os
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).parent.parent
SERVICES_DIR = REPO_ROOT
SERVICES_DIR = REPO_ROOT / "services"
DOCS_DIR = REPO_ROOT / "docs" / "services"
DISPLAY_NAME_OVERRIDES = {
@@ -175,6 +174,8 @@ def format_security(sec):
def generate_service_md(service_name, service_dir):
"""Generate service doc that includes docker-compose.yml, Dockerfile, README, and .env.example."""
include_base = f"services/{service_dir.name}"
lines = []
lines.append(f"# {service_name}")
lines.append("")
@@ -183,7 +184,7 @@ def generate_service_md(service_name, service_dir):
# Include README.md first if exists
readme_path = service_dir / "README.md"
if readme_path.exists():
lines.append(f'--8<-- "{service_dir.name}/README.md"')
lines.append(f'--8<-- "{include_base}/README.md"')
lines.append("> Below are the configuration files for this service. For details on how to deploy or customize, refer to the README above or the official documentation for the service.")
# Include docker-compose.yml
@@ -192,7 +193,7 @@ def generate_service_md(service_name, service_dir):
lines.append("## Docker Compose Configuration")
lines.append("")
lines.append("```yaml")
lines.append(f'--8<-- "{service_dir.name}/docker-compose.yml"')
lines.append(f'--8<-- "{include_base}/docker-compose.yml"')
lines.append("```")
lines.append("")
@@ -202,7 +203,7 @@ def generate_service_md(service_name, service_dir):
lines.append("## Dockerfile")
lines.append("")
lines.append("```dockerfile")
lines.append(f'--8<-- "{service_dir.name}/Dockerfile"')
lines.append(f'--8<-- "{include_base}/Dockerfile"')
lines.append("```")
lines.append("")
@@ -212,7 +213,7 @@ def generate_service_md(service_name, service_dir):
lines.append("## Environment Variables (`.env.example`)")
lines.append("")
lines.append("```bash")
lines.append(f'--8<-- "{service_dir.name}/.env.example"')
lines.append(f'--8<-- "{include_base}/.env.example"')
lines.append("```")
lines.append("")
@@ -275,6 +276,10 @@ def cleanup_stale_service_docs(service_names):
def main():
if not SERVICES_DIR.exists():
print(f"Services directory not found: {SERVICES_DIR}", file=sys.stderr)
return
all_services = {}
# Find all service directories with docker-compose.yml
@@ -284,9 +289,6 @@ def main():
compose_file = item / "docker-compose.yml"
if not compose_file.exists():
continue
# Skip scripts/docs directories
if item.name in ("scripts", "docs", "__pycache__"):
continue
service_name = item.name
try:

View File

@@ -0,0 +1,6 @@
# cloudflare-ddns/.env
# Copy to .env and fill in real values. NEVER commit .env.
CLOUDFLARE_API_TOKEN=__CHANGEME__
DOMAINS=example.org,www.example.org
PROXIED=true

View File

@@ -0,0 +1,34 @@
services:
cloudflare-ddns:
image: favonia/cloudflare-ddns:1
# Prefer "1" or "1.x.y" in production.
#
# - "1" tracks the latest stable release whose major version is 1
# - "1.x.y" pins one specific stable version
# - "latest" moves to each new stable release and may pick up breaking
# changes in a future major release, so it is not recommended in production
# - "edge" tracks the latest unreleased development build
network_mode: host
# Optional. This bypasses network isolation and makes IPv6 easier.
# See "Use IPv6 without sharing the host network".
restart: always
# Restart the updater after reboot
user: "1000:1000"
# Run the updater with specific user and group IDs (in that order).
# You can change the two numbers based on your need.
read_only: true
# Make the container filesystem read-only (optional but recommended)
cap_drop: [all]
# Drop all Linux capabilities (optional but recommended)
security_opt: [no-new-privileges:true]
# Another protection to restrict superuser privileges (optional but recommended)
env_file:
- .env
environment:
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
# Your Cloudflare API token
- DOMAINS=${DOMAINS}
# Your domains (separated by commas)
- PROXIED=${PROXIED:-true}
# Leaning toward using Cloudflare's proxy for these domains (optional)
# Existing DNS records in Cloudflare keep their current proxy statuses

View File

@@ -0,0 +1,7 @@
Serves the generated MkDocs static output from `../site` using NGINX.
Routing is handled by Traefik with host `docs.${DOMAIN}`.
Deploy flow:
1. Build docs: `make docs`
2. Start container: `make up-docs-site` (or `make up`)

View File

@@ -0,0 +1,20 @@
services:
docs-site:
image: nginx:alpine
container_name: docs-site
restart: unless-stopped
volumes:
- ../site:/usr/share/nginx/html:ro
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.http.routers.docs-site.entrypoints=websecure"
- "traefik.http.routers.docs-site.rule=Host(`docs.${DOMAIN}`)"
- "traefik.http.routers.docs-site.tls=true"
- "traefik.http.routers.docs-site.tls.certresolver=letsencrypt"
- "traefik.http.services.docs-site.loadbalancer.server.port=80"
networks:
web:
external: true

View File

@@ -4,7 +4,7 @@ services:
container_name: nextcloud-aio-mastercontainer
restart: always
ports:
- "${AIO_PORT:-8081}:8080"
- "${AIO_PORT}:8080"
volumes:
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
- /var/run/docker.sock:/var/run/docker.sock:ro
@@ -15,8 +15,6 @@ services:
networks:
- nextcloud-aio
- web
env_file:
- ../.env
volumes:
nextcloud_aio_mastercontainer:
@@ -25,3 +23,5 @@ networks:
nextcloud-aio:
web:
external: true

View File

@@ -3,4 +3,3 @@
COUCHDB_USER=admin
COUCHDB_PASSWORD=REPLACE_WITH_STRONG_PASSWORD
COUCHDB_PORT=5984

View File

@@ -0,0 +1 @@
*Note*: When setting up for the first time you need to create the directories for both the etc and the data and make sure they are owned by the same UID as the CouchDB container (default 5984) to avoid permission issues.

View File

@@ -0,0 +1,38 @@
services:
couchdb:
image: couchdb:latest
container_name: obsidian-livesync
restart: unless-stopped
environment:
- COUCHDB_USER=${COUCHDB_USER}
- COUCHDB_PASSWORD=${COUCHDB_PASSWORD}
volumes:
- ${STORAGE_PATH}/obsidian-livesync/data:/opt/couchdb/data
- ${STORAGE_PATH}/obsidian-livesync/local.ini:/opt/couchdb/etc/local.d
ports:
- 5984:5984
labels:
- "traefik.enable=true"
# The Traefik Network
- "traefik.docker.network=web"
# Don't forget to replace 'obsidian-livesync.example.org' with your own domain
- "traefik.http.routers.obsidian-livesync.rule=Host(`obsidian-livesync.${DOMAIN}`)"
# The 'websecure' entryPoint is basically your HTTPS entrypoint. Check the next code snippet if you are encountering problems only; you probably have a working traefik configuration if this is not your first container you are reverse proxying.
- "traefik.http.routers.obsidian-livesync.entrypoints=websecure"
- "traefik.http.routers.obsidian-livesync.service=obsidian-livesync"
- "traefik.http.services.obsidian-livesync.loadbalancer.server.port=5984"
- "traefik.http.routers.obsidian-livesync.tls=true"
# Replace the string 'letsencrypt' with your own certificate resolver
- "traefik.http.routers.obsidian-livesync.tls.certresolver=letsencrypt"
- "traefik.http.middlewares.obsidiancors.headers.accessControlAllowOriginList=app://obsidian.md,capacitor://localhost,http://localhost"
- "traefik.http.middlewares.obsidiancors.headers.accessControlAllowMethods=GET,POST,PUT,DELETE,OPTIONS,HEAD"
- "traefik.http.middlewares.obsidiancors.headers.accessControlAllowHeaders=Authorization,Content-Type,Accept,Origin,X-Requested-With"
- "traefik.http.middlewares.obsidiancors.headers.accessControlAllowCredentials=true"
- "traefik.http.middlewares.obsidiancors.headers.accessControlMaxAge=86400"
- "traefik.http.middlewares.obsidiancors.headers.addVaryHeader=true"
- "traefik.http.routers.obsidian-livesync.middlewares=obsidiancors"
networks:
- web
networks:
web:
external: true

View File

@@ -1,6 +1,6 @@
# traefik/.env
# Copy to .env and fill in real values. NEVER commit .env.
TRAEFIK_DASHBOARD_PORT=8082
TRAEFIK_DASHBOARD_PORT=8080
ACME_EMAIL=letsencrypt@example.com
DASHBOARD_BASIC_AUTH=admin:$$apr1$$changeme$$REPLACE_WITH_HTPASSWD_HASH

View File

@@ -0,0 +1 @@
This is the core proxy that protects my server. It handles SSL termination, routing, and the dashboard for monitoring. I use Traefik's Docker provider to automatically discover services and route traffic based on labels in their `docker-compose.yml` files.

View File

@@ -6,11 +6,12 @@ services:
ports:
- "80:80"
- "443:443"
- "${TRAEFIK_DASHBOARD_PORT:-8082}:8080"
- "${TRAEFIK_DASHBOARD_PORT}:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ${STORAGE_PATH}/traefik/certs:/certs:rw
- ${STORAGE_PATH}/traefik/dynamic:/dynamic:ro
- ./dynamic:/dynamic:ro
- ${STORAGE_PATH}/traefik/letsencrypt:/letsencrypt
networks:
- web
security_opt:
@@ -23,6 +24,7 @@ services:
- "traefik.http.routers.dashboard.rule=Host(`dashboard.${DOMAIN}`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
command:
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
@@ -31,6 +33,8 @@ services:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=web"
- "--api.dashboard=true"
- "--api.insecure=false"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}"
@@ -40,6 +44,9 @@ services:
- "--providers.file.directory=/dynamic"
- "--providers.file.watch=true"
environment:
- DOMAIN=${DOMAIN}
networks:
web:
external: true

View File

@@ -0,0 +1,38 @@
http:
routers:
nextcloud:
rule: 'Host(`nextcloud.{{ env "DOMAIN" }}`)'
entryPoints:
- websecure
service: nextcloud
middlewares:
- nextcloud-chain
tls:
certResolver: letsencrypt
services:
nextcloud:
loadBalancer:
servers:
- url: "http://nextcloud-aio-apache:11000"
middlewares:
nextcloud-secure-headers:
headers:
hostsProxyHeaders:
- X-Forwarded-Host
customRequestHeaders:
X-Forwarded-Proto: https
referrerPolicy: same-origin
nextcloud-dav:
redirectRegex:
regex: "^https://([^/]+)/.well-known/(card|cal)dav"
replacement: "https://${1}/remote.php/dav/"
permanent: true
nextcloud-chain:
chain:
middlewares:
- nextcloud-dav
- nextcloud-secure-headers

View File

@@ -0,0 +1,4 @@
tls:
certificates:
- certFile: /certs/local.crt
keyFile: /certs/local.key

View File

@@ -10,6 +10,7 @@ services:
- "traefik.http.routers.whoami.entrypoints=websecure"
- "traefik.http.routers.whoami.rule=Host(`whoami.${DOMAIN}`)"
- "traefik.http.routers.whoami.tls=true"
- "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
networks:
web:

View File

@@ -1,3 +0,0 @@
THis is the project
More information hear.