deploy nextcloud

This commit is contained in:
2026-04-18 00:36:40 -05:00
parent 4db6f0b06f
commit 9961fe1ed4
13 changed files with 592 additions and 256 deletions

View File

@@ -0,0 +1,102 @@
---
# Nextcloud — the-grid
# Boilerplate: nextcloud 32.0.6-apache
# Generated for mk-labs / local.mk-labs.cloud
#
# Traefik routing handled via static dynamic config on lightning-lane
# External URL: https://the-grid.mk-labs.cloud (Cloudflare Tunnel)
# Internal URL: https://the-grid.local.mk-labs.cloud (Traefik)
#
# Storage split:
# nextcloud_data — local volume (app code, config, apps)
# nextcloud_files — NFS mount from emporium (user files only)
services:
nextcloud-db:
image: docker.io/library/mariadb:11
container_name: nextcloud-db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- nextcloud_db:/var/lib/mysql
environment:
- TZ=America/Chicago
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
networks:
- nextcloud-internal
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
nextcloud-redis:
image: docker.io/library/redis:7-alpine
container_name: nextcloud-redis
restart: unless-stopped
networks:
- nextcloud-internal
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 5s
retries: 3
nextcloud:
image: docker.io/library/nextcloud:32.0.6-apache
container_name: nextcloud
restart: unless-stopped
depends_on:
nextcloud-db:
condition: service_healthy
nextcloud-redis:
condition: service_healthy
ports:
- "80:80"
volumes:
- nextcloud_data:/var/www/html
- nextcloud_files:/var/www/html/data
environment:
- TZ=America/Chicago
# Database
- MYSQL_HOST=nextcloud-db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
# Redis
- REDIS_HOST=nextcloud-redis
# Nextcloud admin
- NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
- NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
# Trusted domains — internal and external
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.local.mk-labs.cloud the-grid.local.mk-labs.cloud the-grid.mk-labs.cloud
# Apache
- APACHE_SERVER_NAME=the-grid.local.mk-labs.cloud
# Reverse proxy — lightning-lane IP only
- TRUSTED_PROXIES=10.1.71.35
- OVERWRITEPROTOCOL=https
- OVERWRITECLIURL=https://the-grid.mk-labs.cloud
networks:
- nextcloud-internal
networks:
nextcloud-internal:
driver: bridge
name: nextcloud-internal
volumes:
nextcloud_data:
driver: local
nextcloud_db:
driver: local
nextcloud_files:
driver: local
driver_opts:
type: nfs
o: "addr=10.1.71.9,rw,nfsvers=4,hard,intr,noatime"
device: ":/volume1/the-grid"

View File

@@ -17,8 +17,12 @@ services:
- ANSIBLE_HOST_KEY_CHECKING=False
networks:
- semaphore_backend
dns_search:
- local.mk-labs.cloud
ports:
- "3000:3000"
volumes:
- ./ansible_key:/home/semaphore/.ssh/id_ed25519:ro
depends_on:
- semaphore_db

View File

@@ -57,6 +57,19 @@ services:
- proxy
restart: unless-stopped
cloudflared:
image: docker.io/cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
networks:
- proxy
depends_on:
traefik:
condition: service_healthy
networks:
proxy:
external: true

View File

@@ -0,0 +1,66 @@
---
services:
traefik:
image: docker.io/library/traefik:v3.6.8
container_name: traefik
security_opt:
- no-new-privileges:true
command:
- "--global.checkNewVersion=false"
- "--global.sendAnonymousUsage=false"
- "--log.level=info"
- "--ping=true"
- "--ping.entryPoint=ping"
- "--api.dashboard=true"
- "--api.insecure=true"
# Entrypoints
- "--entrypoints.ping.address=:8082"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.encodedCharacters.allowEncodedSlash=true"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.websecure.http.encodedCharacters.allowEncodedSlash=true"
- "--entrypoints.websecure.http.tls.certResolver=cloudflare"
- "--entrypoints.websecure.http.tls.domains[0].main=local.mk-labs.cloud"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.local.mk-labs.cloud"
# ACME / Cloudflare DNS-01
- "--certificatesresolvers.cloudflare.acme.email=ryan.blundon@protonmail.com"
- "--certificatesresolvers.cloudflare.acme.storage=/var/traefik/certs/acme.json"
- "--certificatesresolvers.cloudflare.acme.caServer=https://acme-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.cloudflare.acme.dnsChallenge.provider=cloudflare"
- "--certificatesresolvers.cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
# Providers
- "--providers.docker=true"
- "--providers.docker.exposedByDefault=false"
- "--providers.docker.network=proxy"
- "--providers.file.directory=/etc/traefik/dynamic"
- "--providers.file.watch=true"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik_certs:/var/traefik/certs/:rw
- ./dynamic:/etc/traefik/dynamic:ro
environment:
- TZ=America/Chicago
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:8082/ping"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
networks:
- proxy
restart: unless-stopped
networks:
proxy:
external: true
volumes:
traefik_certs:
driver: local

View File

@@ -0,0 +1,24 @@
http:
routers:
nextcloud:
rule: "Host(`nextcloud.local.mk-labs.cloud`) || Host(`the-grid.local.mk-labs.cloud`)"
entryPoints:
- websecure
tls:
certResolver: cloudflare
middlewares:
- nextcloud-caldav
service: nextcloud
middlewares:
nextcloud-caldav:
redirectRegex:
permanent: true
regex: "https://(.*)/.well-known/(card|cal)dav"
replacement: "https://${1}/remote.php/dav/"
services:
nextcloud:
loadBalancer:
servers:
- url: "http://the-grid.local.mk-labs.cloud:80"