Add in cloudflare ddns and restructure repo
This commit is contained in:
6
services/cloudflare-ddns/.env.example
Normal file
6
services/cloudflare-ddns/.env.example
Normal 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
|
||||
34
services/cloudflare-ddns/docker-compose.yml
Normal file
34
services/cloudflare-ddns/docker-compose.yml
Normal 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
|
||||
6
services/devbox/.env.example
Executable file
6
services/devbox/.env.example
Executable file
@@ -0,0 +1,6 @@
|
||||
# devbox/.env
|
||||
# Copy to .env and fill in real values. NEVER commit .env.
|
||||
|
||||
DEVBOX_SSH_PORT=46573
|
||||
DEVBOX_MEM_LIMIT=10g
|
||||
DEVBOX_SWAP_LIMIT=20g
|
||||
13
services/devbox/docker-compose.yml
Executable file
13
services/devbox/docker-compose.yml
Executable file
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
devcontainer:
|
||||
image: devbox-devcontainer
|
||||
container_name: devcontainer
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${DEVBOX_SSH_PORT:-46573}:2222"
|
||||
volumes:
|
||||
- ${STORAGE_PATH}/devbox:/home/devuser
|
||||
env_file:
|
||||
- ../.env
|
||||
mem_limit: ${DEVBOX_MEM_LIMIT:-10g}
|
||||
memswap_limit: ${DEVBOX_SWAP_LIMIT:-20g}
|
||||
7
services/docs-site/README.md
Normal file
7
services/docs-site/README.md
Normal 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`)
|
||||
20
services/docs-site/docker-compose.yml
Normal file
20
services/docs-site/docker-compose.yml
Normal 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
|
||||
3
services/gitea/.env.example
Executable file
3
services/gitea/.env.example
Executable file
@@ -0,0 +1,3 @@
|
||||
# gitea/.env
|
||||
# Copy to .env and fill in real values. NEVER commit .env.
|
||||
# Add any Gitea-specific secrets here.
|
||||
35
services/gitea/docker-compose.yml
Executable file
35
services/gitea/docker-compose.yml
Executable file
@@ -0,0 +1,35 @@
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:1.24.3
|
||||
container_name: gitea
|
||||
restart: always
|
||||
volumes:
|
||||
- ${STORAGE_PATH}/gitea:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "222:22"
|
||||
networks:
|
||||
- gitea
|
||||
- web
|
||||
env_file:
|
||||
- ../.env
|
||||
- .env
|
||||
environment:
|
||||
- USER_UID=${USER_UID}
|
||||
- USER_GID=${USER_GID}
|
||||
- GITEA__database__DB_TYPE=sqlite3
|
||||
- GITEA__server__ROOT_URL=https://gitea.${DOMAIN}/
|
||||
- USER=git
|
||||
- GITEA_CUSTOM=/data/gitea
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.gitea.entrypoints=websecure"
|
||||
- "traefik.http.routers.gitea.rule=Host(`gitea.${DOMAIN}`)"
|
||||
- "traefik.http.routers.gitea.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
|
||||
|
||||
networks:
|
||||
gitea:
|
||||
web:
|
||||
external: true
|
||||
4
services/nextcloud/.env.example
Executable file
4
services/nextcloud/.env.example
Executable file
@@ -0,0 +1,4 @@
|
||||
# nextcloud/.env
|
||||
# Copy to .env and fill in real values. NEVER commit .env.
|
||||
|
||||
AIO_PORT=8081
|
||||
27
services/nextcloud/docker-compose.yml
Executable file
27
services/nextcloud/docker-compose.yml
Executable file
@@ -0,0 +1,27 @@
|
||||
services:
|
||||
nextcloud-aio-mastercontainer:
|
||||
image: ghcr.io/nextcloud-releases/all-in-one:latest
|
||||
container_name: nextcloud-aio-mastercontainer
|
||||
restart: always
|
||||
ports:
|
||||
- "${AIO_PORT}:8080"
|
||||
volumes:
|
||||
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
environment:
|
||||
- APACHE_PORT=11000
|
||||
- NEXTCLOUD_DATADIR=${STORAGE_PATH}/nextcloud
|
||||
- APACHE_ADDITIONAL_NETWORK=web
|
||||
networks:
|
||||
- nextcloud-aio
|
||||
- web
|
||||
|
||||
volumes:
|
||||
nextcloud_aio_mastercontainer:
|
||||
|
||||
networks:
|
||||
nextcloud-aio:
|
||||
web:
|
||||
external: true
|
||||
|
||||
|
||||
5
services/obsidian-livesync/.env.example
Executable file
5
services/obsidian-livesync/.env.example
Executable file
@@ -0,0 +1,5 @@
|
||||
# obsidian/.env
|
||||
# Copy to .env and fill in real values. NEVER commit .env.
|
||||
|
||||
COUCHDB_USER=admin
|
||||
COUCHDB_PASSWORD=REPLACE_WITH_STRONG_PASSWORD
|
||||
1
services/obsidian-livesync/README.md
Normal file
1
services/obsidian-livesync/README.md
Normal 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.
|
||||
38
services/obsidian-livesync/docker-compose.yml
Executable file
38
services/obsidian-livesync/docker-compose.yml
Executable 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
|
||||
6
services/traefik/.env.example
Executable file
6
services/traefik/.env.example
Executable file
@@ -0,0 +1,6 @@
|
||||
# traefik/.env
|
||||
# Copy to .env and fill in real values. NEVER commit .env.
|
||||
|
||||
TRAEFIK_DASHBOARD_PORT=8080
|
||||
ACME_EMAIL=letsencrypt@example.com
|
||||
DASHBOARD_BASIC_AUTH=admin:$$apr1$$changeme$$REPLACE_WITH_HTPASSWD_HASH
|
||||
1
services/traefik/README.md
Normal file
1
services/traefik/README.md
Normal 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.
|
||||
52
services/traefik/docker-compose.yml
Executable file
52
services/traefik/docker-compose.yml
Executable file
@@ -0,0 +1,52 @@
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:v3.6
|
||||
container_name: traefik
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "${TRAEFIK_DASHBOARD_PORT}:8080"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ${STORAGE_PATH}/traefik/certs:/certs:rw
|
||||
- ./dynamic:/dynamic:ro
|
||||
- ${STORAGE_PATH}/traefik/letsencrypt:/letsencrypt
|
||||
networks:
|
||||
- web
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.middlewares.dashboard-auth.basicauth.users=${DASHBOARD_BASIC_AUTH}"
|
||||
- "traefik.http.routers.dashboard.entrypoints=websecure"
|
||||
- "traefik.http.routers.dashboard.middlewares=dashboard-auth@docker"
|
||||
- "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"
|
||||
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
|
||||
- "--entrypoints.websecure.address=:443"
|
||||
- "--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}"
|
||||
- "--certificatesresolvers.letsencrypt.acme.storage=/certs/acme.json"
|
||||
- "--metrics.prometheus=true"
|
||||
- "--accesslog=true"
|
||||
- "--providers.file.directory=/dynamic"
|
||||
- "--providers.file.watch=true"
|
||||
|
||||
environment:
|
||||
- DOMAIN=${DOMAIN}
|
||||
|
||||
networks:
|
||||
web:
|
||||
external: true
|
||||
38
services/traefik/dynamic/nextcloud.yml
Normal file
38
services/traefik/dynamic/nextcloud.yml
Normal 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
|
||||
4
services/traefik/dynamic/tls.yaml
Normal file
4
services/traefik/dynamic/tls.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
tls:
|
||||
certificates:
|
||||
- certFile: /certs/local.crt
|
||||
keyFile: /certs/local.key
|
||||
17
services/whoami/docker-compose.yml
Executable file
17
services/whoami/docker-compose.yml
Executable file
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
whoami:
|
||||
image: traefik/whoami
|
||||
container_name: whoami
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- web
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "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:
|
||||
external: true
|
||||
Reference in New Issue
Block a user