🎉 Initial Commit
This commit is contained in:
commit
8f23ba583d
20 changed files with 1153 additions and 0 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
*.env
|
||||||
30
dyndns/docker-compose.yml
Normal file
30
dyndns/docker-compose.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
name: dyndns
|
||||||
|
services:
|
||||||
|
ddns-updater:
|
||||||
|
container_name: ddns-updater
|
||||||
|
environment:
|
||||||
|
- PERIOD=${DDNS_PERIOD}
|
||||||
|
- UPDATE_COOLDOWN=${DDNS_COOLDOWN}
|
||||||
|
- TZ=${TZ}
|
||||||
|
image: qmcgaw/ddns-updater:latest
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DDNS_DATA_PATH}
|
||||||
|
target: /updater/data
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
network_mode: host
|
||||||
|
hostname: ddns-updater
|
||||||
|
cpu_shares: 90
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 15841M
|
||||||
38
excalidraw/docker-compose.yml
Normal file
38
excalidraw/docker-compose.yml
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
name: ${CONTAINER_NAME}
|
||||||
|
services:
|
||||||
|
excalidraw:
|
||||||
|
cpu_shares: 90
|
||||||
|
command: []
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 15841M
|
||||||
|
hostname: ${CONTAINER_NAME}
|
||||||
|
image: excalidraw/excalidraw:latest
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
ports: []
|
||||||
|
volumes: []
|
||||||
|
devices: []
|
||||||
|
cap_add: []
|
||||||
|
environment: []
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
privileged: false
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
name: traefik
|
||||||
|
external: true
|
||||||
45
forgejo/docker-compose.yml
Normal file
45
forgejo/docker-compose.yml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
name: ${CONTAINER_NAME}
|
||||||
|
|
||||||
|
networks:
|
||||||
|
forgejo:
|
||||||
|
external: false
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
image: codeberg.org/forgejo/forgejo:9.0
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
environment:
|
||||||
|
- USER_UID=1000
|
||||||
|
- USER_GID=1000
|
||||||
|
networks:
|
||||||
|
- forgejo
|
||||||
|
- traefik
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DATA_PATH}
|
||||||
|
target: /data
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
|
||||||
|
- type: bind
|
||||||
|
source: /etc/localtime
|
||||||
|
target: /etc/localtime
|
||||||
|
read_only: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
ports:
|
||||||
|
- '222:22'
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
36
gantt_dockerfolder/docker-compose.yml
Normal file
36
gantt_dockerfolder/docker-compose.yml
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
name: gantt
|
||||||
|
services:
|
||||||
|
gantt-app:
|
||||||
|
image: nginx:stable-alpine
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DIST_PATH}
|
||||||
|
target: /usr/share/nginx/html:ro
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
- type: bind
|
||||||
|
source: ${CONFIG_PATH}
|
||||||
|
target: /etc/nginx/conf.d/default.conf:ro
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
41
jellyfin/docker-compose.yml
Normal file
41
jellyfin/docker-compose.yml
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
services:
|
||||||
|
jellyfin:
|
||||||
|
image: jellyfin/jellyfin
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
environment:
|
||||||
|
- JELLYFIN_PublishedServerUrl=https://${SUBDOMAIN}.${DOMAIN}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${CACHE_PATH}
|
||||||
|
target: /cache
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
- type: bind
|
||||||
|
source: ${CONFIG_PATH}
|
||||||
|
target: /config
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
- type: bind
|
||||||
|
source: ${MEDIA_PATH}
|
||||||
|
target: /media
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
59
kitchenowl/docker-compose.yml
Normal file
59
kitchenowl/docker-compose.yml
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
services:
|
||||||
|
kitchenowl:
|
||||||
|
image: tombursch/kitchenowl:latest
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=${DB_PROVIDER}://${DB_USER}:${DB_PASSWORD}@db:${DB_PORT}/${DB_DATABASE}
|
||||||
|
- BACKEND_PROVIDER=${DB_BACKEND_PROVIDER}
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
- internal_net
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
|
||||||
|
- "traefik.http.middlewares.${ROUTER_NAME}-stripprefix.headers.customrequestheaders.X-Forwarded-Proto=http"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.middlewares=kitchenowl-compress"
|
||||||
|
- "traefik.http.middlewares.${ROUTER_NAME}-compress.compress=true"
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
container_name: ${CONTAINER_NAME}_db
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
- POSTGRES_DB=${DB_DATABASE}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DB_PATH}
|
||||||
|
target: /var/lib/postgresql/data
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- internal_net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
|
internal_net:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
60
matrix/docker-compose.yml
Executable file
60
matrix/docker-compose.yml
Executable file
|
|
@ -0,0 +1,60 @@
|
||||||
|
name: matrix
|
||||||
|
services:
|
||||||
|
synapse:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
hostname: ${CONTAINER_NAME}
|
||||||
|
image: matrixdotorg/synapse:latest
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
cpu_shares: 90
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 15841M
|
||||||
|
|
||||||
|
entrypoint:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- >
|
||||||
|
set -e
|
||||||
|
if [ ! -f /data/homeserver.yaml ]; then
|
||||||
|
echo "Generating initial configuration..."
|
||||||
|
/start.py generate
|
||||||
|
echo "" >> /data/homeserver.yaml
|
||||||
|
echo "enable_registration: true" >> /data/homeserver.yaml
|
||||||
|
echo "enable_registration_without_verification: true" >> /data/homeserver.yaml
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Starting Synapse..."
|
||||||
|
exec /start.py
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- SYNAPSE_REPORT_STATS=${SYNAPSE_REPORT_STATS}
|
||||||
|
- SYNAPSE_SERVER_NAME=${SUBDOMAIN}.${DOMAIN}
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DATA_PATH}
|
||||||
|
target: /data
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
name: traefik
|
||||||
|
external: true
|
||||||
49
n8n/docker-compose.yml
Normal file
49
n8n/docker-compose.yml
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
name: n8n
|
||||||
|
services:
|
||||||
|
n8n:
|
||||||
|
image: docker.n8n.io/n8nio/n8n:latest
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
- N8N_PORT=${CONTAINER_PORT}
|
||||||
|
- N8N_PROTOCOL=https
|
||||||
|
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
|
||||||
|
- N8N_HOST=${SUBDOMAIN}.${DOMAIN}
|
||||||
|
- WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN}/
|
||||||
|
- GENERIC_TIMEZONE=${TZ}
|
||||||
|
- TZ=${TZ}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DATA_PATH}
|
||||||
|
target: /home/node/.n8n
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
|
||||||
|
- type: bind
|
||||||
|
source: ${FILES_PATH}
|
||||||
|
target: /files
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
name: traefik
|
||||||
|
external: true
|
||||||
44
openProject/docker-compose.yml
Normal file
44
openProject/docker-compose.yml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
name: op-xwiki-stack
|
||||||
|
networks:
|
||||||
|
frontend:
|
||||||
|
name: op_xwiki_frontend
|
||||||
|
backend:
|
||||||
|
name: op_xwiki_backend
|
||||||
|
traefik:
|
||||||
|
name: traefik
|
||||||
|
external: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
openproject_web:
|
||||||
|
image: openproject/openproject:17
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- OPENPROJECT_SECRET_KEY_BASE=${OP_SECRET_KEY_BASE}
|
||||||
|
- SECRET_KEY_BASE=${SECRET_KEY_BASE}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DATA_PATH}
|
||||||
|
target: /var/openproject
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- frontend
|
||||||
|
- backend
|
||||||
|
- traefik
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
72
passbolt/docker-compose.yml
Normal file
72
passbolt/docker-compose.yml
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
name: passbolt
|
||||||
|
services:
|
||||||
|
passbolt-db:
|
||||||
|
image: mariadb:10.11
|
||||||
|
container_name: ${CONTAINER_NAME}-db
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
environment:
|
||||||
|
- MYSQL_ROOT_PASSWORD=${DB_MYSQL_ROOT_PASSWORD}
|
||||||
|
- MYSQL_DATABASE=${DB_DATABASE}
|
||||||
|
- MYSQL_USER=${DB_USER}
|
||||||
|
- MYSQL_PASSWORD=${DB_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DB_PATH}
|
||||||
|
target: /var/lib/mysql
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- internal_net
|
||||||
|
|
||||||
|
passbolt:
|
||||||
|
image: passbolt/passbolt:latest-ce
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
depends_on:
|
||||||
|
- passbolt-db
|
||||||
|
environment:
|
||||||
|
- APP_FULL_BASE_URL=https://${SUBDOMAIN}.${DOMAIN}
|
||||||
|
- DB_HOST=passbolt-db
|
||||||
|
- DB_USER=${DB_USER}
|
||||||
|
- DB_PASSWORD=${DB_PASSWORD}
|
||||||
|
- DB_DATABASE=${DB_DATABASE}
|
||||||
|
- EMAIL_DEFAULT_TRANSPORT=${EMAIL_TRANSPORT}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${PGP_PATH}
|
||||||
|
target: /etc/passbolt/gpg
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
- type: bind
|
||||||
|
source: ${JWT_PATH}
|
||||||
|
target: /etc/passbolt/jwt
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
- internal_net
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
name: traefik
|
||||||
|
external: true
|
||||||
|
internal_net:
|
||||||
|
driver: bridge
|
||||||
192
readme.md
Normal file
192
readme.md
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
# 🏠 Homeserver Setup
|
||||||
|
|
||||||
|
Zentrale Dokumentation der Infrastruktur, Docker-Container und persistenten Daten meines Debian-basierten Homeservers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗺️ Projektstruktur
|
||||||
|
|
||||||
|
Das Setup trennt strikt zwischen persistenten Anwendungsdaten (`data/`) und den Docker-Konfigurationsdateien (`homeserver/`).
|
||||||
|
|
||||||
|
```text
|
||||||
|
|
||||||
|
## Tree
|
||||||
|
├── data
|
||||||
|
│ ├── backup_emmc
|
||||||
|
│ │ └── sys_ssh
|
||||||
|
│ ├── dyndns
|
||||||
|
│ │ └── ddns-data
|
||||||
|
│ ├── excalidraw
|
||||||
|
│ ├── forgejo
|
||||||
|
│ │ └── forgejo
|
||||||
|
│ ├── gantt
|
||||||
|
│ │ ├── dist
|
||||||
|
│ │ ├── env.d.ts
|
||||||
|
│ │ ├── gantt_dockerfolder
|
||||||
|
│ │ ├── index.html
|
||||||
|
│ │ ├── node_modules
|
||||||
|
│ │ ├── package.json
|
||||||
|
│ │ ├── package-lock.json
|
||||||
|
│ │ ├── public
|
||||||
|
│ │ ├── README.md
|
||||||
|
│ │ ├── src
|
||||||
|
│ │ ├── tsconfig.app.json
|
||||||
|
│ │ ├── tsconfig.json
|
||||||
|
│ │ ├── tsconfig.node.json
|
||||||
|
│ │ └── vite.config.ts
|
||||||
|
│ ├── jellyfin
|
||||||
|
│ │ ├── cache
|
||||||
|
│ │ ├── config
|
||||||
|
│ │ └── media
|
||||||
|
│ ├── kitchenowl
|
||||||
|
│ │ └── db_data
|
||||||
|
│ ├── letsencrypt
|
||||||
|
│ ├── matrix
|
||||||
|
│ │ └── data
|
||||||
|
│ ├── n8n
|
||||||
|
│ │ └── local-files
|
||||||
|
│ ├── openProject
|
||||||
|
│ ├── passbolt
|
||||||
|
│ │ ├── db-data
|
||||||
|
│ │ ├── gpg-keys
|
||||||
|
│ │ └── jwt-keys
|
||||||
|
│ ├── sure
|
||||||
|
│ │ ├── db
|
||||||
|
│ │ ├── enable_banking.pem
|
||||||
|
│ │ └── storage
|
||||||
|
│ ├── test
|
||||||
|
│ │ └── dns-check.sh
|
||||||
|
│ ├── traefik
|
||||||
|
│ │ ├── acme.json
|
||||||
|
│ │ └── letsencrypt
|
||||||
|
│ ├── wartungsskripte
|
||||||
|
│ │ ├── update_befehl.sh
|
||||||
|
│ │ └── update_docker.sh
|
||||||
|
│ └── xWiki
|
||||||
|
│ ├── postgres_data
|
||||||
|
│ └── xwiki_data
|
||||||
|
└── homeserver
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── excalidraw
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── forgejo
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── gantt_dockerfolder
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── jellyfin
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── kitchenowl
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── letsencrypt
|
||||||
|
├── matrix
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── n8n
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── openProject
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── passbolt
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── readme.md
|
||||||
|
├── sure
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── test
|
||||||
|
│ └── dns-check.sh
|
||||||
|
├── traefik
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── wartungsskripte
|
||||||
|
│ ├── update_befehl.sh
|
||||||
|
│ └── update_docker.sh
|
||||||
|
└── xWiki
|
||||||
|
└── docker-compose.yml
|
||||||
|
```
|
||||||
|
## 🚀 Infrastruktur & Netzwerk
|
||||||
|
Als zentraler Reverse Proxy wird Traefik eingesetzt. Er fängt alle Anfragen auf Port 80/443 ab, verteilt sie an die jeweiligen Docker-Container und erstellt automatisch SSL-Zertifikate via Let's Encrypt.
|
||||||
|
|
||||||
|
## Wichtige URLs im Netzwerk:
|
||||||
|
🌐 Git-Server (Forgejo): `https://git.bybenji.de` (SSH-Port: 222)
|
||||||
|
🌐 Passwortmanager: `https://passbolt.bybenji.de`
|
||||||
|
🌐 Streaming: `https://jellyfin.bybenji.de`
|
||||||
|
|
||||||
|
## 🛠️ Betrieb & Wartung
|
||||||
|
Container starten / stoppen
|
||||||
|
Um einen bestimmten Dienst zu starten, in den entsprechenden Ordner unter homeserver/ wechseln und ausführen:
|
||||||
|
```Bash
|
||||||
|
cd homeserver/jellyfin
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Updates
|
||||||
|
Unter `homeserver/wartungsskripte/` befinden sich Skripte zur Serverpflege.
|
||||||
|
`update_docker.sh`: Aktualisiert alle laufenden Docker-Container auf das neueste Image und räumt alte Images auf (docker system prune).
|
||||||
|
Aktuell ist ein Manuelles Wartungsfenster jeden Samstag um 21 Uhr gesetzt.
|
||||||
|
> [!NOTE] Automatisierung
|
||||||
|
Einrichtung als Cronjob für automatische Updates jeden Sonntag um 03:00 Uhr:
|
||||||
|
>```Bash
|
||||||
|
>0 3 * * 0 /bin/bash /mnt/PB960/data/gantt/homeserver/wartungsskripte/update_docker.>sh
|
||||||
|
>```
|
||||||
|
## 📦 Backup-Strategie
|
||||||
|
|
||||||
|
Um maximale Datensicherheit zu gewährleisten, werden alle Produktivdaten (`data/`) nach dem 3-2-1-Prinzip gesichert.
|
||||||
|
|
||||||
|
### 1. Datenbasis & Lokales Backup (Kopie 1 & 2 - Medium 1)
|
||||||
|
* **Produktivdaten:** Befinden sich live auf dem Produktivsystem.
|
||||||
|
* **Lokales Backup:** Täglich inkrementelle und monatlich vollständige Backups werden auf einem dedizierten **NAS** gesichert, das sich physisch im selben Serverrack befindet.
|
||||||
|
|
||||||
|
### 2. Offsite & Standby-Server (Kopie 3 - Standort extern)
|
||||||
|
* **Backup-Server:** Eine vollständige Kopie wird an einen geografisch getrennten Standort gesichert.
|
||||||
|
* **Hot-Standby:** Da dieser Server denselben Techstack besitzt, kann er bei Wartungsarbeiten oder Ausfällen des Hauptservers direkt als temporäres Produktivsystem zugeschaltet werden.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> **Offene Baustelle: Das 2. Speichermedium**
|
||||||
|
> Für die vollständige Erfüllung des 3-2-1-Prinzips fehlt noch das zweite, alternative Speichermedium (z. B. eine rotierende externe USB-Festplatte (Air-Gapped) oder ein verschlüsselter S3-Cloud-Speicher wie Hetzner Storage Box).
|
||||||
|
|
||||||
|
### 🖥️ System-Backup
|
||||||
|
* Unabhängig von den Anwendungsdaten werden Abbilder des eMMC-Speichers sowie die systemrelevanten SSH-Schlüssel unter `data/backup_emmc/sys_ssh/` vorgehalten.
|
||||||
|
|
||||||
|
|
||||||
|
### 💾 Speicher-Architektur & NAS
|
||||||
|
|
||||||
|
Sowohl das lokale Produktiv-NAS als auch das Offsite-NAS sind speicherseitig identisch aufgebaut, um maximale Redundanz und volle Kompatibilität im Failover-Fall zu gewährleisten.
|
||||||
|
|
||||||
|
### 📍 Phase 1: Start-Setup (Aktueller Stand)
|
||||||
|
* **Main-Server:** 1x 14 TB Seagate Exos (Single Drive – 14 TB Netto-Nutzdaten)
|
||||||
|
* **Offsite-Server:** 1x 14 TB Seagate Exos (Single Drive – 14 TB Backup-Ziel)
|
||||||
|
* **Sicherheit:** Die Datenkomponente wird per täglichem Skript/Replikation auf den Offsite-Server gesichert. Es besteht in dieser Phase noch keine lokale Festplatten-Redundanz (RAID) beim Ausfall einer Platte vor Ort.
|
||||||
|
|
||||||
|
### 🚀 Phase 2: RAID 5 Erweiterung (Zukunft)
|
||||||
|
Sobald zusätzlicher Speicher oder lokale Ausfallsicherheit benötigt wird, wird jedes System um 2 weitere 14 TB Platten ergänzt:
|
||||||
|
* **Konfiguration:** Migration auf ein **3-Platten-RAID-5** pro Server.
|
||||||
|
* **Neuer Speicher:** **28 TB Netto-Nutzdaten** pro Server bei einer Fehlertoleranz von 1 ausfallenden Festplatte pro System.
|
||||||
|
|
||||||
|
## 🖥️ Offsite-Server & Techstack
|
||||||
|
|
||||||
|
Der Offsite-Server dient primär als geografisch getrenntes Backup-Ziel, ist jedoch hardware- und softwareseitig als **Hot-Standby** konzipiert. Bei einem Totalausfall oder Wartungsarbeiten am Hauptstandort kann er die primären Dienste temporär übernehmen.
|
||||||
|
|
||||||
|
### 🌐 Virtualisierungs-Plattform (Proxmox VE)
|
||||||
|
Als Betriebssystem-Unterbau wird **Proxmox VE (Virtual Environment)** eingesetzt. Dies ermöglicht eine strikte Kapselung und einfache Verwaltung der Ressourcen:
|
||||||
|
|
||||||
|
* **Hypervisor:** Typ-1-Bare-Metal-Hypervisor auf Debian-Basis.
|
||||||
|
* **LXC (Linux Containers):** Für ressourcensparende Anwendungen (wie den Docker-Host).
|
||||||
|
* **VMs (Virtuelle Maschinen):** Für isolierte Systeme, die einen eigenen Kernel oder ein anderes OS benötigen.
|
||||||
|
|
||||||
|
### 📦 Container-Architektur (Der "Bauchtanz")
|
||||||
|
Um den exakt gleichen Techstack wie auf dem Main-Server zu spiegeln, läuft innerhalb von Proxmox ein dedizierter LXC-Container (oder eine VM), der als **Docker-Host** fungiert.
|
||||||
|
|
||||||
|
* **Docker & Compose:** Innerhalb dieser Instanz wird die identische `homeserver/`-Struktur per Git synchronisiert gehalten.
|
||||||
|
* **Dienste-Status:** Die Docker-Container (Nextcloud, Immich, Jellyfin etc.) sind im Normalbetrieb gestoppt oder laufen im reinen Standby-Modus, um Ressourcen zu schonen, stehen aber für ein sofortiges Failover bereit.
|
||||||
|
|
||||||
|
### 🔄 Replikation & Backup-Infrastruktur (Phase 1)
|
||||||
|
In der aktuellen Phase (Single-Drive) sieht das Zusammenspiel wie folgt aus:
|
||||||
|
|
||||||
|
1. **ZFS / Local Storage:** Proxmox verwaltet die einzelne 14 TB Seagate Exos Festplatte als lokalen Speicherpool.
|
||||||
|
2. **Pull-/Push-Backups:** Der Hauptserver schiebt seine Daten (z. B. via `rsync`, `rclone` oder BorgBackup) verschlüsselt über das Netzwerk auf den Offsite-Proxmox-Speicher.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Visualisierung
|
||||||
|
├── für einen Ordner oder eine Datei, wenn danach noch weitere Elemente auf derselben Ebene folgen.
|
||||||
|
└── für das letzte Element auf einer Ebene (das „Eckstück“).
|
||||||
|
│ für Linien, die an Unterordnern vorbeiführen (wichtig für die richtige Einrückung).
|
||||||
110
sparkyFitness/docker-compose.yml
Normal file
110
sparkyFitness/docker-compose.yml
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
services:
|
||||||
|
sparkyfitness-db:
|
||||||
|
image: postgres:18.3-alpine
|
||||||
|
container_name: ${CONTAINER_NAME}-db
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: ${SPARKY_FITNESS_DB_NAME}
|
||||||
|
POSTGRES_USER: ${SPARKY_FITNESS_DB_USER}
|
||||||
|
POSTGRES_PASSWORD: ${SPARKY_FITNESS_DB_PASSWORD}
|
||||||
|
PUID: 1000
|
||||||
|
GUID: 1000
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DB_PATH:-./postgresql}
|
||||||
|
target: /var/lib/postgresql
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- sparkyfitness-network
|
||||||
|
|
||||||
|
sparkyfitness-server:
|
||||||
|
image: codewithcj/sparkyfitness_server:latest
|
||||||
|
environment:
|
||||||
|
SPARKY_FITNESS_LOG_LEVEL: ${SPARKY_FITNESS_LOG_LEVEL}
|
||||||
|
ALLOW_PRIVATE_NETWORK_CORS: ${ALLOW_PRIVATE_NETWORK_CORS:-false}
|
||||||
|
SPARKY_FITNESS_EXTRA_TRUSTED_ORIGINS: ${SPARKY_FITNESS_EXTRA_TRUSTED_ORIGINS}
|
||||||
|
SPARKY_FITNESS_PUBLIC_API_DOCS: ${SPARKY_FITNESS_PUBLIC_API_DOCS:-false}
|
||||||
|
SPARKY_FITNESS_DB_USER: ${SPARKY_FITNESS_DB_USER:-sparky}
|
||||||
|
SPARKY_FITNESS_DB_HOST: ${SPARKY_FITNESS_DB_HOST:-sparkyfitness-db}
|
||||||
|
SPARKY_FITNESS_DB_NAME: ${SPARKY_FITNESS_DB_NAME}
|
||||||
|
SPARKY_FITNESS_DB_PASSWORD: ${SPARKY_FITNESS_DB_PASSWORD}
|
||||||
|
SPARKY_FITNESS_APP_DB_USER: ${SPARKY_FITNESS_APP_DB_USER:-sparkyapp}
|
||||||
|
SPARKY_FITNESS_APP_DB_PASSWORD: ${SPARKY_FITNESS_APP_DB_PASSWORD}
|
||||||
|
SPARKY_FITNESS_DB_PORT: 5432
|
||||||
|
SPARKY_FITNESS_API_ENCRYPTION_KEY: ${SPARKY_FITNESS_API_ENCRYPTION_KEY}
|
||||||
|
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
|
||||||
|
SPARKY_FITNESS_FRONTEND_URL: ${SPARKY_FITNESS_FRONTEND_URL:-http://0.0.0.0}
|
||||||
|
SPARKY_FITNESS_DISABLE_SIGNUP: ${SPARKY_FITNESS_DISABLE_SIGNUP}
|
||||||
|
SPARKY_FITNESS_ADMIN_EMAIL: ${SPARKY_FITNESS_ADMIN_EMAIL}
|
||||||
|
SPARKY_FITNESS_EMAIL_HOST: ${SPARKY_FITNESS_EMAIL_HOST}
|
||||||
|
SPARKY_FITNESS_EMAIL_PORT: ${SPARKY_FITNESS_EMAIL_PORT}
|
||||||
|
SPARKY_FITNESS_EMAIL_SECURE: ${SPARKY_FITNESS_EMAIL_SECURE}
|
||||||
|
SPARKY_FITNESS_EMAIL_USER: ${SPARKY_FITNESS_EMAIL_USER}
|
||||||
|
SPARKY_FITNESS_EMAIL_PASS: ${SPARKY_FITNESS_EMAIL_PASS}
|
||||||
|
SPARKY_FITNESS_EMAIL_FROM: ${SPARKY_FITNESS_EMAIL_FROM}
|
||||||
|
GARMIN_MICROSERVICE_URL: http://sparkyfitness-garmin:8000
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY:-}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY:-}
|
||||||
|
NO_PROXY: ${NO_PROXY:-}
|
||||||
|
PUID: 1000
|
||||||
|
GUID: 1000
|
||||||
|
networks:
|
||||||
|
- sparkyfitness-network
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
- sparkyfitness-db
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${SERVER_BACKUP_PATH:-./backup}
|
||||||
|
target: /app/SparkyFitnessServer/backup
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
- type: bind
|
||||||
|
source: ${SERVER_UPLOADS_PATH:-./uploads}
|
||||||
|
target: /app/SparkyFitnessServer/uploads
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
|
||||||
|
sparkyfitness-frontend:
|
||||||
|
image: codewithcj/sparkyfitness:latest
|
||||||
|
environment:
|
||||||
|
SPARKY_FITNESS_FRONTEND_URL: ${SPARKY_FITNESS_FRONTEND_URL}
|
||||||
|
SPARKY_FITNESS_SERVER_HOST: ${CONTAINER_NAME}-server
|
||||||
|
SPARKY_FITNESS_SERVER_PORT: 3010
|
||||||
|
PUID: 1000
|
||||||
|
GUID: 1000
|
||||||
|
networks:
|
||||||
|
- sparkyfitness-network
|
||||||
|
- traefik
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
depends_on:
|
||||||
|
- sparkyfitness-server
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.middlewares=sparkyfitness-headers"
|
||||||
|
- "traefik.http.middlewares.${ROUTER_NAME}-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||||
|
- "traefik.http.middlewares.${ROUTER_NAME}-headers.headers.customrequestheaders.X-Forwarded-Host=fitness.bybenji.de"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
sparkyfitness-network:
|
||||||
|
driver: bridge
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
149
sure/docker-compose.yml
Normal file
149
sure/docker-compose.yml
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
name: sure
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
name: traefik
|
||||||
|
external: true
|
||||||
|
internal_net:
|
||||||
|
name: sure_internal_net
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
services:
|
||||||
|
sure-db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: ${CONTAINER_NAME}-db
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=${DB_DATABASE}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DB_PATH}
|
||||||
|
target: /var/lib/postgresql/data
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- internal_net
|
||||||
|
cpu_shares: 90
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 15841M
|
||||||
|
|
||||||
|
sure-redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: ${CONTAINER_NAME}-redis
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${REDIS_PATH}
|
||||||
|
target: /data
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
networks:
|
||||||
|
- internal_net
|
||||||
|
cpu_shares: 90
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 15841M
|
||||||
|
|
||||||
|
web:
|
||||||
|
image: ghcr.io/we-promise/sure:stable
|
||||||
|
container_name: ${CONTAINER_NAME}-web
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
depends_on:
|
||||||
|
sure-db:
|
||||||
|
condition: service_started
|
||||||
|
sure-redis:
|
||||||
|
condition: service_started
|
||||||
|
environment:
|
||||||
|
- SELF_HOSTED=${SELF_HOSTED}
|
||||||
|
- ALLOW_REGISTRATION=${ALLOW_REGISTRATION}
|
||||||
|
- SECRET_KEY_BASE=${SECRET_KEY_BASE}
|
||||||
|
- RAILS_ASSUME_SSL=${RAILS_ASSUME_SSL}
|
||||||
|
- RAILS_FORCE_SSL=${RAILS_FORCE_SSL}
|
||||||
|
- DB_HOST=sure-db
|
||||||
|
- POSTGRES_DB=${DB_DATABASE}
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
- REDIS_URL=${REDIS_URL}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${STORAGE_PATH}
|
||||||
|
target: /rails/storage
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
- internal_net
|
||||||
|
cpu_shares: 90
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 15841M
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
|
|
||||||
|
worker:
|
||||||
|
image: ghcr.io/we-promise/sure:stable
|
||||||
|
container_name: ${CONTAINER_NAME}-worker
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
command:
|
||||||
|
- /rails/bin/docker-entrypoint
|
||||||
|
- ./bin/bundle
|
||||||
|
- exec
|
||||||
|
- sidekiq
|
||||||
|
depends_on:
|
||||||
|
sure-db:
|
||||||
|
condition: service_started
|
||||||
|
sure-redis:
|
||||||
|
condition: service_started
|
||||||
|
environment:
|
||||||
|
- APP_URL=https://${SUBDOMAIN}.${DOMAIN}
|
||||||
|
- DB_HOST=sure-db
|
||||||
|
- POSTGRES_DB=${DB_DATABASE}
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
- REDIS_URL=${REDIS_URL}
|
||||||
|
- SECRET_KEY_BASE=${SECRET_KEY_BASE}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${STORAGE_PATH}
|
||||||
|
target: /rails/storage
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
- type: bind
|
||||||
|
source: ${BANKING_PATH}
|
||||||
|
target: /rails/config/enable_banking.pem
|
||||||
|
read_only: true
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- internal_net
|
||||||
|
cpu_shares: 90
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 15841M
|
||||||
19
test/dns-check.sh
Executable file
19
test/dns-check.sh
Executable file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
clear
|
||||||
|
echo "=== Nameserver-Überwachung für bybenji.de ==="
|
||||||
|
echo "Letzte Prüfung: $(date +%H:%M:%S)"
|
||||||
|
echo "----------------------------------------"
|
||||||
|
|
||||||
|
NS_INFO=$(nslookup -type=ns budget.bybenji.de 8.8.8.8 2>&1)
|
||||||
|
echo "$NS_INFO"
|
||||||
|
|
||||||
|
if echo "$NS_INFO" | grep -q "desec.io"; then
|
||||||
|
echo -e "\n\a🚀🚀🚀 ERFOLG! Die Nameserver wurden auf deSEC umgestellt! 🚀🚀🚀"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n[Warten auf deSEC...] Nächste Prüfung in 30 Sekunden. (Abbrechen mit STRG+C)"
|
||||||
|
sleep 30
|
||||||
|
done
|
||||||
63
traefik/docker-compose.yml
Normal file
63
traefik/docker-compose.yml
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
name: traefik
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
name: traefik
|
||||||
|
# external: true -> Entfernt, damit dieser Stack das Netzwerk global auf dem Server erstellt!
|
||||||
|
|
||||||
|
services:
|
||||||
|
traefik:
|
||||||
|
image: traefik:latest
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
hostname: traefik
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
cpu_shares: 90
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 15841M
|
||||||
|
|
||||||
|
command:
|
||||||
|
- --api.insecure=true
|
||||||
|
- --providers.docker=true
|
||||||
|
- --providers.docker.exposedbydefault=false
|
||||||
|
- --entrypoints.web.address=:80
|
||||||
|
- --entrypoints.web.http.redirections.entryPoint.to=websecure
|
||||||
|
- --entrypoints.web.http.redirections.entryPoint.scheme=https
|
||||||
|
- --entrypoints.websecure.address=:443
|
||||||
|
- --certificatesresolvers.myresolver.acme.dnschallenge=true
|
||||||
|
- --certificatesresolvers.myresolver.acme.dnschallenge.provider=desec
|
||||||
|
- --certificatesresolvers.myresolver.acme.dnschallenge.delaybeforecheck=10
|
||||||
|
- --certificatesresolvers.myresolver.acme.email=${CERT_RESOLVER_EMAIL}
|
||||||
|
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
|
||||||
|
- --certificatesresolvers.myresolver.acme.dnschallenge.resolvers=${DNS_RESOLVERS}
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- DESEC_TOKEN=${DESEC_TOKEN}
|
||||||
|
- DESEC_TTL=${DESEC_TTL}
|
||||||
|
- DESEC_POLLING_INTERVAL=${DESEC_POLLING_INTERVAL}
|
||||||
|
- DESEC_PROPAGATION_TIMEOUT=${DESEC_PROPAGATION_TIMEOUT}
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "${HTTP_PORT}:80"
|
||||||
|
- "${HTTPS_PORT}:443"
|
||||||
|
- "${DASHBOARD_PORT}:8080"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /var/run/docker.sock
|
||||||
|
target: /var/run/docker.sock
|
||||||
|
read_only: true
|
||||||
|
- type: bind
|
||||||
|
source: ${LETSENCRYPT_PATH}
|
||||||
|
target: /letsencrypt
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
1
wartungsskripte/update_befehl.sh
Normal file
1
wartungsskripte/update_befehl.sh
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
sudo ./update_docker.sh
|
||||||
72
wartungsskripte/update_docker.sh
Executable file
72
wartungsskripte/update_docker.sh
Executable file
|
|
@ -0,0 +1,72 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
PROJECTS=(
|
||||||
|
"/mnt/PB960/homeserver/dyndns"
|
||||||
|
"/mnt/PB960/homeserver/excalidraw"
|
||||||
|
"/mnt/PB960/homeserver/forgejo"
|
||||||
|
"/mnt/PB960/homeserver/gantt_dockerfolder"
|
||||||
|
"/mnt/PB960/homeserver/jellyfin"
|
||||||
|
"/mnt/PB960/homeserver/kitchenowl"
|
||||||
|
"/mnt/PB960/homeserver/matrix"
|
||||||
|
"/mnt/PB960/homeserver/n8n"
|
||||||
|
"/mnt/PB960/homeserver/openProject"
|
||||||
|
"/mnt/PB960/homeserver/passbolt"
|
||||||
|
"/mnt/PB960/homeserver/sparkyFitness"
|
||||||
|
"/mnt/PB960/homeserver/sure"
|
||||||
|
"/mnt/PB960/homeserver/traefik"
|
||||||
|
"/mnt/PB960/homeserver/xWiki"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " STARRTE AUTOMATISCHES DOCKER-UPDATE "
|
||||||
|
echo " Datum: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||||
|
echo "=========================================="
|
||||||
|
|
||||||
|
# Prüfen, ob das Skript als Root ausgeführt wird
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "[FEHLER] Bitte starte das Skript mit 'sudo'!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Aktuellste Version des Repos holen
|
||||||
|
echo "[1/2] Aktualisiere Git-Repository (Homeserver)..."
|
||||||
|
cd /mnt/PB960/homeserver && git pull
|
||||||
|
|
||||||
|
echo "[2/2] Aktualisiere Git-Repository (Gantt)..."
|
||||||
|
cd /mnt/PB960/data/gantt && git pull
|
||||||
|
|
||||||
|
for TARGET_DIR in "${PROJECTS[@]}"; do
|
||||||
|
if [ -d "$TARGET_DIR" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "------------------------------------------"
|
||||||
|
echo "[INFO] Verarbeite Projekt in: $TARGET_DIR"
|
||||||
|
echo "------------------------------------------"
|
||||||
|
|
||||||
|
cd "$TARGET_DIR" || continue
|
||||||
|
|
||||||
|
# 1. Container sauber stoppen
|
||||||
|
echo "[1/4] Stoppe laufende Container..."
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
# 2. Neueste Versionen/Images aus dem Netz ziehen
|
||||||
|
echo "[2/4] Ziehe neueste Docker-Images (Pull)..."
|
||||||
|
docker compose pull
|
||||||
|
|
||||||
|
# 3. Container im Hintergrund neu starten (erzwingt das Update)
|
||||||
|
echo "[3/4] Starte Container neu (erzwinge Update)..."
|
||||||
|
docker compose up -d --build --force-recreate
|
||||||
|
|
||||||
|
# 4. Alte, ungenutzte Image-Reste löschen (spart Speicherplatz)
|
||||||
|
echo "[4/4] Bereinige alte Image-Leichen..."
|
||||||
|
docker image prune -f
|
||||||
|
|
||||||
|
echo "[ERFOLG] Projekt $TARGET_DIR wurde aktualisiert!"
|
||||||
|
else
|
||||||
|
echo "[WARNUNG] Verzeichnis $TARGET_DIR existiert nicht. Überspringe..."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " ALLE UPDATES ERFOLGREICH DURCHGEFÜHRT! "
|
||||||
|
echo "=========================================="
|
||||||
70
xWiki/docker-compose.yml
Normal file
70
xWiki/docker-compose.yml
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
name: xwiki
|
||||||
|
|
||||||
|
networks:
|
||||||
|
frontend:
|
||||||
|
name: op_xwiki_frontend
|
||||||
|
backend:
|
||||||
|
name: op_xwiki_backend
|
||||||
|
traefik:
|
||||||
|
name: traefik
|
||||||
|
external: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
xwiki_db:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
container_name: ${CONTAINER_NAME}_postgres
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
- POSTGRES_DB=${DB_DATABASE}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DB_PATH}
|
||||||
|
target: /var/lib/postgresql/data
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
networks:
|
||||||
|
- backend
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
xwiki_web:
|
||||||
|
image: xwiki:lts-postgres-tomcat
|
||||||
|
container_name: ${CONTAINER_NAME}_web
|
||||||
|
restart: ${RESTART_POLICY}
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
- POSTGRES_DB=${DB_DATABASE}
|
||||||
|
- DB_HOST=xwiki_db
|
||||||
|
- JAVA_OPTS=-Xmx1024m
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${DATA_PATH}
|
||||||
|
target: /usr/local/xwiki
|
||||||
|
bind:
|
||||||
|
create_host_path: true
|
||||||
|
networks:
|
||||||
|
- frontend
|
||||||
|
- backend
|
||||||
|
- traefik
|
||||||
|
depends_on:
|
||||||
|
xwiki_db:
|
||||||
|
condition: service_healthy
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls=true"
|
||||||
|
- "traefik.http.routers.${ROUTER_NAME}.tls.certresolver=${CERTIFICATE_RESOLVER}"
|
||||||
|
- "traefik.http.services.${ROUTER_NAME}.loadbalancer.server.port=${CONTAINER_PORT}"
|
||||||
|
- "traefik.docker.network=${TRAEFIK_NETWORK}"
|
||||||
Loading…
Reference in a new issue