initial commit
This commit is contained in:
28
README.md
28
README.md
@@ -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**
|
||||||
|
|
||||||
|
|||||||
52
containers/aria2/docker-compose.yml
Normal file
52
containers/aria2/docker-compose.yml
Normal 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
24
containers/immich/.env
Normal 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
|
||||||
|
|
||||||
72
containers/immich/docker-compose.yml
Normal file
72
containers/immich/docker-compose.yml
Normal 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
|
||||||
31
containers/navidrome/docker-compose.yml
Normal file
31
containers/navidrome/docker-compose.yml
Normal 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
|
||||||
40
containers/traefik/docker-compose.yml
Normal file
40
containers/traefik/docker-compose.yml
Normal 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
|
||||||
6
containers/traefik/dynamic.yml
Normal file
6
containers/traefik/dynamic.yml
Normal 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
1
crontab/certs.crontab
Normal file
@@ -0,0 +1 @@
|
|||||||
|
30 0 * * * /usr/local/bin/cert_sync.sh 2>&1
|
||||||
21
scripts/backup-navidrome-music.sh
Executable file
21
scripts/backup-navidrome-music.sh
Executable 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
8
scripts/cert_sync.sh
Executable 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
|
||||||
9
systemd-units/backup-navidrome-music.service
Normal file
9
systemd-units/backup-navidrome-music.service
Normal 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
|
||||||
|
|
||||||
9
systemd-units/backup-navidrome-music.timer
Normal file
9
systemd-units/backup-navidrome-music.timer
Normal 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
|
||||||
Reference in New Issue
Block a user