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