initial commit

This commit is contained in:
root
2026-03-26 17:37:02 +01:00
parent 9d50d901c5
commit 3b859555e7
12 changed files with 299 additions and 2 deletions

View File

@@ -1,2 +1,26 @@
# docker
docker compose and settings on my homelab
# docker compose and settings on my homelab.
This repo is a save of the evolution and changes of my docker host in my home-lab.
it is structured around this principles:
- portainer is used on the host, but only as a front-end to docker without ssh'ing needed.
- every services is located in /srv with a subfolder per app
- /srv/immich
- /srv/navidrome
- /srv/traefik
- The container should as musch as possible rely on trafik to expose the service. limit the ports exposed on the host to the minimum
- Certificates are generated on the vps by certbot, and copied every nights to the docker host via a script to keep the locally served file protected with the same certs
- pi-hole is used to define local dns entries for each publicly exposed service, implementing a split-zone and avoiding nat hairpin
# Folder structure
/containers
: Contain the docker-compose.yml file with dependencies and .env
/crontab
: The content of a custom crontab file used
/scripts
: Manually written scripts, deployed in **/usr/local/bin**
/systemd-units
: Systemd services and timers to deploy to **/etc/systemd/system**

View File

@@ -0,0 +1,52 @@
version: "3.8"
services:
Aria2-Pro:
container_name: aria2-pro
image: p3terx/aria2-pro
environment:
- PUID=1000
- PGID=1000
- UMASK_SET=002
- RPC_SECRET=kaiThoh6
- RPC_PORT=6800
- LISTEN_PORT=6888
- DISK_CACHE=64M
- IPV6_MODE=false
- UPDATE_TRACKERS=true
- CUSTOM_TRACKER_URL=
- TZ=Europe/Zurich
volumes:
- ${PWD}/aria2-config:/config
#- ${PWD}/aria2-downloads:/downloads
- /mnt/bulk/aria2:/downloads
# If you use host network mode, then no port mapping is required.
# This is the easiest way to use IPv6 networks.
network_mode: host
# network_mode: bridge
# ports:
# - 6800:6800
# - 6888:6888
# - 6888:6888/udp
restart: unless-stopped
# Since Aria2 will continue to generate logs, limit the log size to 1M to prevent your hard disk from running out of space.
logging:
driver: json-file
options:
max-size: 1m
# AriaNg is just a static web page, usually you only need to deploy on a single host.
AriaNg:
container_name: ariang
image: p3terx/ariang
command: --port 6880 --ipv6
network_mode: host
# network_mode: bridge
# ports:
# - 6880:6880
restart: unless-stopped
logging:
driver: json-file
options:
max-size: 1m

24
containers/immich/.env Normal file
View File

@@ -0,0 +1,24 @@
# You can find documentation for all the supported env variables at https://docs.immich.app/install/environment-variables
# The location where your uploaded files are stored
UPLOAD_LOCATION=/srv/immich/library
# The location where your database files are stored. Network shares are not supported for the database
DB_DATA_LOCATION=/srv/immich/postgres
# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
# TZ=Etc/UTC
TZ=Europe/Zurich
# The Immich version to use. You can pin this to a specific version like "v2.1.0"
IMMICH_VERSION=release
# Connection secret for postgres. You should change it to a random password
# Please use only the characters `A-Za-z0-9`, without special characters or spaces
DB_PASSWORD=kaiThoh0
# The values below this line do not need to be changed
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

View File

@@ -0,0 +1,72 @@
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
volumes:
# On laisse Immich utiliser UPLOAD_LOCATION depuis .env
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
- /mnt/rsync/instantUpload:/mnt/InstantUpload
env_file:
- .env
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.immich.rule=Host(`immich.schork.ch`)"
- "traefik.http.routers.immich.entrypoints=websecure"
- "traefik.http.routers.immich.tls=true"
- "traefik.http.services.immich.loadbalancer.server.port=2283"
depends_on:
- redis
- database
restart: always
healthcheck:
disable: false
networks:
- default
- proxy
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
healthcheck:
disable: false
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63
healthcheck:
test: redis-cli ping || exit 1
restart: always
database:
container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: '--data-checksums'
# DB_STORAGE_TYPE: 'HDD' # à activer si ton stockage n'est pas SSD (dans ton cas, NVMe => laisse commenté)
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
shm_size: 128mb
restart: always
#ports:
# - '5432:5432'
healthcheck:
disable: false
volumes:
model-cache:
networks:
proxy:
external: true

View File

@@ -0,0 +1,31 @@
services:
navidrome:
image: deluan/navidrome:latest
user: 1000:1000 # should be owner of volumes
restart: unless-stopped
environment:
ND_LOGLEVEL: info
ND_ENABLESHARING: true
ND_SCANNER_ENABLED: true
ND_SCANNER_SCHEDULE: '@every 24h'
ND_SPOTIFY_ID: "34332c79b9574d8fae5cc2ea2da164f9"
ND_SPOTIFY_SECRET: "12c7d266343844b4a05deeb1420ed857"
ND_LASTFM_ENABLED: true
ND_LASTFM_APIKEY: "f59ca50517732f5adc21aca83d7b5605"
ND_LASTFM_SECRET: "876f6f25e1847cb0d7bf2b58ce78b02e"
volumes:
- "/srv/navidrome/cfg:/data"
- "/srv/navidrome/music:/music:ro"
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.navidrome.rule=Host(`navidrome.schork.ch`)"
- "traefik.http.routers.navidrome.entrypoints=websecure"
- "traefik.http.routers.navidrome.tls=true"
- "traefik.http.services.navidrome.loadbalancer.server.port=4533"
networks:
proxy:
external: true

View File

@@ -0,0 +1,40 @@
services:
traefik:
image: traefik:v3.6
container_name: traefik
restart: unless-stopped
environment:
DOCKER_API_VERSION: "1.45"
command:
- --api.dashboard=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --providers.file.filename=/etc/traefik/dynamic.yml
# Exemple DNS challenge - provider à adapter
- --certificatesresolvers.letsencrypt.acme.dnschallenge=true
- --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare
# utile pendant le debug
- --accesslog=true
- --log.level=INFO
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /srv/certs:/certs:ro
- ./dynamic.yml:/etc/traefik/dynamic.yml:ro
networks:
- proxy
networks:
proxy:
external: true

View File

@@ -0,0 +1,6 @@
tls:
certificates:
- certFile: /certs/immich.schork.ch/fullchain.pem
keyFile: /certs/immich.schork.ch/privkey.pem
- certFile: /certs/navidrome.schork.ch/fullchain.pem
keyFile: /certs/navidrome.schork.ch/privkey.pem

1
crontab/certs.crontab Normal file
View File

@@ -0,0 +1 @@
30 0 * * * /usr/local/bin/cert_sync.sh 2>&1

View File

@@ -0,0 +1,21 @@
#!/bin/bash
set -euo pipefail
SRC="/srv/navidrome/music/"
DST="zh3289@zh3289.rsync.net:/data1/home/zh3289/navidrome/Music/"
LOCKFILE="/run/backup-navidrome-music.lock"
exec 9>"$LOCKFILE"
flock -n 9 || {
echo "Backup already running"
exit 1
}
echo "==== $(date -Is) backup start ===="
rsync -aH --delete \
--info=progress2,stats \
"$SRC" "$DST"
echo "==== $(date -Is) backup done ===="

8
scripts/cert_sync.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
set -e
#scp -r schork.ch:/etc/letsencrypt/live/* /srv/certs/
rsync -avzL schork.ch:/etc/letsencrypt/live/ /srv/certs
chmod -R 600 /srv/certs
docker restart traefik

View File

@@ -0,0 +1,9 @@
[Unit]
Description=Backup Navidrome music to rsync.net
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-navidrome-music.sh

View File

@@ -0,0 +1,9 @@
[Unit]
Description=Daily backup of Navidrome music to rsync.net
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
[Install]
WantedBy=timers.target