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

View File

@@ -7,3 +7,9 @@ repos:
language: system language: system
pass_filenames: false pass_filenames: false
always_run: true 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: up:
@for svc in $(SERVICES); do \ for svc in $(SERVICES); do \
if [ -f "$$svc/docker-compose.yml" ]; then \ if [ -f "$(SERVICES_DIR)/$$svc/docker-compose.yml" ]; then \
echo "Starting $$svc..."; \ 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; \ 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: down:
@for svc in $(SERVICES); do \ @for svc in $(SERVICES); do \
if [ -f "$$svc/docker-compose.yml" ]; then \ if [ -f "$(SERVICES_DIR)/$$svc/docker-compose.yml" ]; then \
echo "Stopping $$svc..."; \ echo "Stopping $$svc..."; \
(cd $$svc && docker compose down); \ (cd $(SERVICES_DIR)/$$svc && docker compose down); \
fi; \ fi; \
done done
restart: down up restart: down up
logs: logs:
@echo "=== Traefik ===" && (cd traefik && docker compose logs --tail=10) @echo "=== Traefik ===" && (cd $(SERVICES_DIR)/traefik && docker compose logs --tail=10)
@echo "=== Gitea ===" && (cd gitea && docker compose logs --tail=10) @echo "=== Gitea ===" && (cd $(SERVICES_DIR)/gitea && docker compose logs --tail=10)
@echo "=== Nextcloud ===" && (cd nextcloud && docker compose logs --tail=10) @echo "=== Nextcloud ===" && (cd $(SERVICES_DIR)/nextcloud && docker compose logs --tail=10)
status: status:
@for svc in $(SERVICES); do \ @for svc in $(SERVICES); do \
if [ -f "$$svc/docker-compose.yml" ]; then \ if [ -f "$(SERVICES_DIR)/$$svc/docker-compose.yml" ]; then \
echo "--- $$svc ---"; \ 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; \ fi; \
done 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 # homelab-infra
GitOps-managed infrastructure for homelab services using Docker Compose and Traefik for routing. 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 ## 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 ## Directory Structure
@@ -39,8 +43,9 @@ homelab-infra/
├── docs/ # MkDocs documentation source ├── docs/ # MkDocs documentation source
├── mkdocs.yml # MkDocs configuration ├── mkdocs.yml # MkDocs configuration
├── scripts/ # Utility scripts ├── scripts/ # Utility scripts
└── [service]/ # Per-service configurations └── services/ # Per-service configurations
── docker-compose.yml ── [service]/
├── .env.example ├── docker-compose.yml
└── README.md ├── .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 # 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. 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 ## 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 | | Type | Example | Git Repo? | Backup? | Location |
|------|---------|-----------|---------|----------| |------|---------|-----------|---------|----------|
| **Source Configs** | `docker-compose.yml`, `.env.example`, `Makefile` | Yes | No | `/srv/homelab-infra` | | **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>` | | **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>` | | **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 | | Service | Image | Status |
|---------|-------|--------| |---------|-------|--------|
| [cloudflare-ddns](services/cloudflare-ddns.md) | `favonia/cloudflare-ddns:1` | active |
| [devbox](services/devbox.md) | `devbox-devcontainer` | 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 | | [gitea](services/gitea.md) | `gitea/gitea:1.24.3` | active |
| [nextcloud](services/nextcloud.md) | `ghcr.io/nextcloud-releases/all-in-one:latest` | active | | [nextcloud](services/nextcloud.md) | `ghcr.io/nextcloud-releases/all-in-one:latest` | active |
| [obsidian-livesync](services/obsidian-livesync.md) | `couchdb: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 git clone git@gitea.sjhl.nz:james/homelab-infra.git
cd homelab-infra cd homelab-infra
# Set up environment # Create all missing .env files from templates
cp .env.example .env make init-env
# Edit .env with real values
# Set up service secrets # Edit .env and services/*/.env with real 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
# Create required Docker networks # Create required Docker networks
docker network create web docker network create web
# Start everything # Start and verify everything
make up make up
make status
# Optional: start/stop one service
# make up-<service>
# make down-<service>
``` ```
## Commands ## Commands
@@ -113,9 +118,13 @@ homelab-infra/
├── backup.sh # Restic backup script ├── backup.sh # Restic backup script
├── .pre-commit-config.yaml # Pre-commit hooks ├── .pre-commit-config.yaml # Pre-commit hooks
├── docs/ # MkDocs documentation ├── docs/ # MkDocs documentation
├── mkdocs.yml # MkDocs config ├── mkdocs.yml # MkDocs config
├── scripts/ # Utility scripts ├── 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 ## 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 ## Docker Compose Configuration
```yaml ```yaml
--8<-- "devbox/docker-compose.yml" --8<-- "services/devbox/docker-compose.yml"
``` ```
## Environment Variables (`.env.example`) ## Environment Variables (`.env.example`)
```bash ```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 ## Docker Compose Configuration
```yaml ```yaml
--8<-- "gitea/docker-compose.yml" --8<-- "services/gitea/docker-compose.yml"
``` ```
## Environment Variables (`.env.example`) ## Environment Variables (`.env.example`)
```bash ```bash
--8<-- "gitea/.env.example" --8<-- "services/gitea/.env.example"
``` ```

View File

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

View File

@@ -1,15 +1,16 @@
# obsidian-livesync # 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. > 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 ## Docker Compose Configuration
```yaml ```yaml
--8<-- "obsidian-livesync/docker-compose.yml" --8<-- "services/obsidian-livesync/docker-compose.yml"
``` ```
## Environment Variables (`.env.example`) ## Environment Variables (`.env.example`)
```bash ```bash
--8<-- "obsidian-livesync/.env.example" --8<-- "services/obsidian-livesync/.env.example"
``` ```

View File

@@ -1,16 +1,16 @@
# traefik # 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. > 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 ## Docker Compose Configuration
```yaml ```yaml
--8<-- "traefik/docker-compose.yml" --8<-- "services/traefik/docker-compose.yml"
``` ```
## Environment Variables (`.env.example`) ## Environment Variables (`.env.example`)
```bash ```bash
--8<-- "traefik/.env.example" --8<-- "services/traefik/.env.example"
``` ```

View File

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

View File

@@ -9,9 +9,10 @@ markdown_extensions:
- . - .
nav: nav:
- Home: index.md - Home: index.md
- Recovery Reference: recovery.md
- Services: - Services:
- Cloudflare Ddns: services/cloudflare-ddns.md
- Devbox: services/devbox.md - Devbox: services/devbox.md
- Docs Site: services/docs-site.md
- Gitea: services/gitea.md - Gitea: services/gitea.md
- Nextcloud: services/nextcloud.md - Nextcloud: services/nextcloud.md
- Obsidian Livesync: services/obsidian-livesync.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 Usage: python3 scripts/generate_docs.py
""" """
import yaml import yaml
import os
import sys import sys
from pathlib import Path from pathlib import Path
REPO_ROOT = Path(__file__).parent.parent REPO_ROOT = Path(__file__).parent.parent
SERVICES_DIR = REPO_ROOT SERVICES_DIR = REPO_ROOT / "services"
DOCS_DIR = REPO_ROOT / "docs" / "services" DOCS_DIR = REPO_ROOT / "docs" / "services"
DISPLAY_NAME_OVERRIDES = { DISPLAY_NAME_OVERRIDES = {
@@ -175,6 +174,8 @@ def format_security(sec):
def generate_service_md(service_name, service_dir): def generate_service_md(service_name, service_dir):
"""Generate service doc that includes docker-compose.yml, Dockerfile, README, and .env.example.""" """Generate service doc that includes docker-compose.yml, Dockerfile, README, and .env.example."""
include_base = f"services/{service_dir.name}"
lines = [] lines = []
lines.append(f"# {service_name}") lines.append(f"# {service_name}")
lines.append("") lines.append("")
@@ -183,7 +184,7 @@ def generate_service_md(service_name, service_dir):
# Include README.md first if exists # Include README.md first if exists
readme_path = service_dir / "README.md" readme_path = service_dir / "README.md"
if readme_path.exists(): 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.") 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 # Include docker-compose.yml
@@ -192,7 +193,7 @@ def generate_service_md(service_name, service_dir):
lines.append("## Docker Compose Configuration") lines.append("## Docker Compose Configuration")
lines.append("") lines.append("")
lines.append("```yaml") 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("```")
lines.append("") lines.append("")
@@ -202,7 +203,7 @@ def generate_service_md(service_name, service_dir):
lines.append("## Dockerfile") lines.append("## Dockerfile")
lines.append("") lines.append("")
lines.append("```dockerfile") lines.append("```dockerfile")
lines.append(f'--8<-- "{service_dir.name}/Dockerfile"') lines.append(f'--8<-- "{include_base}/Dockerfile"')
lines.append("```") lines.append("```")
lines.append("") lines.append("")
@@ -212,7 +213,7 @@ def generate_service_md(service_name, service_dir):
lines.append("## Environment Variables (`.env.example`)") lines.append("## Environment Variables (`.env.example`)")
lines.append("") lines.append("")
lines.append("```bash") lines.append("```bash")
lines.append(f'--8<-- "{service_dir.name}/.env.example"') lines.append(f'--8<-- "{include_base}/.env.example"')
lines.append("```") lines.append("```")
lines.append("") lines.append("")
@@ -275,6 +276,10 @@ def cleanup_stale_service_docs(service_names):
def main(): def main():
if not SERVICES_DIR.exists():
print(f"Services directory not found: {SERVICES_DIR}", file=sys.stderr)
return
all_services = {} all_services = {}
# Find all service directories with docker-compose.yml # Find all service directories with docker-compose.yml
@@ -284,9 +289,6 @@ def main():
compose_file = item / "docker-compose.yml" compose_file = item / "docker-compose.yml"
if not compose_file.exists(): if not compose_file.exists():
continue continue
# Skip scripts/docs directories
if item.name in ("scripts", "docs", "__pycache__"):
continue
service_name = item.name service_name = item.name
try: 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 container_name: nextcloud-aio-mastercontainer
restart: always restart: always
ports: ports:
- "${AIO_PORT:-8081}:8080" - "${AIO_PORT}:8080"
volumes: volumes:
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config - nextcloud_aio_mastercontainer:/mnt/docker-aio-config
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
@@ -15,8 +15,6 @@ services:
networks: networks:
- nextcloud-aio - nextcloud-aio
- web - web
env_file:
- ../.env
volumes: volumes:
nextcloud_aio_mastercontainer: nextcloud_aio_mastercontainer:
@@ -25,3 +23,5 @@ networks:
nextcloud-aio: nextcloud-aio:
web: web:
external: true external: true

View File

@@ -3,4 +3,3 @@
COUCHDB_USER=admin COUCHDB_USER=admin
COUCHDB_PASSWORD=REPLACE_WITH_STRONG_PASSWORD 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 # traefik/.env
# Copy to .env and fill in real values. NEVER commit .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 ACME_EMAIL=letsencrypt@example.com
DASHBOARD_BASIC_AUTH=admin:$$apr1$$changeme$$REPLACE_WITH_HTPASSWD_HASH 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: ports:
- "80:80" - "80:80"
- "443:443" - "443:443"
- "${TRAEFIK_DASHBOARD_PORT:-8082}:8080" - "${TRAEFIK_DASHBOARD_PORT}:8080"
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- ${STORAGE_PATH}/traefik/certs:/certs:rw - ${STORAGE_PATH}/traefik/certs:/certs:rw
- ${STORAGE_PATH}/traefik/dynamic:/dynamic:ro - ./dynamic:/dynamic:ro
- ${STORAGE_PATH}/traefik/letsencrypt:/letsencrypt
networks: networks:
- web - web
security_opt: security_opt:
@@ -23,6 +24,7 @@ services:
- "traefik.http.routers.dashboard.rule=Host(`dashboard.${DOMAIN}`)" - "traefik.http.routers.dashboard.rule=Host(`dashboard.${DOMAIN}`)"
- "traefik.http.routers.dashboard.service=api@internal" - "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls=true" - "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
command: command:
- "--entrypoints.web.address=:80" - "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
@@ -31,6 +33,8 @@ services:
- "--providers.docker=true" - "--providers.docker=true"
- "--providers.docker.exposedbydefault=false" - "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=web" - "--providers.docker.network=web"
- "--api.dashboard=true"
- "--api.insecure=false"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true" - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}" - "--certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL}"
@@ -40,6 +44,9 @@ services:
- "--providers.file.directory=/dynamic" - "--providers.file.directory=/dynamic"
- "--providers.file.watch=true" - "--providers.file.watch=true"
environment:
- DOMAIN=${DOMAIN}
networks: networks:
web: web:
external: true 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.entrypoints=websecure"
- "traefik.http.routers.whoami.rule=Host(`whoami.${DOMAIN}`)" - "traefik.http.routers.whoami.rule=Host(`whoami.${DOMAIN}`)"
- "traefik.http.routers.whoami.tls=true" - "traefik.http.routers.whoami.tls=true"
- "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
networks: networks:
web: web:

View File

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