#+TITLE: Home Server #+SETUPFILE: ./setup/org-setup-file.org * Hardware #+caption: Home Server Hardware | *Part* | *Model* | |--------------+-------------------------------------------------| | Case | Fractal Design Node 804 | | Motherboard | ASUS PRIME B450M-A | | CPU | AMD Ryzen 7 5700G | | RAM | Corsair Vengeance LPX 32Go (4x8Go) DDR4 3200MHz | | Cooler | ARCTIC Freezer 34 eSports DUO | | PSU | Corsair RM750x | | SSD M.2 | Samsung 970 EVO Plus 1Tb | | Data Drives | 4x 8Tb | | Parity Drive | 1x 10Tb | Note regarding the ASUS PRIME B450M-A 2*The M.2 Socket shares bandwidth with the SATA_5/6 ports, and therefore the SATA_5/6 ports cannot be used when an M.2 device is installed. But it seems that it is a NVME (and not M.2 SATA), and therefore I can use the last 2 SATA ports. * Installation ** Ubuntu - Download *Ubuntu Server 24.04 LTS* ([[https://ubuntu.com/download/server][link]]). - Activate OpenSSH and add SSH Keys - Account: =thomas=, hostname: =homelab= ** Install Important software #+begin_src bash :eval no sudo apt install neovim tmux fd-find ripgrep fzf apache2-utils unrar ranger #+end_src ** Terminal Problem On the local host, using Termite: #+begin_src bash :eval no infocmp > termite.terminfo # export Termite's Terminfo scp termite.terminfo user@remote-host:~/ # or any other method to copy to the remote host #+end_src On the remote host, in the directory where you copied =termite.terminfo=: #+begin_src bash :eval no tic -x termite.terminfo # import Terminfo for current user rm termite.terminfo # optional: remove Terminfo file #+end_src ** Minor Modifications of =~/.inputrc= Modify =~/.inputrc=, like so: #+begin_src conf "\e[A": history-search-backward # arrow up "\e[B": history-search-forward # arrow down #+end_src ** Partition and Format Disk Drives A nice tutorial is available [[https://www.digitalocean.com/community/tutorials/how-to-partition-and-format-storage-devices-in-linux][here]]. #+begin_src bash :eval no lsblk #+end_src #+begin_src bash :eval no sudo parted /dev/sda mklabel gpt #+end_src #+begin_src bash :eval no sudo parted -a opt /dev/sda mkpart primary ext4 0% 100% #+end_src #+begin_src bash :eval no sudo mkfs.ext4 -L primary /dev/sda1 #+end_src ** MergerFS and FStab *MergerFS* is a transparent layer that sits on top of the data drives providing a single mount point for reads / writes ([[https://selfhostedhome.com/combining-different-sized-drives-with-mergerfs-and-snapraid/][link]]). #+begin_src bash :eval no sudo apt install mergerfs #+end_src Create mount points #+begin_src bash :eval no sudo mkdir /mnt/disk0 sudo mkdir /mnt/disk1 sudo mkdir /mnt/disk2 sudo mkdir /mnt/parity #+end_src Create folder where disks will be merged. #+begin_src bash :eval no sudo mkdir /srv/storage #+end_src Edit =/etc/fstab=. #+begin_src conf :eval no /dev/disk/by-uuid/7fb7873c-83bd-4805-98ab-506e6c7b56fa /mnt/disk0 ext4 defaults 0 0 /dev/disk/by-uuid/d9e7cc6b-5054-4eb9-bcb2-7e29480e0c6e /mnt/disk1 ext4 defaults 0 0 /dev/disk/by-uuid/6fcd38b9-0886-46bd-900d-cb1f170dbcee /mnt/disk2 ext4 defaults 0 0 /dev/disk/by-uuid/736bf432-baa8-465e-bf8e-c2bbad1cb7dd /mnt/parity ext4 defaults 0 0 /mnt/disk* /srv/storage fuse.mergerfs allow_other,use_ino,cache.files=partial,dropcacheonclose=true,category.create=mfs,fsname=mergerfs 0 0 #+end_src ** SnapRAID ([[https://github.com/amadvance/snapraid][link]]) and SnapRAID Runner ([[https://github.com/Chronial/snapraid-runner][link]]) <> *SnapRAID* is a snapshot parity calculation tool which acts at the block level independent of filesystem ([[https://selfhostedhome.com/combining-different-sized-drives-with-mergerfs-and-snapraid/][link]]). #+begin_src bash :eval no sudo apt install snapraid #+end_src The configuration file is located in =/etc/snapraid.conf=: #+begin_src conf :tangle /ssh:thomas@homelab:/etc/snapraid.conf # Defines the file to use as parity storage # It must NOT be in a data disk parity /mnt/parity/snapraid.parity # Defines the files to use as content list # You can use multiple specification to store more copies # You must have least one copy for each parity file plus one. Some more don't # hurt # They can be in the disks used for data, parity or boot, # but each file must be in a different disk content /var/snapraid.content content /mnt/disk0/.snapraid.content content /mnt/disk1/.snapraid.content content /mnt/disk2/.snapraid.content # Defines the data disks to use # The order is relevant for parity, do not change it disk disk0 /mnt/disk0 disk disk1 /mnt/disk1 disk disk2 /mnt/disk2 # Defines files and directories to exclude exclude /tmp/ exclude /lost+found/ exclude /Downloads/ # This changes a lot, not necessary to backup exclude *.!sync exclude .DS_Store exclude ._.DS_Store exclude .Thumbs.db exclude .fseventsd exclude .Spotlight-V100 exclude .TemporaryItems exclude .Trashes exclude .part #+end_src Go in the =/home/thomas/.local/soft/= directory and clone the =snapraid-runner= [[https://github.com/tdehaeze/snapraid-runner][repository]]. Then, create the =snapraid-runner.conf= file: #+begin_src conf :noweb yes :tangle /ssh:thomas@homelab:~/.local/soft/snapraid-runner/snapraid-runner.conf [snapraid] ; path to the snapraid executable (e.g. /bin/snapraid) executable = /usr/local/bin/snapraid ; path to the snapraid config to be used config = /etc/snapraid.conf ; abort operation if there are more deletes than this, set to -1 to disable deletethreshold = -1 ; if you want touch to be ran each time touch = true [logging] ; logfile to write to, leave empty to disable ; file = snapraid.log ; maximum logfile size in KiB, leave empty for infinite ; maxsize = 5000 [gotify] sendon = error url = https://gotify.tdehaeze.xyz token = <> [scrub] ; set to true to run scrub after sync enabled = true ; scrub plan - either a percentage or one of [bad, new, full] plan = 12 ; minimum block age (in days) for scrubbing. Only used with percentage plans older-than = 10 #+end_src And finally, create a =cronjob= with =sudo crontab -e= and add the following line: #+begin_src conf 0 3 * * * python3 /home/thomas/.local/soft/snapraid-runner/snapraid-runner.py -c /home/thomas/.local/soft/snapraid-runner/snapraid-runner.conf >> /home/thomas/cron/snapraid_runner.log 2>&1 #+end_src ** Install Docker The procedure is well explained [[https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04][here]]. If docker is already installed, remove it with: #+begin_src bash sudo apt remove docker #+end_src ** Executing the Docker Command Without Sudo #+begin_src bash sudo usermod -aG docker ${USER} #+end_src To apply the new group membership, log out of the server and back in, or type the following: #+begin_src bash su - ${USER} #+end_src ** Install Docker-Compose #+begin_src bash sudo apt install docker-compose #+end_src ** Setup Docker Networks #+begin_src bash docker network create --gateway 192.168.90.1 --subnet 192.168.90.0/24 t2_proxy docker network create docker_default #+end_src ** Change Timezone #+begin_src bash :exec no sudo timedatectl set-timezone Europe/Paris #+end_src ** Secure the Web Server Most of it comes from [[https://github.com/imthenachoman/How-To-Secure-A-Linux-Server][here]]. - Set =PasswordAuthentication no= in =/etc/ssh/sshd_config= ** Automatic Security Updates The procedure is well explained [[https://www.linuxbabe.com/ubuntu/automatic-security-update-unattended-upgrades-ubuntu][here]]. #+begin_src bash sudo apt install unattended-upgrades update-notifier-common #+end_src Edit =/etc/apt/apt.conf.d/50unattended-upgrades=, and change the following lines: #+begin_src conf Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Automatic-Reboot "true"; Unattended-Upgrade::Automatic-Reboot-Time "04:00"; #+end_src Edit =/etc/apt/apt.conf.d/20auto-upgrades=: #+begin_src conf APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; #+end_src ** Setup cronjobs Create a folder =~/cron= with all the scripts and logs related to cron. To edit the cron jobs, type =crontab -e= and add a line like: #+begin_src conf */5 * * * * /home/thomas/cron/caddy_update.sh >> /home/thomas/cron/caddy_update.log 2>&1 #+end_src That will run every 5 minutes. To check how the first part of the crontab works, check [[https://crontab.guru/][this website]]. ** Setup Traefik proxy Follow [[https://www.smarthomebeginner.com/traefik-2-docker-tutorial/][this]] guide. ** Run =docker-compose= #+begin_src bash cd ~/docker && docker-compose up -d #+end_src ** Docker config =~/.docker/config.json= #+begin_src json :tangle /ssh:thomas@homelab:~/.docker/config.json { "psFormat": "table {{ .ID }}\\t{{ .Names }}\t{{ .Status }}" } #+end_src ** Install =earlyoom= for better memory management https://github.com/rfjakob/earlyoom #+begin_src bash :eval no sudo apt install earlyoom #+end_src Check the status with =systemctl status earlyoom=. * Maintenance - How To ** Update System/Packages To show possible update: #+begin_src bash :eval no apt list --upgradable #+end_src #+begin_src bash :eval no sudo -- sh -c 'apt-get update; apt-get upgrade -y; apt-get dist-upgrade -y; apt-get autoremove -y; apt-get autoclean -y' #+end_src ** Snapraid errors If there are errors, you can check what is going on with: #+begin_src bash :eval no sudo snapraid status #+end_src To fix the errors: #+begin_src bash :eval no sudo snapraid -e fix #+end_src You can check again if everything is fixed using the =scrub= command: #+begin_src bash :eval no sudo snapraid scrub #+end_src ** Docker Commands - Starting a container: =$ docker start homeassistant= - Stopping a container: =$ docker stop homeassistant= - Restarting a container: =$ docker restart homeassistant= - Listing the running containers: =$ docker ps or $ cd ~/docker/ && docker-compose ps= - View the logs of a container: =$ docker logs -f homeassistant= - Drop a shell into a container: =$ docker exec -it homeassistant /bin/bash= - Update specific container: =docker-compose pull --ignore-pull-failures homeassistant= Update All Containers #+begin_src bash :eval no cd ~/docker/ && docker compose pull --ignore-pull-failures && docker compose up -d #+end_src Clean up Docker environment This will delete all unused images, volumes and networks. #+begin_src bash :eval no docker system prune -f && docker image prune -f && docker volume prune -f #+end_src ** Add =wireguard= client *** With an Android client Show the QRcode corresponding the a specific peer with: #+begin_src bash docker exec -it wireguard /app/show-peer 1 #+end_src Then, simply scan the QRcode with the [[https://github.com/WireGuard/wireguard-android][Wireguard]] application. *** With a Linux client Copy the file =$CONFIGDIR/wireguard/peeri/peeri.conf=, e.g.: #+begin_src conf [Interface] Address = 10.13.13.4/24 DNS = 10.13.1.1 PrivateKey = **** ListenPort = 51820 [Peer] PublicKey = **** Endpoint = wireguard.tdehaeze.xyz:51820 AllowedIPs = 0.0.0.0/0, ::0/0 #+end_src Then, paste the file to =/etc/wireguard/interfacename.conf=. And then: - =sudo chmod 600 /etc/wireguard/interfacename.conf= - =sudo chown root:root /etc/wireguard/interfacename.conf= Then, start the tunnel with: #+begin_src bash :eval no wg-quick up interfacename #+end_src ** Add new user to =authelia= Modify the user database file: #+begin_src bash :eval no nvim ~/docker/config/authelia/users_database.yml #+end_src Add an entry for the new user. Restart the container with =docker-compose restart authelia=. Ask the new user to go to https://login.tdehaeze.xyz/ to reset his password. * Docker-Compose :PROPERTIES: :header-args: :tangle /ssh:thomas@homelab:~/docker/docker-compose.yaml :header-args+: :comments none :mkdirp yes :END: ** USB config https://hackaday.io/page/13294-solved-docker-udev-usb-naming =/etc/udev/rules.d/99-usb-serial.rules= #+begin_src conf :tangle no # SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ACTION=="add", RUN+="/home/thomas/docker/mount-usb-device.sh tina2" # SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ACTION=="remove", RUN+="/bin/rm -f /dev/ttyUSB-tina2" SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ACTION=="add", RUN+="/home/thomas/docker/mount-usb-device.sh zigbee" SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ACTION=="remove", RUN+="/bin/rm -f /dev/ttyUSB-zigbee" #+end_src =/home/thomas/docker/mount-usb-device.sh= #+begin_src bash :eval no :tangle no p="" # if [ "$1" == "tina2" ] # then # p=`realpath /dev/serial/by-id/usb-1a86_USB_Serial-if00-port0` # fi if [ "$1" == "zigbee" ] then p=`realpath /dev/serial/by-id/usb-Silicon_Labs_slae.sh_cc2652rb_stick_-_slaesh_s_iot_stuff_00_12_4B_00_23_93_39_57-if00-port0` fi if [ "x$p" != "x" ] then rm -f /dev/ttyUSB-$1 ln $p /dev/ttyUSB-$1 fi #+end_src ** Basic Config #+begin_src yaml networks: t2_proxy: external: true name: t2_proxy immich: external: false backend: external: false default: driver: bridge #+end_src #+begin_src yaml x-logging: &default-logging driver: "json-file" options: max-size: "200k" max-file: "10" #+end_src #+begin_src yaml services: #+end_src ** Docker Config and Tools *** =traefik= - Application proxy ([[https://github.com/traefik/traefik][link]]) #+begin_src yaml traefik: container_name: traefik image: traefik:v3.6 restart: unless-stopped depends_on: - authelia networks: t2_proxy: ipv4_address: 192.168.90.254 # You can specify a static IP security_opt: - no-new-privileges:true ports: - 80:80 # http - 443:443 # https - 8448:8448 # Matrix volumes: - $CONFIGDIR/traefik2/acme.json:/acme.json - $CONFIGDIR/traefik2/traefik.yaml:/etc/traefik/traefik.yaml - $CONFIGDIR/traefik2/services.yaml:/etc/traefik/services.yaml - /var/log/traefik:/var/log - /var/run/docker.sock:/var/run/docker.sock:ro environment: - CF_API_EMAIL=$CLOUDFLARE_EMAIL - CF_API_KEY=$CLOUDFLARE_API_KEY labels: - "traefik.enable=true" # HTTP-to-HTTPS Redirect - "traefik.http.routers.http-catchall.entryPoints=web" - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)" - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" # HTTP Routers - "traefik.http.routers.traefik-rtr.entrypoints=web-secure" - "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME`)" - "traefik.http.routers.traefik-rtr.tls=true" - "traefik.http.routers.traefik-rtr.middlewares=authelia@docker" - "traefik.http.routers.traefik-rtr.service=traefik-svc" # - "traefik.http.routers.traefik-rtr.tls.certresolver=dns-cloudflare" # Comment out this line after first run of traefik to force the use of wildcard certs - "traefik.http.routers.traefik-rtr.tls.domains[0].main=$DOMAINNAME" - "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINNAME" - "traefik.http.routers.traefik-rtr.tls.domains[1].main=wingaudio.fr" - "traefik.http.routers.traefik-rtr.tls.domains[1].sans=*.wingaudio.fr" - "traefik.http.services.traefik-svc.loadbalancer.server.port=8080" # Services - API - "traefik.http.routers.traefik-rtr.service=api@internal" # Router - "traefik.http.routers.openwrt.entrypoints=web-secure" - "traefik.http.routers.openwrt.rule=Host(`openwrt.$DOMAINNAME`)" - "traefik.http.routers.openwrt.tls=true" - "traefik.http.routers.openwrt.service=openwrt@file" # Valetudo - "traefik.http.routers.valetudo.entrypoints=web-secure" - "traefik.http.routers.valetudo.rule=Host(`valetudo.$DOMAINNAME`)" - "traefik.http.routers.valetudo.tls=true" - "traefik.http.routers.valetudo.middlewares=authelia@docker" - "traefik.http.routers.valetudo.service=valetudo@file" logging: *default-logging #+end_src =traefik.yaml= #+begin_src yaml :tangle /ssh:thomas@homelab:/home/thomas/docker/config/traefik2/traefik.yaml global: checkNewVersion: true sendAnonymousUsage: false entryPoints: web: address: :80 web-secure: address: :443 forwardedHeaders: trustedIPs: 173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22 matrix-federation: address: :8448 matrix-internal-matrix-client-api: address: :8008 api: dashboard: true core: defaultRuleSyntax: v2 log: level: ERROR metrics: influxDB2: address: https://influxdb.$DOMAINNAME token: dhkvChi1tXrMY18plDTWifz8MZNUm2M4QGpEAd2FftmMlfsN7KLq96uQXADbiQxDb1Vo2pYTSblCGqrfVygqJw== org: homelab bucket: traefik accessLog: filePath: /var/log/access.log filters: statusCodes: 400-499 providers: docker: endpoint: unix:///var/run/docker.sock defaultrule: Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME`) exposedByDefault: false network: t2_proxy file: filename: /etc/traefik/services.yaml serversTransport: insecureSkipVerify: true # Necessary for Unifi (but not recommended) # respondingTimeouts: # readTimeout: "5s" # writeTimeout: "5s" # idleTimeout: "360s" certificatesResolvers: dns-cloudflare: acme: # caServer: https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing email: dehaeze.thomas@gmail.com storage: /acme.json dnsChallenge: provider: cloudflare resolvers: 1.1.1.1:53,1.0.0.1:53 # delayBeforeCheck: 90 # To delay DNS check and reduce LE hitrate #+end_src #+begin_src yaml :tangle /ssh:thomas@homelab:/home/thomas/docker/config/traefik2/services.yaml http: services: openwrt: loadBalancer: servers: - url: "http://192.168.1.1/" valetudo: loadBalancer: servers: - url: "http://192.168.1.110/" - url: "http://192.168.2.157/" - url: "http://192.168.5.157/" healthCheck: path: / middlewares: unifiHeaders: headers: customRequestHeaders: Authorization: "" # Removes basic-auth: basicAuth: users: - "tdehaeze:$2y$05$SSzSMIUEGrfQgZMas1ROYeLzqfuqnQG6hJRgxGWV2It5yv7YzN3Ay" #+end_src *** =authelia= - Single Sign-On Multi-Factor portal ([[https://github.com/authelia/authelia][link]]) #+begin_src yaml authelia: container_name: authelia image: authelia/authelia:4.35 restart: unless-stopped networks: - t2_proxy - backend volumes: - $CONFIGDIR/authelia:/config - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - AUTHELIA_NOTIFIER_SMTP_PASSWORD=$GOOGLE_AUTHELIA_PASS - AUTHELIA_JWT_SECRET=$AUTHELIA_JWT_SECRET labels: - "traefik.enable=true" - "traefik.http.routers.authelia-rtr.entrypoints=web-secure" - "traefik.http.routers.authelia-rtr.tls=true" - "traefik.http.routers.authelia-rtr.service=authelia-svc" - "traefik.http.routers.authelia-rtr.rule=Host(`login.$DOMAINNAME`)" - "traefik.http.services.authelia-svc.loadbalancer.server.port=9091" - "traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://login.$DOMAINNAME/" - "traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true" - "traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email" - "treafik.http.middlewares.chain-authelia.chain.middlewares=middlewares-rate-limit, middlewares-secure-headers, middlewares-authelia" - "traefik.docker.network=t2_proxy" #+end_src =configuration.yml= #+begin_src yaml :tangle /ssh:thomas@homelab:/home/thomas/docker/config/authelia/configuration.yml --- ############################################################### # Authelia configuration # ############################################################### default_redirection_url: https://authelia.tdehaeze.xyz server: host: 0.0.0.0 port: 9091 log: level: debug totp: issuer: authelia.com period: 30 skew: 1 authentication_backend: file: path: /config/users_database.yml password: algorithm: argon2id iterations: 1 salt_length: 16 parallelism: 8 memory: 1024 access_control: default_policy: deny rules: - domain: valetudo.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - ["group:colloc"] - domain: openwrt.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: traefik.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: scrutiny.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: sync-jm.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: sync-anne.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: syncthing.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: uptime.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: homepage.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: wireguard.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: change.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: esphome.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: influxdb.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: node-red.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - ["group:colloc"] - domain: mqttui.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: zigbee2mqtt.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: restic.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: qobuz.tdehaeze.xyz policy: bypass resources: - "^/download.*$" - domain: qobuz.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - ["group:friends"] - ["group:family"] - domain: sonarr.tdehaeze.xyz policy: bypass networks: - 172.18.0.0/16 - domain: sonarr.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: prowlarr.tdehaeze.xyz policy: bypass networks: - 172.18.0.0/16 - domain: prowlarr.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: radarr.tdehaeze.xyz policy: bypass networks: - 172.18.0.0/16 - domain: radarr.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: unifi.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: joal.tdehaeze.xyz policy: one_factor subject: - ["group:admins"] - domain: owasabi.tdehaeze.xyz policy: one_factor resources: - "^/control.*$" subject: - ["group:admins"] - ["user:owasabi"] - domain: owasabi.tdehaeze.xyz policy: bypass - domain: owasabi-mountains.tdehaeze.xyz policy: one_factor resources: - "^/control.*$" subject: - ["group:admins"] - ["user:owasabi"] - domain: owasabi-mountains.tdehaeze.xyz policy: bypass session: name: authelia_session expiration: 3600 inactivity: 300 domain: tdehaeze.xyz regulation: max_retries: 3 find_time: 120 ban_time: 300 storage: encryption_key: bUEO5bYNJYziXUxEWFYubUmUdUZPhy local: path: /config/db.sqlite3 notifier: smtp: host: smtp.gmail.com port: 587 username: tdehaeze.xyz@gmail.com sender: tdehaeze.xyz@gmail.com #+end_src *** =uptime-kuma= - Monitoring Tool ([[https://github.com/louislam/uptime-kuma][link]]) #+begin_src yaml uptime-kuma: container_name: uptime-kuma image: louislam/uptime-kuma:2 restart: unless-stopped networks: - t2_proxy environment: - TZ=$TZ - PUID=$PUID - PGID=$PGID volumes: - /docker/uptime-kuma:/app/data labels: - "traefik.enable=true" - "traefik.http.routers.uptime-rtr.entrypoints=web-secure" - "traefik.http.routers.uptime-rtr.rule=Host(`uptime.$DOMAINNAME`)" - "traefik.http.routers.uptime-rtr.tls=true" - "traefik.http.routers.uptime-rtr.service=uptime-svc" - "traefik.http.routers.uptime-rtr.middlewares=authelia@docker" - "traefik.http.services.uptime-svc.loadbalancer.server.port=3001" logging: *default-logging #+end_src *** =gotify= - Notification service ([[https://github.com/gotify/server][link]]) In order to have notifications on Linux desktop use [[https://github.com/ztpnk/gotify-dunst][gotify-dunst]]. #+begin_src yaml gotify: container_name: gotify image: gotify/server restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - GOTIFY_DEFAULTUSER_NAME=$GOTIFY_DEFAULTUSER_NAME - GOTIFY_DEFAULTUSER_PASS=$GOTIFY_DEFAULTUSER_PASS volumes: - $CONFIGDIR/gotify:/app/data labels: - "traefik.enable=true" - "traefik.http.routers.gotify-rtr.entrypoints=web-secure" - "traefik.http.routers.gotify-rtr.rule=Host(`gotify.$DOMAINNAME`)" - "traefik.http.routers.gotify-rtr.tls=true" - "traefik.http.routers.gotify-rtr.service=gotify-svc" - "traefik.http.services.gotify-svc.loadbalancer.server.port=80" #+end_src *** =scrutiny= - Hard drive monitoring ([[https://hub.docker.com/r/hotio/scrutiny][link]]) #+begin_src yaml scrutiny-web: container_name: scrutiny-web image: ghcr.io/analogj/scrutiny:master-web restart: unless-stopped networks: - t2_proxy - backend environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - SCRUTINY_WEB_INFLUXDB_HOST=influxdb volumes: - $CONFIGDIR/scrutiny:/opt/scrutiny/config labels: - "traefik.enable=true" - "traefik.http.routers.scrutiny-rtr.entrypoints=web-secure" - "traefik.http.routers.scrutiny-rtr.rule=Host(`scrutiny.$DOMAINNAME`)" - "traefik.http.routers.scrutiny-rtr.tls=true" - "traefik.http.routers.scrutiny-rtr.service=scrutiny-svc" - "traefik.http.routers.scrutiny-rtr.middlewares=authelia@docker" - "traefik.http.services.scrutiny-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src #+begin_src yaml scrutiny-collector: container_name: scrutiny-collector image: ghcr.io/analogj/scrutiny:master-collector restart: unless-stopped cap_add: - SYS_RAWIO - SYS_ADMIN networks: - backend environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - COLLECTOR_API_ENDPOINT=http://scrutiny-web:8080 volumes: - /run/udev:/run/udev:ro devices: - /dev/sda:/dev/sda - /dev/sdb:/dev/sdb - /dev/sdc:/dev/sdc - /dev/sdd:/dev/sdd - /dev/nvme0:/dev/nvme0 logging: *default-logging #+end_src *** =wireguard= - VPN ([[https://github.com/linuxserver/docker-wireguard][link]]) #+begin_src yaml wireguard: container_name: wireguard image: weejewel/wg-easy restart: unless-stopped networks: - t2_proxy cap_add: - NET_ADMIN - SYS_MODULE environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - WG_HOST=82.66.44.13 - PASSWORD_HASH='$$2a$$12$$kVt.q4N25VD/n5bXjk9yGubmHlPjGtXKGcDa2c3qYzfse4U502mzm' volumes: - $CONFIGDIR/wg-easy:/etc/wireguard ports: - 51820:51820/udp sysctls: - net.ipv4.ip_forward=1 - net.ipv4.conf.all.src_valid_mark=1 labels: - "traefik.enable=true" - "traefik.http.routers.wireguard-rtr.entrypoints=web-secure" - "traefik.http.routers.wireguard-rtr.rule=Host(`wireguard.$DOMAINNAME`)" - "traefik.http.routers.wireguard-rtr.tls=true" - "traefik.http.routers.wireguard-rtr.service=wireguard-svc" - "traefik.http.routers.wireguard-rtr.middlewares=authelia@docker" - "traefik.http.services.wireguard-svc.loadbalancer.server.port=51821" logging: *default-logging #+end_src *** =nginx= - Root (used for Matrix) #+begin_src yaml root: container_name: root image: nginx restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/root/nginx.conf:/etc/nginx/nginx.conf labels: - "traefik.enable=true" - "traefik.http.routers.root-rtr.entrypoints=web-secure" - "traefik.http.routers.root-rtr.rule=Host(`$DOMAINNAME`)" - "traefik.http.routers.root-rtr.tls=true" - "traefik.http.routers.root-rtr.service=root-svc" - "traefik.http.services.root-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src =nginx.conf= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/root/nginx.conf events { } http { server { server_name tdehaeze.xyz; listen 8080; location /.well-known/matrix/client { proxy_pass https://matrix.tdehaeze.xyz/.well-known/matrix/client; proxy_set_header X-Forwarded-For $remote_addr; proxy_ssl_server_name on; } location /.well-known/matrix/server { proxy_pass https://matrix.tdehaeze.xyz/.well-known/matrix/server; proxy_set_header X-Forwarded-For $remote_addr; proxy_ssl_server_name on; } } } #+end_src *** =commento= - Commenting system ([[https://github.com/adtac/commento][link]]) #+begin_src yaml commento: container_name: commento image: registry.gitlab.com/commento/commento restart: unless-stopped networks: - t2_proxy - backend # ports: # - 8080:8080 environment: - TZ=$TZ - UID=$PUID - GID=$PGID - COMMENTO_ORIGIN=https://commento.tdehaeze.xyz/ - COMMENTO_PORT=8080 - COMMENTO_POSTGRES=postgres://postgres:$COMMENTO_DB_PASSWORD@commento_db:5432/commento?sslmode=disable - COMMENTO_SMTP_HOST=smtp.gmail.com - COMMENTO_SMTP_PORT=587 - COMMENTO_SMTP_USERNAME=tdehaeze.xyz@gmail.com - COMMENTO_SMTP_PASSWORD=$GOOGLE_AUTHELIA_PASS - COMMENTO_SMTP_FROM_ADDRESS=tdehaeze.xyz@gmail.com depends_on: - commento_db labels: - "traefik.enable=true" - "traefik.http.routers.commento-rtr.entrypoints=web-secure" - "traefik.http.routers.commento-rtr.rule=Host(`commento.$DOMAINNAME`)" - "traefik.http.routers.commento-rtr.tls=true" - "traefik.http.routers.commento-rtr.service=commento-svc" - "traefik.http.services.commento-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src #+begin_src yaml commento_db: image: postgres:13 shm_size: 512mb restart: unless-stopped networks: - backend user: "${PUID}:${PGID}" environment: - POSTGRES_DB=commento - POSTGRES_USER=postgres - POSTGRES_PASSWORD=$COMMENTO_DB_PASSWORD volumes: - $CONFIGDIR/commento_db:/var/lib/postgresql/data logging: *default-logging #+end_src *** =rustdesk= - Remote desktop application ([[https://github.com/rustdesk/rustdesk][link]]) #+begin_src yaml hbbs: container_name: hbbs image: rustdesk/rustdesk-server:latest restart: unless-stopped command: hbbs -r rustdesk.tdehaeze.xyz:21117 volumes: - $CONFIGDIR/rustdesk:/root ports: - 21115:21115 - 21116:21116 - 21116:21116/udp - 21118:21118 depends_on: - hbbr hbbr: container_name: hbbr image: rustdesk/rustdesk-server:latest restart: unless-stopped command: hbbr volumes: - $CONFIGDIR/rustdesk:/root ports: - 21117:21117 - 21119:21119 labels: - "traefik.enable=true" - "traefik.http.routers.rustdesk-rtr.entrypoints=web-secure" - "traefik.http.routers.rustdesk-rtr.rule=Host(`rustdesk.$DOMAINNAME`)" - "traefik.http.routers.rustdesk-rtr.tls=true" - "traefik.http.routers.rustdesk-rtr.service=rustdesk-svc" - "traefik.http.services.rustdesk-svc.loadbalancer.server.port=21117" #+end_src *** =unifi-controller= - Software for Unifi devices ([[https://hub.docker.com/r/linuxserver/unifi-controller][link]]) #+begin_src yaml unifi-mongodb: container_name: unifi-mongodb image: mongo:4 networks: - backend restart: unless-stopped environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/unifi-mongodb/db:/data/db logging: *default-logging #+end_src #+begin_src yaml unifi-controller: container_name: unifi-controller image: linuxserver/unifi-network-application networks: - t2_proxy - backend restart: unless-stopped environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - MONGO_USER=unifi - MONGO_PASS=bMhre3Nza6mZzz1m - MONGO_HOST=unifi-mongodb - MONGO_PORT=27017 - MONGO_DBNAME=unifi volumes: - $CONFIGDIR/unifi/data:/config ports: # - 8443:8443 - 3478:3478/udp - 10001:10001/udp - 8080:8080 # - 1900:1900/udp #optional # - 8843:8843 #optional # - 8880:8880 #optional # - 6789:6789 #optional # - 5514:5514/udp #optional labels: - "traefik.enable=true" - "traefik.http.routers.unifi-rtr.entrypoints=web-secure" - "traefik.http.routers.unifi-rtr.rule=Host(`unifi.$DOMAINNAME`)" - "traefik.http.routers.unifi-rtr.tls=true" - "traefik.http.routers.unifi-rtr.service=unifi-svc" - "traefik.http.routers.unifi-rtr.middlewares=unifiHeaders@file" - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https" # - "traefik.http.routers.unifi-rtr.middlewares=authelia@docker" - "traefik.http.services.unifi-svc.loadbalancer.server.port=8443" - "traefik.http.services.unifi-svc.loadbalancer.server.scheme=https" logging: *default-logging #+end_src #+begin_src yaml :tangle no unifi-controller: image: jacobalberty/unifi networks: - t2_proxy restart: unless-stopped environment: - RUNAS_UID0=false - UNIFI_UID=$PUID - UNIFI_GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/unifi-controller/data:/unifi/data - $CONFIGDIR/unifi-controller/log:/unifi/log - $CONFIGDIR/unifi-controller/cert:/unifi/cert - $CONFIGDIR/unifi-controller/init.d:/unifi/init.d ports: - 3478:3478/udp # STUN - 10001:10001/udp # AP discovery - 6789:6789/tcp # Speed test - 8080:8080/tcp # Device/ controller comm. - 8443:8443/tcp # Controller GUI/API as seen in a web browser - 8880:8880/tcp # HTTP portal redirection - 8843:8843/tcp # HTTPS portal redirection labels: - "traefik.enable=true" - "traefik.http.routers.unifi-rtr.entrypoints=web-secure" - "traefik.http.routers.unifi-rtr.rule=Host(`unifi.$DOMAINNAME`)" - "traefik.http.routers.unifi-rtr.tls=true" - "traefik.http.routers.unifi-rtr.service=unifi-svc" - "traefik.http.services.unifi-svc.loadbalancer.serverstransport=ignorecert" - "traefik.http.services.unifi-svc.loadbalancer.server.scheme=https" - "traefik.http.services.unifi-svc.loadbalancer.server.port=8443" logging: *default-logging #+end_src ** Websites *** =homepage= - A highly customizable homepage ([[https://github.com/gethomepage/homepage][link]]) #+begin_src yaml homepage: container_name: homepage image: ghcr.io/gethomepage/homepage:latest restart: unless-stopped networks: - t2_proxy environment: - HOMEPAGE_ALLOWED_HOSTS=* # TODO - Not recommanded See gethomepage.dev/installation/#homepage_allowed_hosts - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/homepage/:/app/config - /var/run/docker.sock:/var/run/docker.sock:ro # optional, for docker integrations - /mnt/disk0:/mnt/disk0:ro - /mnt/disk1:/mnt/disk1:ro - /mnt/disk2:/mnt/disk2:ro labels: - "traefik.enable=true" - "traefik.http.routers.homepage-rtr.entrypoints=web-secure" - "traefik.http.routers.homepage-rtr.rule=Host(`homepage.$DOMAINNAME`)" - "traefik.http.routers.homepage-rtr.tls=true" - "traefik.http.routers.homepage-rtr.service=homepage-svc" - "traefik.http.routers.homepage-rtr.middlewares=authelia@docker" - "traefik.http.services.homepage-svc.loadbalancer.server.port=3000" logging: *default-logging #+end_src *** =hugo= - Wiki + Blog ([[https://git.tdehaeze.xyz/tdehaeze/digital-brain][link]]) #+begin_src yaml hugo: container_name: hugo image: tdehaeze/hugo-caddy restart: unless-stopped networks: - t2_proxy environment: - REPO=git.tdehaeze.xyz/tdehaeze/digital-brain labels: - "traefik.enable=true" - "traefik.http.routers.hugo-rtr.entrypoints=web-secure" - "traefik.http.routers.hugo-rtr.rule=Host(`brain.$DOMAINNAME`)" - "traefik.http.routers.hugo-rtr.tls=true" - "traefik.http.routers.hugo-rtr.service=hugo-svc" - "traefik.http.services.hugo-svc.loadbalancer.server.port=2015" logging: *default-logging #+end_src *** =research= - Research Pages ([[https://git.tdehaeze.xyz/tdehaeze/research-home-page][link]]) #+begin_src yaml research: container_name: research image: abiosoft/caddy:1.0.3-no-stats restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - PLUGINS=git volumes: - $CONFIGDIR/research/Caddyfile:/etc/Caddyfile - /docker/research:/srv # - ~/.ssh:/root/.ssh labels: - "homepage.group=Blog" - "homepage.href=`research.$DOMAINNAME`" - "homepage.description=Research blog" - "traefik.enable=true" - "traefik.http.routers.caddy-rtr.entrypoints=web-secure" - "traefik.http.routers.caddy-rtr.rule=Host(`research.$DOMAINNAME`)" - "traefik.http.routers.caddy-rtr.tls=true" - "traefik.http.routers.caddy-rtr.service=caddy-svc" - "traefik.http.services.caddy-svc.loadbalancer.server.port=2015" logging: *default-logging #+end_src =Caddyfile= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/caddy/Caddyfile 0.0.0.0:2015 { root /srv/www/ git { repo https://git.tdehaeze.xyz/tdehaeze/research-home-page path /srv/www/ interval -1 hook /research-home-page/webhook QHZgAKjD8q2v54Ru then git submodule update --init --recursive --merge --remote } } #+end_src *** =dotfiles= - Dotfiles ([[https://git.tdehaeze.xyz/tdehaeze/literate-dotfiles][link]]) #+begin_src yaml dotfiles: container_name: dotfiles image: abiosoft/caddy:1.0.3-no-stats restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - PLUGINS=git volumes: - $CONFIGDIR/dotfiles/Caddyfile:/etc/Caddyfile - $CONFIGDIR/dotfiles/www:/srv/www labels: - "traefik.enable=true" - "traefik.http.routers.dotfiles-rtr.entrypoints=web-secure" - "traefik.http.routers.dotfiles-rtr.rule=Host(`dotfiles.$DOMAINNAME`)" - "traefik.http.routers.dotfiles-rtr.tls=true" - "traefik.http.routers.dotfiles-rtr.service=dotfiles-svc" - "traefik.http.services.dotfiles-svc.loadbalancer.server.port=2015" logging: *default-logging #+end_src =Caddyfile= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/dotfiles/Caddyfile 0.0.0.0:2015 { root /srv/www/docs/ git { repo https://git.tdehaeze.xyz/tdehaeze/literate-dotfiles path /srv/www/ interval -1 hook /literate-dotfiles/webhook QHZgAKjD8q2v54Ru } } #+end_src *** =help= - Help page for Jellyfin ([[https://git.tdehaeze.xyz/tdehaeze/family-page][link]]) #+begin_src yaml help: container_name: help image: abiosoft/caddy:1.0.3-no-stats restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - PLUGINS=git volumes: - $CONFIGDIR/help/Caddyfile:/etc/Caddyfile - $CONFIGDIR/help/www:/srv/www labels: - "traefik.enable=true" - "traefik.http.routers.help-rtr.entrypoints=web-secure" - "traefik.http.routers.help-rtr.rule=Host(`help.$DOMAINNAME`)" - "traefik.http.routers.help-rtr.tls=true" - "traefik.http.routers.help-rtr.service=help-svc" - "traefik.http.services.help-svc.loadbalancer.server.port=2015" logging: *default-logging #+end_src =Caddyfile= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/help/Caddyfile 0.0.0.0:2015 { root /srv/www/ git { repo https://git.tdehaeze.xyz/tdehaeze/family-page path /srv/www/ interval -1 hook /help/webhook 0fdVzNShbcmw } } #+end_src *** =mealie= - Recipe Manager ([[https://github.com/hay-kot/mealie][link]]) #+begin_src yaml miam: container_name: miam image: hkotel/mealie restart: unless-stopped networks: - t2_proxy environment: - db_type=sqlite - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/mealie:/app/data labels: - "traefik.enable=true" - "traefik.http.routers.miam-rtr.entrypoints=web-secure" - "traefik.http.routers.miam-rtr.rule=Host(`miam.$DOMAINNAME`)" - "traefik.http.routers.miam-rtr.tls=true" - "traefik.http.routers.miam-rtr.service=miam-svc" - "traefik.http.services.miam-svc.loadbalancer.server.port=9000" logging: *default-logging #+end_src *** =gitea= - Git server ([[https://github.com/go-gitea/gitea][link]]) #+begin_src yaml gitea: container_name: gitea image: gitea/gitea depends_on: - gitea_db restart: unless-stopped networks: - t2_proxy - backend volumes: - $CONFIGDIR/gitea:/data environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - SSH_PORT=$GITEA_SSH_PORT ports: - "2222:22" labels: - "traefik.enable=true" - "traefik.http.routers.git-rtr.entrypoints=web-secure" - "traefik.http.routers.git-rtr.rule=Host(`git.$DOMAINNAME`)" - "traefik.http.routers.git-rtr.tls=true" - "traefik.http.routers.git-rtr.service=git-svc" - "traefik.http.services.git-svc.loadbalancer.server.port=3000" logging: *default-logging #+end_src #+begin_src yaml gitea_db: container_name: gitea_db image: mariadb:10 restart: unless-stopped networks: - backend ports: - 3306:3306 user: "${PUID}:${PGID}" environment: - MYSQL_ROOT_PASSWORD=$GITEA_DB_MYSQL_ROOT_PASSWORD - MYSQL_DATABASE=gitea - MYSQL_USER=gitea - MYSQL_PASSWORD=$GITEA_DB_MYSQL_PASSWORD volumes: - $CONFIGDIR/gitea_db:/var/lib/mysql #+end_src *** =changedetection= - Detect change in websites ([[https://github.com/dgtlmoon/changedetection.io][link]]) #+begin_src yaml changedetection: container_name: changedetection image: ghcr.io/dgtlmoon/changedetection.io restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - BASE_URL=https://change.tdehaeze.xyz volumes: - $CONFIGDIR/changedetection:/datastore labels: - "traefik.enable=true" - "traefik.http.routers.changedetection-rtr.entrypoints=web-secure" - "traefik.http.routers.changedetection-rtr.rule=Host(`change.$DOMAINNAME`)" - "traefik.http.routers.changedetection-rtr.tls=true" - "traefik.http.routers.changedetection-rtr.service=changedetection-svc" - "traefik.http.routers.changedetection-rtr.middlewares=authelia@docker" - "traefik.http.services.changedetection-svc.loadbalancer.server.port=5000" logging: *default-logging #+end_src *** =wingaudio= - With Wordpress #+begin_src yaml wingaudio: container_name: wingaudio image: wordpress depends_on: - wingaudio_db restart: unless-stopped networks: - t2_proxy - backend volumes: - $CONFIGDIR/wingaudio:/var/www/html environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - WORDPRESS_DB_HOST=wingaudio_db - WORDPRESS_DB_USER=wingaudio - WORDPRESS_DB_PASSWORD=$WINGAUDIO_DB_MYSQL_PASSWORD - WORDPRESS_DB_NAME=wingaudio user: "${PUID}:${PGID}" labels: - "traefik.enable=true" - "traefik.http.routers.wingaudio-rtr.entrypoints=web-secure" - "traefik.http.routers.wingaudio-rtr.rule=Host(`wingaudio.fr`)" - "traefik.http.routers.wingaudio-rtr.tls=true" - "traefik.http.routers.wingaudio-rtr.service=wingaudio-svc" - "traefik.http.services.wingaudio-svc.loadbalancer.server.port=80" logging: *default-logging #+end_src #+begin_src yaml wingaudio_db: container_name: wingaudio_db image: mysql:5.7 restart: unless-stopped networks: - backend user: "${PUID}:${PGID}" environment: - MYSQL_DATABASE=wingaudio - MYSQL_USER=wingaudio - MYSQL_PASSWORD=$WINGAUDIO_DB_MYSQL_PASSWORD - MYSQL_RANDOM_ROOT_PASSWORD=$WINGAUDIO_DB_MYSQL_ROOT_PASSWORD volumes: - $CONFIGDIR/wingaudio_db:/var/lib/mysql logging: *default-logging #+end_src ** Multimedia *** =jellyfin= - Media server ([[https://hub.docker.com/r/linuxserver/jellyfin][link]]) #+begin_src yaml jellyfin: container_name: jellyfin image: linuxserver/jellyfin restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/jellyfin:/config - /docker/jellyfin-cache:/cache - /docker/jellyfin-metadata:/metadata - /srv/storage/TVShows:/data/tvshows - /srv/storage/Documentaries:/data/documentaries - /srv/storage/LiveMusic:/data/livemusic - /srv/storage/Animes:/data/animes - /srv/storage/Movies:/data/movies - /srv/storage/Music:/data/music - /srv/storage/StandUp:/data/standup environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ group_add: - 109 devices: # VAAPI Devices - /dev/dri/renderD128:/dev/dri/renderD128 - /dev/dri/card1:/dev/dri/card1 ports: - 8096:8096 labels: - "traefik.enable=true" - "traefik.http.routers.jellyfin-rtr.entrypoints=web-secure" - "traefik.http.routers.jellyfin-rtr.rule=Host(`jellyfin.$DOMAINNAME`)" - "traefik.http.routers.jellyfin-rtr.tls=true" - "traefik.http.routers.jellyfin-rtr.service=jellyfin-svc" - "traefik.http.services.jellyfin-svc.loadbalancer.server.port=8096" logging: *default-logging #+end_src *** =jellystat= - Statistics App for Jellyfin ([[https://github.com/CyferShepard/Jellystat][link]]) #+begin_src yaml jellystat: container_name: jellystat image: cyfershepard/jellystat:latest restart: unless-stopped networks: - backend - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - POSTGRES_USER=postgres - POSTGRES_PASSWORD=fmxi0iS3TSGVigvZ - POSTGRES_IP=jellystat_db - POSTGRES_PORT=5432 - JWT_SECRET='k36isYXNuQT7Kk9S' volumes: - $CONFIGDIR/jellystat:/app/backend/backup-data depends_on: - jellystat_db labels: - "traefik.enable=true" - "traefik.http.routers.jellystat-rtr.entrypoints=web-secure" - "traefik.http.routers.jellystat-rtr.rule=Host(`jellystat.$DOMAINNAME`)" - "traefik.http.routers.jellystat-rtr.tls=true" - "traefik.http.routers.jellystat-rtr.service=jellystat-svc" - "traefik.http.services.jellystat-svc.loadbalancer.server.port=3000" logging: *default-logging #+end_src #+begin_src yaml jellystat_db: image: postgres:15.2 shm_size: 512mb restart: unless-stopped networks: - backend volumes: - $CONFIGDIR/jellystat_db:/var/lib/postgresql/data environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - POSTGRES_DB='jfstat' - POSTGRES_USER=postgres - POSTGRES_PASSWORD=fmxi0iS3TSGVigvZ #+end_src *** =jfa-go= - Manage Jellyfin Users ([[https://github.com/hrfee/jfa-go][link]]) #+begin_src yaml jfa: container_name: jfa image: hrfee/jfa-go restart: unless-stopped depends_on: - jellyfin networks: - t2_proxy volumes: - $CONFIGDIR/jfa:/data - $CONFIGDIR/jellyfin:/jf - /etc/localtime:/etc/localtime:ro environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.jfa-rtr.entrypoints=web-secure" - "traefik.http.routers.jfa-rtr.rule=Host(`jfa.$DOMAINNAME`)" - "traefik.http.routers.jfa-rtr.tls=true" - "traefik.http.routers.jfa-rtr.service=jfa-svc" - "traefik.http.services.jfa-svc.loadbalancer.server.port=8056" logging: *default-logging #+end_src *** =lms= - Server for Squeezebox and compatible players ([[https://github.com/LMS-Community/slimserver][link]]) #+begin_src yaml lms: container_name: lms image: lmscommunity/lyrionmusicserver restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/lms/config:/config:rw - $CONFIGDIR/lms/playlist:/playlist:rw - /srv/storage/Music:/music:ro - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro ports: - 9000:9000/tcp - 9090:9090/tcp - 3483:3483/tcp environment: - HTTP_PORT=9000 labels: - "traefik.enable=true" # - "traefik.http.routers.lms-rtr.entrypoints=web-secure" # - "traefik.http.routers.lms-rtr.rule=Host(`lms.$DOMAINNAME`)" # - "traefik.http.routers.lms-rtr.tls=true" # - "traefik.http.routers.lms-rtr.service=lms-svc" # - "traefik.http.services.lms-svc.loadbalancer.server.port=9000" logging: *default-logging #+end_src ** Cloud *** =syncthing= - File Synchronization ([[https://hub.docker.com/r/linuxserver/syncthing][link]]) #+begin_src yaml syncthing: container_name: syncthing image: linuxserver/syncthing restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - UMASK_SET=022 volumes: - $CONFIGDIR/syncthing:/config - /srv/storage/Cloud:/Cloud - /srv/storage/Cloud/pictures/phone:/Pictures - /srv/storage/Cloud/pdfs:/Onyx/Download - /srv/storage/Cloud/pdfs-notes:/Onyx/note - /srv/storage/Cloud/.stfolder:/Onyx/.stfolder - /srv/storage/.password-store:/.password-store ports: - 22000:22000 - 21027:21027/udp labels: - "traefik.enable=true" - "traefik.http.routers.syncthing-rtr.entrypoints=web-secure" - "traefik.http.routers.syncthing-rtr.rule=Host(`syncthing.$DOMAINNAME`)" - "traefik.http.routers.syncthing-rtr.tls=true" - "traefik.http.routers.syncthing-rtr.service=syncthing-svc" - "traefik.http.routers.syncthing-rtr.middlewares=authelia@docker" - "traefik.http.services.syncthing-svc.loadbalancer.server.port=8384" logging: *default-logging #+end_src *** =sync-anne= - File Synchronization ([[https://hub.docker.com/r/linuxserver/syncthing][link]]) #+begin_src yaml sync-anne: container_name: sync-anne image: linuxserver/syncthing restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - UMASK_SET=022 volumes: - $CONFIGDIR/sync-anne:/config - /srv/storage/Users/anne:/Cloud - /srv/storage/Users/anne/Photos/telephone:/telephone ports: - 22001:22001 - 21028:21028/udp labels: - "traefik.enable=true" - "traefik.http.routers.sync-anne-rtr.entrypoints=web-secure" - "traefik.http.routers.sync-anne-rtr.rule=Host(`sync-anne.$DOMAINNAME`)" - "traefik.http.routers.sync-anne-rtr.tls=true" - "traefik.http.routers.sync-anne-rtr.service=sync-anne-svc" - "traefik.http.routers.sync-anne-rtr.middlewares=authelia@docker" - "traefik.http.services.sync-anne-svc.loadbalancer.server.port=8384" logging: *default-logging #+end_src *** =sync-jm= - File Synchronization ([[https://hub.docker.com/r/linuxserver/syncthing][link]]) #+begin_src yaml sync-jm: container_name: sync-jm image: linuxserver/syncthing restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - UMASK_SET=022 volumes: - $CONFIGDIR/sync-jm:/config - /srv/storage/Users/jean-marie:/Cloud # - /srv/storage/Users/jean-marie/Photos/telephone:/telephone ports: - 22002:22002 - 21029:21029/udp labels: - "traefik.enable=true" - "traefik.http.routers.sync-jm-rtr.entrypoints=web-secure" - "traefik.http.routers.sync-jm-rtr.rule=Host(`sync-jm.$DOMAINNAME`)" - "traefik.http.routers.sync-jm-rtr.tls=true" - "traefik.http.routers.sync-jm-rtr.service=sync-jm-svc" - "traefik.http.routers.sync-jm-rtr.middlewares=authelia@docker" - "traefik.http.services.sync-jm-svc.loadbalancer.server.port=8384" logging: *default-logging #+end_src *** =filebrowser-quantum= - Web file browser ([[https://hub.docker.com/r/filebrowser/filebrowser][link]]) #+begin_src yaml filebrowser: container_name: filebrowser image: gtstef/filebrowser:stable restart: unless-stopped networks: - t2_proxy volumes: - /srv/storage:/srv/storage - $CONFIGDIR/filebrowser-quantum:/home/filebrowser/data - /docker/filebrowser-tmp:/home/filebrowser/tmp # Required if uid other than 1000 user: "${PUID}:${PGID}" environment: - FILEBROWSER_CONFIG=data/config.yaml - FILEBROWSER_DATABASE=data/database.db - PUID=$PUID - PGID=$PGID - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.cloud-rtr.entrypoints=web-secure" - "traefik.http.routers.cloud-rtr.rule=Host(`cloud.$DOMAINNAME`)" - "traefik.http.routers.cloud-rtr.tls=true" - "traefik.http.routers.cloud-rtr.service=cloud-svc" - "traefik.http.services.cloud-svc.loadbalancer.server.port=80" - "traefik.http.middlewares.filebrowser-buffering.buffering.maxRequestBodyBytes=10737418240" # Upload Configuration logging: *default-logging #+end_src *** =radicale= - CalDAV/CardDAV server ([[https://github.com/tomsquest/docker-radicale][link]]) #+begin_src yaml radicale: container_name: radicale image: tomsquest/docker-radicale restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/radicale/config:/config:ro - $CONFIGDIR/radicale/data:/data environment: - TZ=$TZ - UID=$PUID - GID=$PGID security_opt: - no-new-privileges:true cap_drop: - ALL cap_add: - SETUID - SETGID - CHOWN - KILL labels: - "traefik.enable=true" - "traefik.http.routers.radicale-rtr.entrypoints=web-secure" - "traefik.http.routers.radicale-rtr.rule=Host(`radicale.$DOMAINNAME`)" - "traefik.http.routers.radicale-rtr.tls=true" - "traefik.http.routers.radicale-rtr.service=radicale-svc" - "traefik.http.services.radicale-svc.loadbalancer.server.port=5232" logging: *default-logging #+end_src =config= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/radicale/config/config [server] hosts = 0.0.0.0:5232 [auth] type = htpasswd htpasswd_filename = /config/users htpasswd_encryption = md5 [storage] filesystem_folder = /data/collections #+end_src *** =linkding= - Bookmark manager ([[https://github.com/sissbruecker/linkding][link]]) #+begin_src yaml linkding: container_name: linkding image: sissbruecker/linkding restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/linkding:/etc/linkding/data user: "${PUID}:${PGID}" environment: - TZ=$TZ - PUID=$PUID - PGID=$PGID labels: - "traefik.enable=true" - "traefik.http.routers.linkding-rtr.entrypoints=web-secure" - "traefik.http.routers.linkding-rtr.rule=Host(`bm.$DOMAINNAME`)" - "traefik.http.routers.linkding-rtr.tls=true" - "traefik.http.routers.linkding-rtr.service=linkding-svc" - "traefik.http.services.linkding-svc.loadbalancer.server.port=9090" logging: *default-logging #+end_src *** =backrest= - Automatic Backups ([[https://github.com/garethgeorge/backrest][link]]) #+begin_src yaml restic: container_name: restic image: garethgeorge/backrest:latest-alpine restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ - BACKREST_DATA=/data # path for backrest data. restic binary and the database are placed here. - BACKREST_CONFIG=/config/config.json # path for the backrest config file. - XDG_CACHE_HOME=/cache # path for the restic cache which greatly improves performance. volumes: - $CONFIGDIR/restic/config:/config - $CONFIGDIR/restic/data:/data - /docker/restic-cache:/cache - /srv/storage/Backups:/srv/Backups # Local Restic Backups - /srv/storage/Users:/source/Users:ro # User Clouds - /srv/storage/Cloud:/source/Cloud:ro # My Own Cloud # - /srv/storage/Music:/source/Music:ro # Musics - /srv/storage/immich:/source/immich:ro # Musics - /home/thomas:/source/home:ro # Homelab - Home directory - /home/thomas/.ssh/known_hosts:/root/.ssh/known_hosts:ro # Used to SSH to backup machine - /home/thomas/.ssh/id_rsa:/root/.ssh/id_rsa:ro # Used to SSH to backup machine labels: - "traefik.enable=true" - "traefik.http.routers.restic-rtr.entrypoints=web-secure" - "traefik.http.routers.restic-rtr.rule=Host(`restic.$DOMAINNAME`)" - "traefik.http.routers.restic-rtr.tls=true" - "traefik.http.routers.restic-rtr.service=restic-svc" - "traefik.http.routers.restic-rtr.middlewares=authelia@docker" - "traefik.http.services.restic-svc.loadbalancer.server.port=9898" logging: *default-logging #+end_src *** =miniflux= - RSS reader ([[https://hub.docker.com/r/miniflux/miniflux][link]]) #+begin_src yaml miniflux: container_name: miniflux image: miniflux/miniflux restart: unless-stopped networks: - t2_proxy - backend depends_on: - miniflux_db environment: - DATABASE_URL=postgres://miniflux:SCJWWXqHwehP7f8g@miniflux_db/miniflux?sslmode=disable - RUN_MIGRATIONS=1 - CREATE_ADMIN=1 - ADMIN_USERNAME=$MINIFLUX_ADMIN_NAME - ADMIN_PASSWORD=$MINIFLUX_ADMIN_PASS labels: - "traefik.enable=true" - "traefik.http.routers.miniflux-rtr.entrypoints=web-secure" - "traefik.http.routers.miniflux-rtr.rule=Host(`rss.$DOMAINNAME`)" - "traefik.http.routers.miniflux-rtr.tls=true" - "traefik.http.routers.miniflux-rtr.service=miniflux-svc" - "traefik.http.services.miniflux-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src #+begin_src yaml miniflux_db: container_name: miniflux_db image: postgres:12 shm_size: 512mb restart: unless-stopped networks: - backend user: "${PUID}:${PGID}" environment: - POSTGRES_USER=miniflux - POSTGRES_PASSWORD=$MINIFLUX_POSTGRES_PASSWORD volumes: - $CONFIGDIR/miniflux_db:/var/lib/postgresql/data logging: *default-logging #+end_src ** Home *** =mosquitto= - MQTT broker ([[https://github.com/eclipse/mosquitto/][link]]) #+begin_src yaml mosquitto: container_name: mosquitto image: eclipse-mosquitto restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ expose: - 1883 - 9001 ports: - 1883:1883 - 9001:9001 volumes: - $CONFIGDIR/mosquitto/config:/mosquitto/config - $CONFIGDIR/mosquitto/log:/mosquitto/log - $CONFIGDIR/mosquitto/data:/mosquitto/data logging: *default-logging #+end_src *** =zigbee2mqtt= - Zigbee to MQTT bridge ([[https://github.com/Koenkk/zigbee2mqtt/][link]]) #+begin_src yaml zigbee2mqtt: container_name: zigbee2mqtt image: koenkk/zigbee2mqtt restart: unless-stopped privileged: true depends_on: - mosquitto networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/zigbee2mqtt:/app/data - /run/udev:/run/udev:ro - /dev/ttyUSB-zigbee:/dev/ttyUSB0:ro labels: - "traefik.enable=true" - "traefik.http.routers.zigbee2mqtt-rtr.entrypoints=web-secure" - "traefik.http.routers.zigbee2mqtt-rtr.rule=Host(`zigbee2mqtt.$DOMAINNAME`)" - "traefik.http.routers.zigbee2mqtt-rtr.tls=true" - "traefik.http.routers.zigbee2mqtt-rtr.service=zigbee2mqtt-svc" - "traefik.http.routers.zigbee2mqtt-rtr.middlewares=authelia@docker" - "traefik.http.services.zigbee2mqtt-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src *** =node-red= - Automation tool ([[https://github.com/node-red/node-red][link]]) #+begin_src yaml node-red: container_name: node-red image: nodered/node-red restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/node-red:/data ports: - 1880:1880 labels: - "traefik.enable=true" - "traefik.http.routers.node-red-rtr.entrypoints=web-secure" - "traefik.http.routers.node-red-rtr.rule=Host(`node-red.$DOMAINNAME`)" - "traefik.http.routers.node-red-rtr.tls=true" - "traefik.http.routers.node-red-rtr.service=node-red-svc" - "traefik.http.routers.node-red-rtr.middlewares=authelia@docker" - "traefik.http.services.node-red-svc.loadbalancer.server.port=1880" logging: *default-logging #+end_src *** =esphome= - System to control ESP8266/ESP32 devices ([[https://github.com/esphome/esphome][link]]) #+begin_src yaml esphome: container_name: esphome image: esphome/esphome restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - ESPHOME_DASHBOARD_USE_PING=true volumes: - $CONFIGDIR/esphome:/config - /docker/.esphome:/config/.esphome labels: - "traefik.enable=true" - "traefik.http.routers.esphome-rtr.entrypoints=web-secure" - "traefik.http.routers.esphome-rtr.rule=Host(`esphome.$DOMAINNAME`)" - "traefik.http.routers.esphome-rtr.tls=true" - "traefik.http.routers.esphome-rtr.service=esphome-svc" - "traefik.http.routers.esphome-rtr.middlewares=authelia@docker" - "traefik.http.services.esphome-svc.loadbalancer.server.port=6052" logging: *default-logging #+end_src *** =mqttui= - MQTT Web Interface ([[https://github.com/terdia/mqttui][link]]) #+begin_src yaml mqttui: container_name: mqttui image: terdia07/mqttui restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - MQTT_BROKER=192.168.1.21 - MQTT_PORT=1883 labels: - "traefik.enable=true" - "traefik.http.routers.mqttui-rtr.entrypoints=web-secure" - "traefik.http.routers.mqttui-rtr.rule=Host(`mqttui.$DOMAINNAME`)" - "traefik.http.routers.mqttui-rtr.tls=true" - "traefik.http.routers.mqttui-rtr.service=mqttui-svc" - "traefik.http.routers.mqttui-rtr.middlewares=authelia@docker" - "traefik.http.services.mqttui-svc.loadbalancer.server.port=5000" logging: *default-logging #+end_src *** =influxdb= - Scalable datastore for metrics, events, and real-time analytics ([[https://github.com/influxdata/influxdb][link]]) #+begin_src yaml influxdb: container_name: influxdb image: influxdb restart: unless-stopped networks: - t2_proxy - backend environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - /docker/influxdb:/var/lib/influxdb2:rw labels: - "traefik.enable=true" - "traefik.http.routers.influxdb-rtr.entrypoints=web-secure" - "traefik.http.routers.influxdb-rtr.rule=Host(`influxdb.$DOMAINNAME`)" - "traefik.http.routers.influxdb-rtr.tls=true" - "traefik.http.routers.influxdb-rtr.service=influxdb-svc" - "traefik.http.services.influxdb-svc.loadbalancer.server.port=8086" healthcheck: test: "curl -f http://localhost:8086/ping" interval: 5s timeout: 10s retries: 5 logging: *default-logging #+end_src ** Immich *** =immich-server= #+begin_src yaml immich-server: container_name: immich-server image: ghcr.io/immich-app/immich-server:release restart: unless-stopped networks: - t2_proxy - immich volumes: - /srv/storage/immich:/usr/src/app/upload - /etc/localtime:/etc/localtime:ro env_file: - immich.env depends_on: - immich-redis - immich-database user: "${PUID}:${PGID}" labels: - "traefik.enable=true" - "traefik.http.routers.immich-rtr.entrypoints=web-secure" - "traefik.http.routers.immich-rtr.rule=Host(`immich.$DOMAINNAME`)" - "traefik.http.routers.immich-rtr.tls=true" - "traefik.http.routers.immich-rtr.service=immich-svc" - "traefik.http.services.immich-svc.loadbalancer.server.port=2283" logging: *default-logging #+end_src *** =immich-machine-learning= #+begin_src yaml immich-machine-learning: container_name: immich-machine-learning image: ghcr.io/immich-app/immich-machine-learning:release restart: unless-stopped networks: - immich volumes: - /srv/storage/immich:/usr/src/app/upload - /docker/immich-machine-learning-cache:/cache env_file: - immich.env user: "${PUID}:${PGID}" logging: *default-logging #+end_src *** =immich-redis= #+begin_src yaml immich-redis: container_name: immich-redis image: redis:6.2-alpine@sha256:70a7a5b641117670beae0d80658430853896b5ef269ccf00d1827427e3263fa3 restart: unless-stopped networks: - immich logging: *default-logging #+end_src *** =immich-database= #+begin_src yaml immich-database: container_name: immich-database image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0 restart: unless-stopped networks: - immich env_file: - immich.env environment: - POSTGRES_PASSWORD=$${DB_PASSWORD} - POSTGRES_USER=$${DB_USERNAME} - POSTGRES_DB=$${DB_DATABASE_NAME} - PG_DATA=/var/lib/postgresql/data # Uncomment the DB_STORAGE_TYPE: 'HDD' var if your database isn't stored on SSDs # - DB_STORAGE_TYPE: 'HDD' volumes: - $CONFIGDIR/immich/postgresql-data:/var/lib/postgresql/data logging: *default-logging #+end_src *** =immich.env= :PROPERTIES: :header-args: :tangle /ssh:thomas@homelab:~/docker/immich.env :header-args+: :comments none :mkdirp yes :noweb yes :END: #+begin_src conf ################################################################################### # Database ################################################################################### DB_HOSTNAME=immich-database DB_USERNAME=postgres DB_PASSWORD=aC2fdTEHiRcrb0U5 DB_DATABASE_NAME=immich # Optional Database settings: # DB_PORT=5432 ################################################################################### # Redis ################################################################################### REDIS_HOSTNAME=immich-redis ################################################################################### # Log message level - [simple|verbose] ################################################################################### LOG_LEVEL=log #################################################################################### # Alternative Service Addresses - Optional # # This is an advanced feature for users who may be running their immich services on different hosts. # It will not change which address or port that services bind to within their containers, but it will change where other services look for their peers. # Note: immich-microservices is bound to 3002, but no references are made #################################################################################### IMMICH_WEB_URL=http://immich-server:3000 IMMICH_SERVER_URL=http://immich-server:3001 IMMICH_MACHINE_LEARNING_URL=http://immich-machine-learning:3003 #################################################################################### # Alternative API's External Address - Optional # # This is an advanced feature used to control the public server endpoint returned to clients during Well-known discovery. # You should only use this if you want mobile apps to access the immich API over a custom URL. Do not include trailing slash. # NOTE: At this time, the web app will not be affected by this setting and will continue to use the relative path: /api # Examples: http://localhost:3001, http://immich-api.example.com, etc #################################################################################### #IMMICH_API_URL_EXTERNAL=http://localhost:3001 #+end_src ** Download :noexport: *** =prowlarr= - API support for torrents ([[https://github.com/Prowlarr/Prowlarr][link]]) #+begin_src yaml prowlarr: container_name: prowlarr image: ghcr.io/almottier/prowlarr-ygg restart: unless-stopped networks: - t2_proxy - backend environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - AUTO_UPDATE=true volumes: - $CONFIGDIR/prowlarr:/config labels: - "traefik.enable=true" - "traefik.http.routers.prowlarr-rtr.entrypoints=web-secure" - "traefik.http.routers.prowlarr-rtr.rule=Host(`prowlarr.$DOMAINNAME`)" - "traefik.http.routers.prowlarr-rtr.tls=true" - "traefik.http.routers.prowlarr-rtr.middlewares=authelia@docker" - "traefik.http.routers.prowlarr-rtr.service=prowlarr-svc" - "traefik.http.services.prowlarr-svc.loadbalancer.server.port=9696" #+end_src *** =jellyseerr= - Managing requests for the media library ([[https://github.com/Fallenbagel/jellyseerr][link]]) #+begin_src yaml jellyseerr: container_name: jellyseerr image: ghcr.io/seerr-team/seerr:latest restart: unless-stopped init: true networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/jellyseerr:/app/config labels: - "traefik.enable=true" - "traefik.http.routers.jellyseerr-rtr.entrypoints=web-secure" - "traefik.http.routers.jellyseerr-rtr.rule=Host(`jellyseerr.$DOMAINNAME`)" - "traefik.http.routers.jellyseerr-rtr.tls=true" # - "traefik.http.routers.jellyseerr-rtr.middlewares=authelia@docker" - "traefik.http.routers.jellyseerr-rtr.service=jellyseerr-svc" - "traefik.http.services.jellyseerr-svc.loadbalancer.server.port=5055" #+end_src *** =qobuz= - Qobuz Downloader ([[https://github.com/tdehaeze/qobuz-docker][link]]) #+begin_src yaml qobuz: container_name: qobuz image: tdehaeze/docker-qobuz restart: unless-stopped networks: - t2_proxy volumes: - /srv/storage/Music:/downloads environment: - TZ=$TZ - QOBUZNAME=$QOBUZNAME - QOBUZPASS=$QOBUZPASS - DOWNLOADDIR=/downloads - JELLYFINURL=https://jellyfin.tdehaeze.xyz/library/refresh - JELLYFINTOKEN=$JELLYFINTOKEN - NOTIF_TYPE=gotify - GOTIFY_URL=$GOTIFY_URL - GOTIFY_TOKEN=$QOBUZ_GOTIFY_TOKEN user: "${PUID}:${PGID}" labels: - "traefik.enable=true" - "traefik.http.routers.qobuz-rtr.entrypoints=web-secure" - "traefik.http.routers.qobuz-rtr.rule=Host(`qobuz.$DOMAINNAME`)" - "traefik.http.routers.qobuz-rtr.tls=true" - "traefik.http.routers.qobuz-rtr.service=qobuz-svc" - "traefik.http.routers.qobuz-rtr.middlewares=authelia@docker" - "traefik.http.services.qobuz-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src *** =sonarr= - Automatically download TVshows ([[https://github.com/Sonarr/Sonarr][link]]) #+begin_src yaml sonarr: container_name: sonarr image: lscr.io/linuxserver/sonarr restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - UMASK_SET=022 volumes: - $CONFIGDIR/sonarr:/config - /srv/storage/TVShows:/data/TVShows - /srv/storage/Animes:/data/Animes - /srv/storage/Downloads:/data/Downloads labels: - "traefik.enable=true" - "traefik.http.routers.sonarr-rtr.entrypoints=web-secure" - "traefik.http.routers.sonarr-rtr.rule=Host(`sonarr.$DOMAINNAME`)" - "traefik.http.routers.sonarr-rtr.tls=true" - "traefik.http.routers.sonarr-rtr.middlewares=authelia@docker" - "traefik.http.routers.sonarr-rtr.service=sonarr-svc" - "traefik.http.services.sonarr-svc.loadbalancer.server.port=8989" #+end_src *** =radarr= - Automatically download Movies ([[https://github.com/Radarr/Radarr][link]]) #+begin_src yaml radarr: container_name: radarr image: lscr.io/linuxserver/radarr restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - UMASK_SET=022 volumes: - $CONFIGDIR/radarr:/config - /srv/storage/Movies:/data/Movies - /srv/storage/Downloads:/data/Downloads labels: - "traefik.enable=true" - "traefik.http.routers.radarr-rtr.entrypoints=web-secure" - "traefik.http.routers.radarr-rtr.rule=Host(`radarr.$DOMAINNAME`)" - "traefik.http.routers.radarr-rtr.tls=true" - "traefik.http.routers.radarr-rtr.middlewares=authelia@docker" - "traefik.http.routers.radarr-rtr.service=radarr-svc" - "traefik.http.services.radarr-svc.loadbalancer.server.port=7878" #+end_src *** =transmission= - Torrent Client #+begin_src yaml transmission: container_name: transmission image: lscr.io/linuxserver/transmission restart: unless-stopped network_mode: "service:gluetun" volumes: - /etc/localtime:/etc/localtime:ro - $CONFIGDIR/transmission:/config - /srv/storage/Downloads:/data/Downloads environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - USER=$TRANSMISSION_NAME - PASS=$TRANSMISSION_PASS logging: *default-logging #+end_src *** =gluetun= - Provide VPN connection to other containers ([[https://github.com/bubuntux/nordvpn][link]]) #+begin_src yaml gluetun: container_name: gluetun image: qmcgaw/gluetun restart: unless-stopped cap_add: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun # network_mode: bridge networks: - t2_proxy ports: - 9091:9091/tcp # For transmission - 27133:27133/tcp # For transmission - 27133:27133/udp # For transmission # - 8065:8065 # For transmission environment: - VPN_SERVICE_PROVIDER=airvpn - VPN_TYPE=wireguard - WIREGUARD_PRIVATE_KEY=MAmROmJK6GeU7SwmIeVqzOMzo5pp28NEzGZsleucGWM= - WIREGUARD_PRESHARED_KEY=6UzMUwNNQWC3x7YKmjdg3n1KudwnFfqgROYMYFfXkYc= - WIREGUARD_ADDRESSES=10.188.186.114 - SERVER_COUNTRIES=Switzerland - FIREWALL_VPN_INPUT_PORTS=27133 - HEALTH_VPN_DURATION_INITIAL=120s - DNS_KEEP_NAMESERVER=off - TZ=$TZ volumes: - $CONFIGDIR/gluetun:/config labels: - "traefik.enable=true" - "traefik.docker.network=t2_proxy" - "traefik.http.routers.transmission-rtr.entrypoints=web-secure" - "traefik.http.routers.transmission-rtr.rule=Host(`torrent.$DOMAINNAME`)" - "traefik.http.routers.transmission-rtr.tls=true" - "traefik.http.routers.transmission-rtr.service=gluetun-svc" - "traefik.http.routers.transmission-rtr.middlewares=basic-auth@file" - "traefik.http.services.gluetun-svc.loadbalancer.server.port=9091" - "traefik.http.services.gluetun-svc.loadbalancer.server.scheme=http" logging: *default-logging #+end_src ** Affichtoo *** =affichtoo-owasabi= - Affichtoo #+begin_src yaml affichtoo-owasabi: container_name: affichtoo-owasabi image: tdehaeze/affichtoo restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/affichtoo/owasabi:/app/static/conf labels: - "traefik.enable=true" - "traefik.http.routers.owasabi-rtr.entrypoints=web-secure" - "traefik.http.routers.owasabi-rtr.rule=Host(`owasabi.$DOMAINNAME`)" - "traefik.http.routers.owasabi-rtr.tls=true" - "traefik.http.routers.owasabi-rtr.service=owasabi-svc" - "traefik.http.routers.owasabi-rtr.middlewares=authelia@docker" - "traefik.http.services.owasabi-svc.loadbalancer.server.port=8000" logging: *default-logging #+end_src *** =affichtoo-owasabi-mountains= - Affichtoo #+begin_src yaml affichtoo-owasabi-mountins: container_name: affichtoo-owasabi-mountins image: tdehaeze/affichtoo restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/affichtoo/owasabi-mountains:/app/static/conf labels: - "traefik.enable=true" - "traefik.http.routers.owasabi-mountains-rtr.entrypoints=web-secure" - "traefik.http.routers.owasabi-mountains-rtr.rule=Host(`owasabi-mountains.$DOMAINNAME`)" - "traefik.http.routers.owasabi-mountains-rtr.tls=true" - "traefik.http.routers.owasabi-mountains-rtr.service=owasabi-mountains-svc" - "traefik.http.routers.owasabi-mountains-rtr.middlewares=authelia@docker" - "traefik.http.services.owasabi-mountains-svc.loadbalancer.server.port=8000" logging: *default-logging #+end_src * Docker-Compose OLD :noexport: ** =huntarr= - Find Missing & Upgrade Media Items ([[https://github.com/plexguide/Huntarr.io][link]]) #+begin_src yaml huntarr: container_name: huntarr image: huntarr/huntarr:latest restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/huntarr:/config labels: - "traefik.enable=true" - "traefik.http.routers.huntarr-rtr.entrypoints=web-secure" - "traefik.http.routers.huntarr-rtr.rule=Host(`huntarr.$DOMAINNAME`)" - "traefik.http.routers.huntarr-rtr.tls=true" - "traefik.http.routers.huntarr-rtr.service=huntarr-svc" - "traefik.http.services.huntarr-svc.loadbalancer.server.port=9705" #+end_src ** =ygege= ([[https://github.com/UwUDev/ygege][link]]) #+begin_src yaml ygege: container_name: ygege image: uwucode/ygege restart: unless-stopped networks: - t2_proxy - backend environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/ygege/sessions:/app/sessions - $CONFIGDIR/ygege/config.json:/app/config.json labels: - "traefik.enable=false" # ports: # - 8715:8715 #+end_src ** =joal= - Seeding Torrents ([[https://github.com/anthonyraymond/joal][link]]) #+begin_src yaml joal: container_name: joal image: anthonyraymond/joal restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/joal:/data command: ["--joal-conf=/data", "--spring.main.web-environment=true", "--server.port=443", "--joal.ui.path.prefix=joal", "--joal.ui.secret-token=test"] labels: - "traefik.enable=true" - "traefik.http.routers.joal-rtr.entrypoints=web-secure" - "traefik.http.routers.joal-rtr.rule=Host(`joal.$DOMAINNAME`)" - "traefik.http.routers.joal-rtr.tls=true" - "traefik.http.routers.joal-rtr.service=joal-svc" - "traefik.http.routers.joal-rtr.middlewares=authelia@docker" - "traefik.http.services.joal-svc.loadbalancer.server.port=443" logging: *default-logging #+end_src ** =flaresolverr= - Proxy server to bypass Cloudflare protection ([[https://github.com/FlareSolverr/FlareSolverr][link]]) #+begin_src yaml flaresolverr: container_name: flaresolverr # image: ghcr.io/flaresolverr/flaresolverr:latest # image: 21hsmw/flaresolverr:nodriver image: alexfozor/flaresolverr:pr-1300-experimental restart: unless-stopped networks: - t2_proxy environment: - LOG_LEVEL=info - LOG_HTML=false # - CAPTCHA_SOLVER=none - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.flaresolverr-rtr.entrypoints=web-secure" - "traefik.http.routers.flaresolverr-rtr.rule=Host(`flaresolverr.$DOMAINNAME`)" - "traefik.http.routers.flaresolverr-rtr.tls=true" # - "traefik.http.routers.flaresolverr-rtr.middlewares=authelia@docker" - "traefik.http.routers.flaresolverr-rtr.service=flaresolverr-svc" - "traefik.http.services.flaresolverr-svc.loadbalancer.server.port=8191" #+end_src ** =filebrowser= - Web file browser ([[https://hub.docker.com/r/filebrowser/filebrowser][link]]) #+begin_src yaml filebrowser: container_name: filebrowser image: filebrowser/filebrowser restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/filebrowser/filebrowser.db:/database/filebrowser.db - $CONFIGDIR/filebrowser/settings.json:/config/settings.json - /srv/storage:/srv/storage user: "${PUID}:${PGID}" healthcheck: disable: true # https://github.com/filebrowser/filebrowser/issues/3092 environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.cloud-rtr.entrypoints=web-secure" - "traefik.http.routers.cloud-rtr.rule=Host(`cloud.$DOMAINNAME`)" - "traefik.http.routers.cloud-rtr.tls=true" - "traefik.http.routers.cloud-rtr.service=cloud-svc" - "traefik.http.services.cloud-svc.loadbalancer.server.port=80" logging: *default-logging #+end_src =settings.json= #+begin_src json :tangle /ssh:thomas@homelab:/home/thomas/docker/config/filebrowser/settings.json { "port": 80, "baseURL": "", "address": "", "log": "stdout", "database": "/database/filebrowser.db", "root": "/srv/storage" } #+end_src ** =homer= - Home page for myself ([[https://github.com/bastienwirtz/homer][link]]) #+begin_src yaml :tangle no homer: container_name: homer image: b4bz/homer restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/homer/assets/:/www/assets labels: - "traefik.enable=true" - "traefik.http.routers.homer-rtr.entrypoints=web-secure" - "traefik.http.routers.homer-rtr.rule=Host(`homer.$DOMAINNAME`)" - "traefik.http.routers.homer-rtr.tls=true" - "traefik.http.routers.homer-rtr.service=homer-svc" - "traefik.http.services.homer-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src =config.yml= #+begin_src yaml :tangle /ssh:thomas@homelab:/home/thomas/docker/config/homer/assets/config.yml --- title: "Homepage" subtitle: "" logo: "assets/homer.png" header: false footer: false columns: "auto" connectivityCheck: false theme: default links: [] services: - name: "Websites" icon: "fas fa-desktop" items: - name: "Brain" logo: "/assets/tools/brain.png" subtitle: "Digital Brain" url: "https://brain.tdehaeze.xyz" - name: "Research" logo: "/assets/tools/orgmode.png" subtitle: "Research Pages" url: "https://research.tdehaeze.xyz" - name: "Help" logo: "/assets/tools/help.png" subtitle: "Help Page" url: "https://help.tdehaeze.xyz" - name: "Dotfiles" logo: "/assets/tools/dotfiles.png" subtitle: "My Literate Dotfiles" url: "https://dotfiles.tdehaeze.xyz" - name: "Miam" logo: "/assets/tools/miam.png" subtitle: "Personnal Recipes" url: "https://miam.tdehaeze.xyz" - name: "Miniflux" logo: "/assets/tools/miniflux.png" subtitle: "RSS Feeds" url: "https://rss.tdehaeze.xyz" - name: "LinkDing" logo: "/assets/tools/linkding.png" subtitle: "Bookmark Manager" url: "https://bm.tdehaeze.xyz" - name: "Multimedia" icon: "fas fa-photo-video" items: - name: "Jellyfin" logo: "/assets/tools/jellyfin.png" subtitle: "Media Library" url: "https://jellyfin.tdehaeze.xyz" - name: "JFA-Go" logo: "/assets/tools/jellyfin.png" subtitle: "Manage Jellyfin Users" url: "http://jfa.tdehaeze.xyz/" # - name: "Audioserve" # logo: "/assets/tools/audiobook.png" # subtitle: "Audiobook Server" # url: "https://audiobook.tdehaeze.xyz" # - name: "Kavita" # logo: "/assets/tools/kavita.png" # subtitle: "Book Library" # url: "https://kavita.tdehaeze.xyz" - name: "Cloud" icon: "fas fa-cloud" items: - name: "Cinny" logo: "/assets/tools/cinny.png" subtitle: "Matrix web client" url: "https://cinny.tdehaeze.xyz" - name: "File Browser" logo: "/assets/tools/cloud.png" subtitle: "Simple Personnal Could" url: "https://cloud.tdehaeze.xyz" - name: "Syncthing" logo: "/assets/tools/syncthing.png" subtitle: "Anne" url: "https://sync-anne.tdehaeze.xyz" - name: "Syncthing" logo: "/assets/tools/syncthing.png" subtitle: "Jean-Marie" url: "https://sync-jm.tdehaeze.xyz" - name: "Syncthing" logo: "/assets/tools/syncthing.png" subtitle: "P2P Sync" url: "https://syncthing.tdehaeze.xyz" - name: "Radicale" logo: "/assets/tools/radicale.png" subtitle: "CalDAV/CardDAV Server" url: "https://radicale.tdehaeze.xyz" - name: "Gitea" logo: "/assets/tools/gitea.png" subtitle: "Git Server" url: "https://git.tdehaeze.xyz" - name: "Download" icon: "fas fa-download" items: - name: "JellySrerr" logo: "/assets/tools/jellyseerr.png" subtitle: "Torrent Client" url: "http://jellyseerr.tdehaeze.xyz/" # - name: "Down" # logo: "/assets/tools/down.png" # subtitle: "Torrent Download" # url: "https://down.tdehaeze.xyz/" - name: "Qobuz" subtitle: "Music Download" logo: "/assets/tools/qobuz.png" url: "https://qobuz.tdehaeze.xyz" - name: "Sonarr" logo: "/assets/tools/sonarr.png" subtitle: "TVShows Download" url: "http://sonarr.tdehaeze.xyz/" - name: "Radarr" logo: "/assets/tools/radarr.png" subtitle: "Movies Download" url: "http://radarr.tdehaeze.xyz/" - name: "Prowlarr" logo: "/assets/tools/prowlarr.png" subtitle: "Torrent Indexer" url: "http://prowlarr.tdehaeze.xyz/" # - name: "Jackett" # logo: "/assets/tools/jackett.png" # subtitle: "Torrent Client" # url: "http://jackett.tdehaeze.xyz/" - name: "Transmission" logo: "/assets/tools/transmission.png" subtitle: "Torrent Client" url: "http://torrent.tdehaeze.xyz/transmission/web/" - name: "Config" icon: "fas fa-cog" items: # - name: "Portainer" # logo: "/assets/tools/portainer.png" # subtitle: "Manger Docker" # url: "https://portainer.tdehaeze.xyz/#/containers" - name: "Traefik" logo: "/assets/tools/traefik.png" subtitle: "Reverse Proxy" url: "https://traefik.tdehaeze.xyz" - name: "Wireguard" logo: "/assets/tools/wireguard.png" subtitle: "Manger Docker" url: "https://wireguard.tdehaeze.xyz/" - name: "Uptime" logo: "/assets/tools/uptime.png" subtitle: "Monitoring" url: "https://uptime.tdehaeze.xyz" - name: "Commento" logo: "/assets/tools/commento.png" subtitle: "Commenting System" url: "https://commento.tdehaeze.xyz" - name: "Gotify" logo: "/assets/tools/gotify.png" subtitle: "Messaging System" url: "https://gotify.tdehaeze.xyz" - name: "Scrutiny" logo: "/assets/tools/scrutiny.png" subtitle: "S.M.A.R.T" url: "http://scrutiny.tdehaeze.xyz/web/dashboard" - name: "Home" icon: "fas fa-home" items: - name: "OpenWRT" logo: "/assets/tools/openwrt.png" subtitle: "Router" url: "https://openwrt.tdehaeze.xyz/" - name: "Unifi" logo: "/assets/tools/unifi.png" subtitle: "Wifi Expander" url: "https://unifi.tdehaeze.xyz/" - name: "Changedetection.io" logo: "/assets/tools/changedetection.png" subtitle: "Detect change in websites" url: "https://change.tdehaeze.xyz" - name: "Zigbee2MQTT" logo: "/assets/tools/zigbee2mqtt.png" subtitle: "Zigbee2MQTT" url: "https://zigbee2mqtt.tdehaeze.xyz/" - name: "Node Red" logo: "/assets/tools/node-red.png" subtitle: "Event-driven applications" url: "https://node-red.tdehaeze.xyz/" - name: "InfluxDB" logo: "/assets/tools/influxdb.png" subtitle: "Time series database" url: "https://influxdb.tdehaeze.xyz/" - name: "ESPHome" logo: "/assets/tools/esphome.png" subtitle: "System to control ESP8266/ESP32" url: "https://esphome.tdehaeze.xyz/" #+end_src ** =metube= - Download Youtube Videos ([[https://github.com/alexta69/metube][link]]) #+begin_src yaml :tangle no metube: container_name: metube restart: unless-stopped image: alexta69/metube networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - STATE_DIR=/statedir user: "1000:1000" volumes: - /srv/storage/Downloads/youtube:/downloads - $CONFIGDIR/metube:/statedir labels: - "traefik.enable=true" - "traefik.http.routers.metube-rtr.entrypoints=web-secure" - "traefik.http.routers.metube-rtr.rule=Host(`metube.$DOMAINNAME`)" - "traefik.http.routers.metube-rtr.tls=true" # - "traefik.http.routers.metube-rtr.middlewares=authelia@docker" - "traefik.http.routers.metube-rtr.service=metube-svc" - "traefik.http.services.metube-svc.loadbalancer.server.port=8081" #+end_src ** Homeassistant :PROPERTIES: :header-args+: :tangle no :END: *** =homeassistant= - Home Automation ([[https://hub.docker.com/r/homeassistant/home-assistant][link]]) #+begin_src yaml homeassistant: container_name: homeassistant image: homeassistant/home-assistant:stable restart: unless-stopped networks: - t2_proxy - backend #ports: # - target: 8123 # published: 8123 # protocol: tcp # mode: host # privileged: true # ports: # - 8123:8123 # network_mode: host volumes: - $CONFIGDIR/homeassistant:/config - /etc/localtime:/etc/localtime:ro - /dev/bus/usb:/dev/bus/usb environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.homeassistant-rtr.entrypoints=web-secure" - "traefik.http.routers.homeassistant-rtr.rule=Host(`home.$DOMAINNAME`)" - "traefik.http.routers.homeassistant-rtr.tls=true" - "traefik.http.routers.homeassistant-rtr.service=homeassistant-svc" - "traefik.http.services.homeassistant-svc.loadbalancer.server.port=8123" # - "traefik.http.services.homeassistant-svc.loadbalancer.servers.url=http://172.17.0.1:8123" logging: *default-logging #+end_src *** =whishper= - Speech Recognition #+begin_src yaml wyoming-whisper: container_name: homeassistant image: rhasspy/wyoming-whisper restart: unless-stopped networks: - t2_proxy - backend volumes: - $CONFIGDIR/whisper:/data ports: - 10300:10300 labels: - "traefik.enable=true" logging: *default-logging command: --model tiny-int8 --language en #+end_src *** =piper= - text to speech #+begin_src yaml wyoming-piper: image: rhasspy/wyoming-piper restart: unless-stopped networks: - t2_proxy - backend volumes: - $CONFIGDIR/piper:/data ports: - 10200:10200 labels: - "traefik.enable=true" logging: *default-logging command: --voice en_US-lessac-medium #+end_src *** =openwakeword= - audio wake word #+begin_src yaml openwakeword: image: rhasspy/wyoming-openwakeword restart: unless-stopped networks: - t2_proxy - backend ports: - 10400:10400 labels: - "traefik.enable=true" command: --preload-model 'ok_nabu' logging: *default-logging #+end_src ** =navidrome= - Music server #+begin_src yaml navidrome: container_name: navidrome image: deluan/navidrome restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/navidrome:/data - /srv/storage/Music:/music:ro environment: - ND_MUSICFOLDER=/music - ND_DATAFOLDER=/data - ND_SCANINTERVAL=10m - ND_LOGLEVEL=info - ND_PORT=4533 - ND_TRANSCODINGCACHESIZE=100MB - ND_SESSIONTIMEOUT=24h - PUID=$PUID - PGID=$PGID - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.navidrome-rtr.entrypoints=web-secure" - "traefik.http.routers.navidrome-rtr.rule=Host(`navidrome.$DOMAINNAME`)" - "traefik.http.routers.navidrome-rtr.tls=true" - "traefik.http.routers.navidrome-rtr.service=navidrome-svc" - "traefik.http.services.navidrome-svc.loadbalancer.server.port=4533" logging: *default-logging #+end_src ** =family= - Home page for family ([[https://github.com/bastienwirtz/homer][link]]) #+begin_src yaml famille: container_name: famille image: b4bz/homer restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/famille/assets/:/www/assets labels: - "traefik.enable=true" - "traefik.http.routers.famille-rtr.entrypoints=web-secure" - "traefik.http.routers.famille-rtr.rule=Host(`famille.$DOMAINNAME`)" - "traefik.http.routers.famille-rtr.tls=true" - "traefik.http.routers.famille-rtr.service=famille-svc" - "traefik.http.services.famille-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src =config.yml= #+begin_src yaml :tangle /ssh:thomas@homelab:/home/thomas/docker/config/famille/assets/config.yml --- title: "Homepage" subtitle: "" logo: "assets/homer.png" header: false footer: false columns: "auto" connectivityCheck: false theme: default message: style: "" # See https://bulma.io/documentation/components/message/#colors for styling options. title: "Coucou !" content: "Ci dessous tu peux trouver différents sites accéssibles sur mon serveur. Si tu as besoin d'aide avec l'utilisation de Jellyfin, tout est expliqué ici." links: [] services: - name: "Websites" icon: "fas fa-desktop" items: - name: "Jellyfin" logo: "/assets/tools/jellyfin.png" subtitle: "Librairie multimédia" url: "https://jellyfin.tdehaeze.xyz" - name: "File Browser" logo: "/assets/tools/cloud.png" subtitle: "Cloud personnel" url: "https://cloud.tdehaeze.xyz" - name: "Miam" logo: "/assets/tools/miam.png" subtitle: "Site de recettes partagées" url: "https://miam.tdehaeze.xyz" - name: "Multimedia" icon: "fas fa-photo-video" items: - name: "Jellyseerr" subtitle: "Ajout de Films/Séries sur Jellyfin" logo: "/assets/tools/jellyseerr.png" url: "https://jellyseerr.tdehaeze.xyz" - name: "Qobuz" subtitle: "Ajout de Musique sur Jellyfin" logo: "/assets/tools/qobuz.png" url: "https://qobuz.tdehaeze.xyz" #+end_src ** =sync-ju= - File Synchronization ([[https://hub.docker.com/r/linuxserver/syncthing][link]]) #+begin_src yaml sync-ju: container_name: sync-ju image: linuxserver/syncthing restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - UMASK_SET=022 volumes: - $CONFIGDIR/sync-ju:/config - /srv/storage/Users/juliette:/Cloud - /srv/storage/Cloud/personnal:/Cloud/Thomas ports: - 22003:22003 - 21030:21030/udp labels: - "traefik.enable=true" - "traefik.http.routers.sync-ju-rtr.entrypoints=web-secure" - "traefik.http.routers.sync-ju-rtr.rule=Host(`sync-ju.$DOMAINNAME`)" - "traefik.http.routers.sync-ju-rtr.tls=true" - "traefik.http.routers.sync-ju-rtr.service=sync-ju-svc" - "traefik.http.routers.sync-ju-rtr.middlewares=authelia@docker" - "traefik.http.services.sync-ju-svc.loadbalancer.server.port=8384" logging: *default-logging #+end_src ** =tina2= - Web interface for 3D printing ([[https://github.com/OctoPrint/OctoPrint][link]]) #+begin_src yaml tina2: image: octoprint/octoprint restart: unless-stopped privileged: true networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/tina2:/octoprint - /run/udev:/run/udev:ro - /dev/ttyUSB-tina2:/dev/ttyUSB0:ro labels: - "traefik.enable=true" - "traefik.http.routers.tina2-rtr.entrypoints=web-secure" - "traefik.http.routers.tina2-rtr.rule=Host(`3d-printer.$DOMAINNAME`)" - "traefik.http.routers.tina2-rtr.tls=true" - "traefik.http.routers.tina2-rtr.service=tina2-svc" - "traefik.http.services.tina2-svc.loadbalancer.server.port=80" logging: *default-logging #+end_src ** =transmission-openvpn= - Torrent server ([[https://hub.docker.com/r/haugene/transmission-openvpn][link]]) #+begin_src yaml :tangle no transmission: image: haugene/transmission-openvpn cap_add: - NET_ADMIN networks: - t2_proxy sysctls: - net.ipv6.conf.all.disable_ipv6=0 restart: unless-stopped ports: - 9091:9091 dns: - 8.8.8.8 - 8.8.4.4 volumes: - /etc/localtime:/etc/localtime:ro - $CONFIGDIR/transmission:/config - /srv/storage/Downloads:/data - /srv/storage/Downloads/watch:/watch environment: - CREATE_TUN_DEVICE=true - PUID=$PUID - PGID=$PGID - TRANSMISSION_WEB_UI=flood-for-transmission - LOCAL_NETWORK=192.168.0.0/16 - OPENVPN_PROVIDER=AIRVPN - OPENVPN_CONFIG=default - HEALTH_CHECK_HOST=github.com - TRANSMISSION_UTP_ENABLED=false - TRANSMISSION_RPC_AUTHENTICATION_REQUIRED=true - TRANSMISSION_RPC_USERNAME=$TRANSMISSION_NAME - TRANSMISSION_RPC_PASSWORD=$TRANSMISSION_PASS labels: - "traefik.enable=true" - "traefik.docker.network=t2_proxy" - "traefik.http.routers.transmission-rtr.entrypoints=web-secure" - "traefik.http.routers.transmission-rtr.rule=Host(`torrent.$DOMAINNAME`)" - "traefik.http.routers.transmission-rtr.tls=true" - "traefik.http.routers.transmission-rtr.service=transmission-svc" - "traefik.http.services.transmission-svc.loadbalancer.server.port=9091" - "traefik.http.services.transmission-svc.loadbalancer.server.scheme=http" logging: *default-logging #+end_src ** =restic-hc4= - Automatic backups on Odroid HC4 ([[https://github.com/djmaze/resticker/][link]]) #+begin_src yaml :tangle no restic-hc4: image: mazzolino/restic restart: "no" networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ - RUN_ON_STARTUP=false - BACKUP_CRON=45 13 * * * # Backup every day - RESTIC_REPOSITORY=sftp://thomas@pierrick.tdehaeze.xyz:10022//srv/storage/backup - RESTIC_PASSWORD=$RESTIC_PASSWORD - RESTIC_BACKUP_SOURCES=/source - RESTIC_BACKUP_ARGS=--host homelab --tag local --group-by host --exclude-file /exclude.txt --verbose - RESTIC_FORGET_ARGS=--group-by tag --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune - RESTIC_GOTIFY_TOKEN=$RESTIC_GOTIFY_TOKEN - SUCCESS_ON_INCOMPLETE_BACKUP=true - POST_COMMANDS_FAILURE=curl "https://gotify.tdehaeze.xyz/message?token=$RESTIC_GOTIFY_TOKEN" -F "title=Restic HC4" -F "message=Backup failed" -F "priority=5" - POST_COMMANDS_EXIT=ssh -p 10022 thomas@pierrick.tdehaeze.xyz "sudo systemctl poweroff" volumes: - $CONFIGDIR/restic-hc4/exclude.txt:/exclude.txt:ro - /srv/storage/Users:/source/Users:ro # User Clouds - /srv/storage/Cloud:/source/Cloud:ro # My Own Cloud - /srv/storage/Music:/source/Music:ro # Musics - /home/thomas:/source/home:ro # Homelab - Home directory - /home/thomas/.ssh/known_hosts:/root/.ssh/known_hosts:ro # Used to SSH to backup machine - /home/thomas/.ssh/id_rsa:/root/.ssh/id_rsa:ro # Used to SSH to backup machine logging: *default-logging #+end_src =exclude.txt= - Exclude files #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/restic-hc4/exclude.txt *.db *.log *.log.* #+end_src The backup server should power at 1:30pm, and at 1:35 it should update the dynamic DNS server. The Docker container (if stopped) will automatically starts at 1:40 using a Cronjob: #+begin_src conf :tangle no 40 13 * * * cd /home/thomas/docker && docker-compose start restic-hc4 #+end_src Then the backup should start at 1:45PM ** =pdf= - Stirling #+begin_src yaml stirling-pdf: image: frooodle/s-pdf restart: unless-stopped networks: - t2_proxy environment: - DOCKER_ENABLE_SECURITY=false - INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/pdf:/configs labels: - "traefik.enable=true" - "traefik.http.routers.pdf-rtr.entrypoints=web-secure" - "traefik.http.routers.pdf-rtr.rule=Host(`pdf.$DOMAINNAME`)" - "traefik.http.routers.pdf-rtr.tls=true" - "traefik.http.routers.pdf-rtr.service=pdf-svc" - "traefik.http.services.pdf-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src ** TODO =blocky= - DNS proxy ad-blocker #+begin_src yaml :tangle no blocky: container_name: blocky image: spx01/blocky networks: - t2_proxy restart: unless-stopped environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - /etc/localtime:/etc/localtime:ro - $CONFIGDIR/blocky/config.yml:/app/config.yml ports: - 53:53/tcp - 53:53/udp - 4000:4000/tcp labels: - "traefik.enable=false" # - "traefik.http.routers.unifi-rtr.entrypoints=web-secure" # - "traefik.http.routers.unifi-rtr.rule=Host(`unifi.$DOMAINNAME`)" # - "traefik.http.routers.unifi-rtr.tls=true" # - "traefik.http.routers.unifi-rtr.service=unifi-svc" # - "traefik.http.routers.unifi-rtr.middlewares=unifiHeaders@file" # - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https" # # - "traefik.http.routers.unifi-rtr.middlewares=authelia@docker" # - "traefik.http.services.unifi-svc.loadbalancer.server.port=8443" # - "traefik.http.services.unifi-svc.loadbalancer.server.scheme=https" logging: *default-logging #+end_src ** =metube= - Download Youtube Videos ([[https://github.com/alexta69/metube][link]]) #+begin_src yaml metube: container_name: metube image: alexta69/metube restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - STATE_DIR=/statedir user: "1000:1000" volumes: - /srv/storage/Downloads/youtube:/downloads - $CONFIGDIR/metube:/statedir labels: - "traefik.enable=true" - "traefik.http.routers.metube-rtr.entrypoints=web-secure" - "traefik.http.routers.metube-rtr.rule=Host(`metube.$DOMAINNAME`)" - "traefik.http.routers.metube-rtr.tls=true" # - "traefik.http.routers.metube-rtr.middlewares=authelia@docker" - "traefik.http.routers.metube-rtr.service=metube-svc" - "traefik.http.services.metube-svc.loadbalancer.server.port=8081" #+end_src ** Affichtoo *** =japonais= - Affichtoo #+begin_src yaml affichtoo-japonais: container_name: affichtoo-japonais image: tdehaeze/affichtoo restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/affichtoo/japonais:/app/static/conf labels: - "traefik.enable=true" - "traefik.http.routers.japonais-rtr.entrypoints=web-secure" - "traefik.http.routers.japonais-rtr.rule=Host(`japonais.$DOMAINNAME`)" - "traefik.http.routers.japonais-rtr.tls=true" - "traefik.http.routers.japonais-rtr.service=japonais-svc" - "traefik.http.services.japonais-svc.loadbalancer.server.port=8000" # - "traefik.http.routers.japonais-rtr.middlewares=japonais-auth" logging: *default-logging #+end_src *** =creperie= - Affichtoo #+begin_src yaml affichtoo-creperie: container_name: affichtoo-creperie image: tdehaeze/affichtoo restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/affichtoo/creperie:/app/static/conf labels: - "traefik.enable=true" - "traefik.http.routers.creperie-rtr.entrypoints=web-secure" - "traefik.http.routers.creperie-rtr.rule=Host(`creperie.$DOMAINNAME`)" - "traefik.http.routers.creperie-rtr.tls=true" - "traefik.http.routers.creperie-rtr.service=creperie-svc" - "traefik.http.services.creperie-svc.loadbalancer.server.port=8000" # - "traefik.http.routers.creperie-rtr.middlewares=creperie-auth" logging: *default-logging #+end_src *** =burger= - Affichtoo #+begin_src yaml affichtoo-burger: container_name: affichtoo-burger image: tdehaeze/affichtoo restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/affichtoo/burger:/app/static/conf labels: - "traefik.enable=true" - "traefik.http.routers.burger-rtr.entrypoints=web-secure" - "traefik.http.routers.burger-rtr.rule=Host(`burger.$DOMAINNAME`)" - "traefik.http.routers.burger-rtr.tls=true" - "traefik.http.routers.burger-rtr.service=burger-svc" - "traefik.http.services.burger-svc.loadbalancer.server.port=8000" # - "traefik.http.routers.burger-rtr.middlewares=burger-auth" logging: *default-logging #+end_src *** =indien= - Affichtoo #+begin_src yaml affichtoo-indien: container_name: affichtoo-indien image: tdehaeze/affichtoo restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/affichtoo/indien:/app/static/conf labels: - "traefik.enable=true" - "traefik.http.routers.indien-rtr.entrypoints=web-secure" - "traefik.http.routers.indien-rtr.rule=Host(`indien.$DOMAINNAME`)" - "traefik.http.routers.indien-rtr.tls=true" - "traefik.http.routers.indien-rtr.service=indien-svc" - "traefik.http.services.indien-svc.loadbalancer.server.port=8000" # - "traefik.http.routers.indien-rtr.middlewares=indien-auth" logging: *default-logging #+end_src *** =italien= - Affichtoo #+begin_src yaml affichtoo-italien: container_name: affichtoo-italien image: tdehaeze/affichtoo restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/affichtoo/italien:/app/static/conf labels: - "traefik.enable=true" - "traefik.http.routers.italien-rtr.entrypoints=web-secure" - "traefik.http.routers.italien-rtr.rule=Host(`italien.$DOMAINNAME`)" - "traefik.http.routers.italien-rtr.tls=true" - "traefik.http.routers.italien-rtr.service=italien-svc" - "traefik.http.services.italien-svc.loadbalancer.server.port=8000" # - "traefik.http.routers.italien-rtr.middlewares=italien-auth" logging: *default-logging #+end_src *** =libanais= - Affichtoo #+begin_src yaml affichtoo-libanais: container_name: affichtoo-libanais image: tdehaeze/affichtoo restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/affichtoo/libanais:/app/static/conf labels: - "traefik.enable=true" - "traefik.http.routers.libanais-rtr.entrypoints=web-secure" - "traefik.http.routers.libanais-rtr.rule=Host(`libanais.$DOMAINNAME`)" - "traefik.http.routers.libanais-rtr.tls=true" - "traefik.http.routers.libanais-rtr.service=libanais-svc" - "traefik.http.services.libanais-svc.loadbalancer.server.port=8000" # - "traefik.http.routers.libanais-rtr.middlewares=libanais-auth" logging: *default-logging #+end_src ** =wishlist= #+begin_src yaml wishlist: container_name: wishlist image: wingysam/christmas-community restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ - SITE_TITLE=Ma Liste d'Envies - SHORT_TITLE=Wishlist - BULMASWATCH=Minty - PFP=false - LANGUAGE=fr-FR - SINGLE_LIST=false - LISTS_PUBLIC=true - SMILE=false - TABLE=true volumes: - $CONFIGDIR/wishlist:/data labels: - "traefik.enable=true" - "traefik.http.routers.wishlist-rtr.entrypoints=web-secure" - "traefik.http.routers.wishlist-rtr.rule=Host(`wishlist.$DOMAINNAME`)" - "traefik.http.routers.wishlist-rtr.tls=true" - "traefik.http.routers.wishlist-rtr.service=wishlist-svc" - "traefik.http.services.wishlist-svc.loadbalancer.server.port=80" logging: *default-logging #+end_src ** =ihatemoney= - Tricount Alternative ([[https://github.com/spiral-project/ihatemoney][link]]) #+begin_src yaml ihatemoney: image: ihatemoney/ihatemoney:6.1.0 container_name: ihatemoney restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - PORT=8000 - ACTIVATE_DEMO_PROJECT=False volumes: - $CONFIGDIR/ihatemoney:/database labels: - "traefik.enable=true" - "traefik.http.routers.ihatemoney-rtr.entrypoints=web-secure" - "traefik.http.routers.ihatemoney-rtr.rule=Host(`ihatemoney.$DOMAINNAME`)" - "traefik.http.routers.ihatemoney-rtr.tls=true" - "traefik.http.routers.ihatemoney-rtr.service=ihatemoney-svc" - "traefik.http.services.ihatemoney-svc.loadbalancer.server.port=8000" logging: *default-logging #+end_src ** =adguardhome= - Network-wide ads & trackers blocking DNS server ([[https://github.com/AdguardTeam/AdGuardHome][link]]) #+begin_src yaml :tangle no adguardhome: container_name: adguardhome image: adguard/adguardhome restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/adguardhome/work:/opt/adguardhome/work - $CONFIGDIR/adguardhome/conf:/opt/adguardhome/conf ports: - 53:53/tcp - 53:53/udp # - 853:853 labels: - "traefik.enable=true" - "traefik.http.routers.adguardhome-rtr.entrypoints=web-secure" - "traefik.http.routers.adguardhome-rtr.rule=Host(`adguardhome.$DOMAINNAME`)" - "traefik.http.routers.adguardhome-rtr.tls=true" - "traefik.http.routers.adguardhome-rtr.service=adguardhome-svc" - "traefik.http.routers.adguardhome-rtr.middlewares=authelia@docker" - "traefik.http.services.adguardhome-svc.loadbalancer.server.port=3000" logging: *default-logging #+end_src ** =jackett= - API support for torrents ([[https://github.com/Jackett/Jackett][link]]) #+begin_src yaml :tangle no jackett: container_name: jackett image: lscr.io/linuxserver/jackett restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - AUTO_UPDATE=true volumes: - $CONFIGDIR/jackett:/config - /srv/storage/Downloads:/downloads labels: - "traefik.enable=true" - "traefik.http.routers.jackett-rtr.entrypoints=web-secure" - "traefik.http.routers.jackett-rtr.rule=Host(`jackett.$DOMAINNAME`)" - "traefik.http.routers.jackett-rtr.tls=true" - "traefik.http.routers.jackett-rtr.middlewares=authelia@docker" - "traefik.http.routers.jackett-rtr.service=jackett-svc" - "traefik.http.services.jackett-svc.loadbalancer.server.port=9117" #+end_src ** =portainer= - Manage docker ([[https://github.com/portainer/portainer][link]]) #+begin_src yaml :tangle no portainer: container_name: portainer image: portainer/portainer restart: unless-stopped command: -H unix:///var/run/docker.sock networks: - t2_proxy security_opt: - no-new-privileges:true volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - $CONFIGDIR/portainer:/data environment: - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.portainer-rtr.entrypoints=web-secure" - "traefik.http.routers.portainer-rtr.rule=Host(`portainer.$DOMAINNAME`)" - "traefik.http.routers.portainer-rtr.tls=true" - "traefik.http.routers.portainer-rtr.service=portainer-svc" - "traefik.http.routers.portainer-rtr.middlewares=authelia@docker" - "traefik.http.services.portainer-svc.loadbalancer.server.port=9000" logging: *default-logging #+end_src ** =ddns= - Dynamic DNS Server #+begin_src yaml :tangle no ddns: container_name: ddns image: davd/docker-ddns restart: unless-stopped networks: - t2_proxy environment: - RECORD_TTL=60 - ZONE=example.org - SHARED_SECRET=9Kzd9vSyPQuO4CPO # volumes: # - ./bind-data:/var/cache/bind ports: - "53:53" - "53:53/udp" labels: - "traefik.enable=true" - "traefik.http.routers.ddns-rtr.entrypoints=web-secure" - "traefik.http.routers.ddns-rtr.rule=Host(`ddns.$DOMAINNAME`)" - "traefik.http.routers.ddns-rtr.tls=true" - "traefik.http.routers.ddns-rtr.service=ddns-svc" - "traefik.http.services.ddns-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src ** =docker-torrent= - Download Torrents from YGG ([[https://github.com/tdehaeze/qobuz-docker][link]]) #+begin_src yaml down: container_name: down image: tdehaeze/docker-torrent restart: always networks: - t2_proxy volumes: - /srv/storage/Downloads/watch:/watch - /srv/storage/Cloud/org/asked-list.org:/list.org environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - YGGTORRENTNAME=$YGGTORRENTNAME - YGGTORRENTPASS=$YGGTORRENTPASS - NOTIF_TYPE=gotify - GOTIFY_URL=$GOTIFY_URL - GOTIFY_TOKEN=$DOWN_GOTIFY_TOKEN user: "${PUID}:${PGID}" labels: - "traefik.enable=true" - "traefik.http.routers.down-rtr.entrypoints=web-secure" - "traefik.http.routers.down-rtr.rule=Host(`down.$DOMAINNAME`)" - "traefik.http.routers.down-rtr.tls=true" - "traefik.http.routers.down-rtr.service=down-svc" - "traefik.http.services.down-svc.loadbalancer.server.port=3000" logging: *default-logging #+end_src ** =snapraid= - Manage local backup with parity disk ([[https://github.com/amadvance/snapraid][link]]) #+begin_src yaml snapraid: container_name: snapraid image: xagaba/snapraid restart: unless-stopped privileged: true volumes: - /mnt:/mnt - $CONFIGDIR/snapraid:/config - type: "bind" source: /dev/disk target: /dev/disk environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ logging: *default-logging #+end_src =snapraid.conf= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/snapraid/snapraid.conf # Defines the file to use as parity storage # It must NOT be in a data disk # Format: "parity FILE_PATH" parity /mnt/parity/snapraid.parity # Defines the files to use as content list # You can use multiple specification to store more copies # You must have least one copy for each parity file plus one. Some more don't # hurt # They can be in the disks used for data, parity or boot, # but each file must be in a different disk # Format: "content FILE_PATH" # content /var/snapraid.content content /mnt/disk0/.snapraid.content content /mnt/disk1/.snapraid.content content /mnt/disk2/.snapraid.content # Defines the data disks to use # The order is relevant for parity, do not change it # Format: "disk DISK_NAME DISK_MOUNT_POINT" disk disk0 /mnt/disk0 disk disk1 /mnt/disk1 disk disk2 /mnt/disk2 # Excludes hidden files and directories (uncomment to enable). #nohidden # Defines files and directories to exclude # Remember that all the paths are relative at the mount points # Format: "exclude FILE" # Format: "exclude DIR/" # Format: "exclude /PATH/FILE" # Format: "exclude /PATH/DIR/" exclude /tmp/ exclude /lost+found/ exclude /srv/storage/Downloads/incomplete/ # This changes a lot, not necessary to backup exclude *.!sync exclude .DS_Store exclude ._.DS_Store exclude .Thumbs.db exclude .fseventsd exclude .Spotlight-V100 exclude .TemporaryItems exclude .Trashes exclude .part exclude .arc #+end_src =snapraid-runner.conf= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/snapraid/snapraid-runner.conf [snapraid] ; path to the snapraid executable (e.g. /bin/snapraid) executable = /usr/bin/snapraid ; path to the snapraid config to be used config = /config/snapraid.conf ; abort operation if there are more deletes than this, set to -1 to disable deletethreshold = -1 ; if you want touch to be ran each time touch = false [logging] ; logfile to write to, leave empty to disable file = /config/snapraid.log ; maximum logfile size in KiB, leave empty for infinite maxsize = 5000 ; [email] ; ; when to send an email, comma-separated list of [success, error] ; sendon = success,error ; ; set to false to get full programm output via email ; short = true ; subject = [SnapRAID] Status Report: ; from = ; to = ; ; maximum email size in KiB ; maxsize = 500 ; ; [smtp] ; host = ; ; leave empty for default port ; port = ; ; set to "true" to activate ; ssl = false ; tls = false ; user = ; password = [scrub] ; set to true to run scrub after sync enabled = false percentage = 12 older-than = 10 #+end_src ** =transmission= - Torrent client ([[https://hub.docker.com/r/linuxserver/transmission][link]]) #+begin_src yaml transmission: container_name: transmission image: lscr.io/linuxserver/transmission restart: unless-stopped network_mode: container:gluetun environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - USER=$TRANSMISSION_NAME - PASS=$TRANSMISSION_PASS - TRANSMISSION_WEB_HOME=/flood-for-transmission/ volumes: - $CONFIGDIR/transmission:/config - /srv/storage/Downloads:/downloads - /srv/storage/Downloads/watch:/watch logging: *default-logging #+end_src ** =photoprism= ([[https://github.com/photoprism/photoprism][link]]) #+begin_src yaml photoprism: container_name: photoprism image: photoprism/photoprism:latest depends_on: - photoprism_db networks: - t2_proxy - backend security_opt: - seccomp:unconfined - apparmor:unconfined user: "${PUID}:${PGID}" environment: PHOTOPRISM_ADMIN_PASSWORD: "pi3DnacevhCQ" PHOTOPRISM_SITE_URL: "https://photos.tdehaeze.xyz/" PHOTOPRISM_ORIGINALS_LIMIT: 500 PHOTOPRISM_READONLY: "false" PHOTOPRISM_DISABLE_WEBDAV: "true" PHOTOPRISM_DISABLE_TENSORFLOW: "true" PHOTOPRISM_DISABLE_FACES: "true" PHOTOPRISM_DISABLE_CLASSIFICATION: "true" PHOTOPRISM_DARKTABLE_PRESETS: "false" # Enables Darktable presets and disables concurrent RAW conversion PHOTOPRISM_DATABASE_DRIVER: "mysql" PHOTOPRISM_DATABASE_SERVER: "photoprism_db:3306" PHOTOPRISM_DATABASE_NAME: "photoprism" PHOTOPRISM_DATABASE_USER: "photoprism" PHOTOPRISM_DATABASE_PASSWORD: "PMsLF5577UagH08c" PHOTOPRISM_UID: $PUID PHOTOPRISM_GID: $PGID HOME: "/photoprism" working_dir: "/photoprism" volumes: - "/srv/storage/Cloud/pictures:/photoprism/originals" # original media files (photos and videos) - "$CONFIGDIR/photoprism/storage:/photoprism/storage" # *writable* storage folder for cache, database, and sidecar files (never remove) # - "$CONFIGDIR/photoprism/originals:/photoprism/originals" # original media files (photos and videos) # - "/example/family:/photoprism/originals/family" # *additional* media folders can be mounted like this # - "~/Import:/photoprism/import" # *optional* base folder from which files can be imported to originals labels: - "traefik.enable=true" - "traefik.http.routers.photos-rtr.entrypoints=web-secure" - "traefik.http.routers.photos-rtr.rule=Host(`photos.$DOMAINNAME`)" - "traefik.http.routers.photos-rtr.tls=true" - "traefik.http.routers.photos-rtr.service=photos-svc" - "traefik.http.services.photos-svc.loadbalancer.server.port=2342" logging: *default-logging #+end_src #+begin_src yaml :tangle no photoprism_db: container_name: photoprism_db restart: unless-stopped image: mariadb:10.6 networks: - backend security_opt: - seccomp:unconfined - apparmor:unconfined command: mysqld --innodb-buffer-pool-size=128M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120 volumes: - "$CONFIGDIR/photoprism_db/database:/var/lib/mysql" environment: MYSQL_ROOT_PASSWORD: ZyZ4vhBmnERp5Amt MYSQL_DATABASE: photoprism MYSQL_USER: photoprism MYSQL_PASSWORD: PMsLF5577UagH08c #+end_src ** =diun= - Notification for Docker image updates ([[https://github.com/crazy-max/diun/][link]]) #+begin_src yaml diun: container_name: diun image: crazymax/diun restart: unless-stopped networks: - backend environment: - TZ=$TZ - LOG_LEVEL=info - LOG_JSON=false - DIUN_WATCH_WORKERS=20 - DIUN_WATCH_SCHEDULE=0 7 * * 6 - DIUN_PROVIDERS_DOCKER=true - DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT=true - DIUN_NOTIF_GOTIFY_ENDPOINT=$GOTIFY_URL - DIUN_NOTIF_GOTIFY_TOKEN=$DIUN_GOTIFY_TOKEN volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - $CONFIGDIR/diun:/data logging: *default-logging #+end_src ** =audioserve= - Audiobook server ([[https://github.com/izderadicka/audioserve][link]]) #+begin_src yaml audioserve: container_name: audioserve image: izderadicka/audioserve restart: unless-stopped command: /audiobooks networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - AUDIOSERVE_SHARED_SECRET=$AUDIOSERVE_SHARED_SECRET volumes: - /srv/storage/AudioBooks:/audiobooks - /etc/localtime:/etc/localtime:ro - $CONFIGDIR/audioserve:/home/audioserve/.audioserve labels: - "traefik.enable=true" - "traefik.http.routers.audioserve-rtr.entrypoints=web-secure" - "traefik.http.routers.audioserve-rtr.rule=Host(`audiobook.$DOMAINNAME`)" - "traefik.http.routers.audioserve-rtr.tls=true" - "traefik.http.routers.audioserve-rtr.service=audioserve-svc" - "traefik.http.services.audioserve-svc.loadbalancer.server.port=3000" logging: *default-logging #+end_src ** =kavita= - Reading server ([[https://github.com/Kareadita/Kavita][link]]) #+begin_src yaml kavita: container_name: kavita image: kizaing/kavita:latest restart: unless-stopped networks: - t2_proxy environment: - TZ=$TZ - UID=$PUID - GID=$PGID volumes: - $CONFIGDIR/kavita:/kavita/config - /srv/storage/Books:/books - /srv/storage/Scans:/scans - /srv/storage/Comics:/comics labels: - "traefik.enable=true" - "traefik.http.routers.kavita-rtr.entrypoints=web-secure" - "traefik.http.routers.kavita-rtr.rule=Host(`kavita.$DOMAINNAME`)" - "traefik.http.routers.kavita-rtr.tls=true" - "traefik.http.routers.kavita-rtr.service=kavita-svc" - "traefik.http.services.kavita-svc.loadbalancer.server.port=5000" logging: *default-logging #+end_src ** =wikijs= - Wiki App ([[https://github.com/Requarks/wiki][link]]) #+begin_src yaml wikijs: image: ghcr.io/linuxserver/wikijs:version-2.5.201 container_name: wikijs restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/wikijs/config:/config - $CONFIGDIR/wikijs/data:/data labels: - "traefik.enable=true" - "traefik.http.routers.wikijs-rtr.entrypoints=web-secure" - "traefik.http.routers.wikijs-rtr.rule=Host(`wiki.$DOMAINNAME`)" - "traefik.http.routers.wikijs-rtr.tls=true" - "traefik.http.routers.wikijs-rtr.service=wikijs-svc" - "traefik.http.services.wikijs-svc.loadbalancer.server.port=3000" logging: *default-logging #+end_src ** =lldap= - LDAP Server ([[https://github.com/nitnelave/lldap][link]]) #+begin_src yaml :tangle no lldap: image: nitnelave/lldap container_name: lldap restart: unless-stopped networks: - t2_proxy - backend ports: - 3890:3890 volumes: - $CONFIGDIR/lldap:/data labels: - "traefik.enable=true" - "traefik.http.routers.lldap-rtr.entrypoints=web-secure" - "traefik.http.routers.lldap-rtr.rule=Host(`lldap.$DOMAINNAME`)" - "traefik.http.routers.lldap-rtr.tls=true" - "traefik.http.routers.lldap-rtr.service=lldap-svc" - "traefik.http.routers.lldap-rtr.middlewares=authelia@docker" - "traefik.http.services.lldap-svc.loadbalancer.server.port=17170" logging: *default-logging #+end_src ** =acoustic= - Acoustic Pages #+begin_src yaml acoustic: container_name: acoustic image: abiosoft/caddy:1.0.3-no-stats restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - PLUGINS=git volumes: - $CONFIGDIR/acoustic/Caddyfile:/etc/Caddyfile - $CONFIGDIR/acoustic/web:/srv labels: - "traefik.enable=true" - "traefik.http.routers.acoustic-rtr.entrypoints=web-secure" - "traefik.http.routers.acoustic-rtr.rule=Host(`acoustic.$DOMAINNAME`)" - "traefik.http.routers.acoustic-rtr.tls=true" - "traefik.http.routers.acoustic-rtr.service=acoustic-svc" - "traefik.http.services.acoustic-svc.loadbalancer.server.port=2015" logging: *default-logging #+end_src *** =Caddyfile= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/acoustic/Caddyfile 0.0.0.0:2015 { root /srv/www/ git { repo https://git.tdehaeze.xyz/tdehaeze/acoustic-home-page path /srv/www/ interval -1 hook /acoustic-home-page/webhook 9a2CMCD5CucbnVQr then git submodule update --init --recursive --merge } } #+end_src ** =pyload= - Download manager (link) #+begin_src yaml pyload: container_name: pyload image: ghcr.io/linuxserver/pyload restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/pyload/config:/config - /srv/storage/Downloads:/downloads environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.pyload-rtr.entrypoints=web-secure" - "traefik.http.routers.pyload-rtr.rule=Host(`pyload.$DOMAINNAME`)" - "traefik.http.routers.pyload-rtr.tls=true" - "traefik.http.routers.pyload-rtr.service=pyload-svc" - "traefik.http.services.pyload-svc.loadbalancer.server.port=8000" logging: *default-logging #+end_src ** =aria2= - Download daemon ([[https://hub.docker.com/r/opengg/aria2][link]]) Backend ([[https://hub.docker.com/r/opengg/aria2][link]]): #+begin_src yaml aria2: container_name: aria2 image: opengg/aria2 restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID user: "${PUID}:${PGID}" volumes: - $CONFIGDIR/aria2:/config - /srv/storage/Downloads:/downloads ports: - 6800:6800 logging: *default-logging #+end_src Web-UI ([[https://hub.docker.com/r/p3terx/ariang][link]]): #+begin_src yaml aria2-ui: container_name: aria2-ui image: p3terx/ariang restart: unless-stopped networks: - t2_proxy depends_on: - aria2 environment: - PUID=$PUID - PGID=$PGID labels: - "traefik.enable=true" - "traefik.http.routers.aria2-rtr.entrypoints=http" - "traefik.http.routers.aria2-rtr.rule=Host(`dl.$DOMAINNAME`)" - "traefik.http.routers.aria2-rtr.tls=false" - "traefik.http.routers.aria2-rtr.service=aria2-svc" - "traefik.http.services.aria2-svc.loadbalancer.server.port=6880" logging: *default-logging #+end_src *** =aria2.conf= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/aria2/aria2.conf :noweb yes save-session=/config/aria2.session input-file=/config/aria2.session save-session-interval=60 dir=/downloads file-allocation=prealloc disk-cache=128M enable-rpc=true rpc-listen-port=6800 rpc-allow-origin-all=true rpc-listen-all=true rpc-secret=<> auto-file-renaming=false max-connection-per-server=16 min-split-size=1M split=16 #+end_src ** =deemix= - Music Download ([[https://gitlab.com/Bockiii/deemix-docker][link]]) :noexport: #+begin_src yaml deemix: container_name: deemix image: registry.gitlab.com/bockiii/deemix-docker restart: unless-stopped networks: - t2_proxy volumes: - /srv/storage/Music:/downloads - $CONFIGDIR/deemix:/config environment: - TZ=$TZ - PUID=$PUID - PGID=$PGID - ARL=$DEEMIX_ARL labels: - "traefik.enable=true" - "traefik.http.routers.deemix-rtr.entrypoints=web-secure" - "traefik.http.routers.deemix-rtr.rule=Host(`deemix.$DOMAINNAME`)" - "traefik.http.routers.deemix-rtr.tls=true" - "traefik.http.routers.deemix-rtr.service=deemix-svc" - "traefik.http.routers.deemix-rtr.middlewares=authelia@docker" - "traefik.http.services.deemix-svc.loadbalancer.server.port=6595" logging: *default-logging #+end_src *** =.arl= #+begin_src conf :tangle /ssh:thomas@homelab:/home/thomas/docker/config/deemix/.arl :noweb yes <> #+end_src ** =vaultwarden= - Password Manager ([[https://github.com/dani-garcia/vaultwarden][link]]) #+begin_src yaml vaultwarden: container_name: vaultwarden image: vaultwarden/server restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/vaultwarden:/data labels: - "traefik.enable=true" - "traefik.http.routers.vaultwarden-rtr.entrypoints=web-secure" - "traefik.http.routers.vaultwarden-rtr.rule=Host(`pass.$DOMAINNAME`)" - "traefik.http.routers.vaultwarden-rtr.tls=true" - "traefik.http.routers.vaultwarden-rtr.service=vaultwarden-svc" - "traefik.http.services.vaultwarden-svc.loadbalancer.server.port=80" #+end_src ** =gonic= - Subsonic Server #+begin_src yaml gonic: container_name: gonic image: sentriz/gonic restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/gonic:/data - /srv/storage/Music:/music:ro labels: - "traefik.enable=true" - "traefik.http.routers.gonic-rtr.entrypoints=web-secure" - "traefik.http.routers.gonic-rtr.rule=Host(`gonic.$DOMAINNAME`)" - "traefik.http.routers.gonic-rtr.tls=true" - "traefik.http.routers.gonic-rtr.service=gonic-svc" - "traefik.http.services.gonic-svc.loadbalancer.server.port=80" logging: *default-logging #+end_src ** =watchtower= - Automatic Update Docker images #+begin_src yaml watchtower: container_name: watchtower image: containrrr/watchtower restart: unless-stopped networks: - backend environment: - TZ=$TZ - WATCHTOWER_SCHEDULE=0 0 4 * * MON - WATCHTOWER_CLEANUP=true - WATCHTOWER_TIMEOUT=30s - WATCHTOWER_DEBUG=false - WATCHTOWER_MONITOR_ONLY=true - WATCHTOWER_NOTIFICATIONS=email - WATCHTOWER_NOTIFICATION_EMAIL_FROM=tdehaeze.xyz@gmail.com - WATCHTOWER_NOTIFICATION_EMAIL_TO=dehaeze.thomas@gmail.com - WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.gmail.com - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587 - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=tdehaeze.xyz@gmail.com - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=$GOOGLE_WATCHTOWER_PASS - WATCHTOWER_NOTIFICATION_EMAIL_DELAY=2 volumes: - /var/run/docker.sock:/var/run/docker.sock:ro #+end_src ** =guacamole= - Remote connection #+begin_src yaml guacamole: image: oznu/guacamole container_name: guacamole restart: unless-stopped networks: - t2_proxy - backend environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ volumes: - $CONFIGDIR/guacamole:/config labels: - "traefik.enable=true" - "traefik.http.routers.guacamole-rtr.entrypoints=web-secure" - "traefik.http.routers.guacamole-rtr.rule=Host(`guacamole.$DOMAINNAME`)" - "traefik.http.routers.guacamole-rtr.tls=true" - "traefik.http.routers.guacamole-rtr.service=guacamole-svc" - "traefik.http.services.guacamole-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src ** =transfer= - Transfer.sh #+begin_src yaml transfer: container_name: transfer image: dutchcoders/transfer.sh restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - UMASK_SET=022 - BASEDIR=/tmp/ - PROVIDER=local volumes: - /srv/storage/Uploads:/tmp/ labels: - "traefik.enable=true" - "traefik.http.routers.transfer-rtr.entrypoints=web-secure" - "traefik.http.routers.transfer-rtr.rule=Host(`file.$DOMAINNAME`)" - "traefik.http.routers.transfer-rtr.tls=true" - "traefik.http.routers.transfer-rtr.service=transfer-svc" - "traefik.http.services.transfer-svc.loadbalancer.server.port=8080" #+end_src ** =bazarr= - Automatically download Music #+begin_src yaml bazarr: container_name: bazarr image: linuxserver/bazarr restart: unless-stopped networks: - backend environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - UMASK_SET=022 #optional volumes: - $CONFIGDIR/bazarr:/config - /srv/storage/TVShows:/tv - /srv/storage/Movies:/movies ports: - 6767:6767 #+end_src ** =mail-cli= - CLI mail client #+begin_src yaml mail-cli: image: tdehaeze/docker-mail-cli container_name: mail-cli restart: unless-stopped volumes: - $CONFIGDIR/mail-cli:/config - /srv/storage/mail:/mail - /srv/storage/Downloads:/data environment: - TZ=$TZ - PUID=$PUID - PGID=$PGID tty: true #+end_src ** =cloudcmd= - Minimalist file manager #+begin_src yaml cloudcmd: container_name: cloudcmd image: coderaiser/cloudcmd restart: unless-stopped networks: - t2_proxy environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - CLOUDCMD_ROOT=/mnt/fs - CLOUDCMD_VIM=true - CLOUDCMD_ONE_FILE_PANEL=true volumes: - /srv/storage/Downloads:/mnt/fs/Downloads - /srv/storage/Cloud:/mnt/fs/Cloud - /srv/storage/TVShows:/mnt/fs/TVShows labels: - "traefik.enable=true" - "traefik.http.routers.cloudcmd-rtr.entrypoints=web-secure" - "traefik.http.routers.cloudcmd-rtr.rule=Host(`cloud.$DOMAINNAME`)" - "traefik.http.routers.cloudcmd-rtr.tls=true" - "traefik.http.routers.cloudcmd-rtr.service=cloudcmd-svc" - "traefik.http.routers.cloudcmd-rtr.middlewares=private-auth" - "traefik.http.services.cloudcmd-svc.loadbalancer.server.port=8000" #+end_src ** =wallabag= - Bookmark Manager #+begin_src yaml wallabag: container_name: wallabag image: wallabag/wallabag restart: unless-stopped depends_on: - wallabag_db networks: - t2_proxy - backend environment: - MYSQL_ROOT_PASSWORD=$WALLABAG_MYSQL_ROOT_PASSWORD - SYMFONY__ENV__DATABASE_DRIVER=pdo_mysql - SYMFONY__ENV__DATABASE_HOST=wallabag_db - SYMFONY__ENV__DATABASE_PORT=3308 - SYMFONY__ENV__DATABASE_NAME=symfony - SYMFONY__ENV__DATABASE_USER=root - SYMFONY__ENV__DATABASE_PASSWORD=$WALLABAG_MYSQL_PASSWORD - SYMFONY__ENV__DATABASE_CHARSET=utf8mb4 - SYMFONY__ENV__DOMAIN_NAME=https://wallabag.tdehaeze.xyz volumes: - $CONFIGDIR/wallabag/images:/var/www/wallabag/web/assets/images labels: - "traefik.enable=true" - "traefik.http.routers.wallabag-rtr.entrypoints=web-secure" - "traefik.http.routers.wallabag-rtr.rule=Host(`wallabag.$DOMAINNAME`)" - "traefik.http.routers.wallabag-rtr.tls=true" - "traefik.http.routers.wallabag-rtr.service=wallabag-svc" - "traefik.http.services.wallabag-svc.loadbalancer.server.port=80" wallabag_db: container_name: wallabag_db image: mariadb restart: unless-stopped networks: - backend ports: - 3308:3306 environment: - MYSQL_ROOT_PASSWORD=$WALLABAG_MYSQL_ROOT_PASSWORD - MYSQL_DATABASE=wallabag - MYSQL_USER=wallabag - MYSQL_PASSWORD=$WALLABAG_MYSQL_PASSWORD volumes: - $CONFIGDIR/wallabag/data:/var/lib/mysql #+end_src ** =buku= - Bookmark manager #+begin_src yaml buku: container_name: buku image: bukuserver/bukuserver restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ - BUKUSERVER_PER_PAGE=100 - BUKUSERVER_OPEN_IN_NEW_TAB=true # - BUKUSERVER_SECRET_KEY=123456789012345678901234 # - BUKUSERVER_URL_RENDER_MODE=full # - BUKUSERVER_DISABLE_FAVICON=false volumes: - $CONFIGDIR/buku:/root/.local/share/buku labels: - "traefik.enable=true" - "traefik.http.routers.buku-rtr.entrypoints=web-secure" - "traefik.http.routers.buku-rtr.rule=Host(`bookmarks.$DOMAINNAME`)" - "traefik.http.routers.buku-rtr.tls=true" - "traefik.http.routers.buku-rtr.service=buku-svc" - "traefik.http.routers.buku-rtr.middlewares=private-auth" - "traefik.http.services.buku-svc.loadbalancer.server.port=5001" #+end_src ** =duplicati= - Backup system #+begin_src yaml duplicati: container_name: duplicati image: linuxserver/duplicati restart: unless-stopped networks: - t2_proxy environment: - UID=$PUID - GID=$PGID - TZ=$TZ # - CLI_ARGS= #optional volumes: - $CONFIGDIR/duplicati:/config - /srv/storage/Backups:/backups - /srv/storage/Cloud/thesis:/source labels: - "traefik.enable=true" - "traefik.http.routers.duplicati-rtr.entrypoints=web-secure" - "traefik.http.routers.duplicati-rtr.rule=Host(`backup.$DOMAINNAME`)" - "traefik.http.routers.duplicati-rtr.tls=true" - "traefik.http.routers.duplicati-rtr.service=duplicati-svc" - "traefik.http.routers.duplicati-rtr.middlewares=private-auth" - "traefik.http.services.duplicati-svc.loadbalancer.server.port=8200" #+end_src ** =netdata= - Performance Monitoring #+begin_src yaml netdata: image: netdata/netdata container_name: netdata restart: unless-stopped hostname: netdata.tdehaeze.xyz networks: - t2_proxy - backend environment: - PUID=$PUID - PGID=998 - TZ=$TZ cap_add: - SYS_PTRACE security_opt: - apparmor:unconfined volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /var/run/docker.sock:/var/run/docker.sock:ro - $CONFIGDIR/netdata:/etc/netdata labels: - "traefik.enable=true" - "traefik.http.routers.netdata-rtr.entrypoints=web-secure" - "traefik.http.routers.netdata-rtr.rule=Host(`netdata.$DOMAINNAME`)" - "traefik.http.routers.netdata-rtr.tls=true" - "traefik.http.routers.netdata-rtr.service=netdata-svc" - "traefik.http.services.netdata-svc.loadbalancer.server.port=19999" #+end_src ** =fail2ban= - Ban hosts that cause multiple authentication errors #+begin_src yaml fail2ban: image: crazymax/fail2ban:latest container_name: fail2ban restart: unless-stopped network_mode: "host" cap_add: - NET_ADMIN - NET_RAW volumes: - $CONFIGDIR/fail2ban:/data - /var/log:/var/log:ro environment: - TZ=$TZ - PUID=$PUID - PGID=$PGID #+end_src * =.env= - Variable used for Docker Compose :noexport: :PROPERTIES: :header-args: :tangle /ssh:thomas@homelab:~/docker/.env :header-args+: :comments none :mkdirp yes :noweb yes :END: #+begin_src conf PUID=1000 PGID=1000 TZ=Europe/Paris #+end_src #+begin_src conf CONFIGDIR=/home/thomas/docker/config DOMAINNAME=tdehaeze.xyz #+end_src #+begin_src conf CLOUDFLARE_EMAIL=dehaeze.thomas@gmail.com CLOUDFLARE_API_KEY=<> #+end_src #+begin_src conf MINIFLUX_ADMIN_NAME=tdehaeze MINIFLUX_ADMIN_PASS=<> MINIFLUX_POSTGRES_PASSWORD=<> #+end_src #+begin_src conf RESTIC_PASSWORD=<> #+end_src #+begin_src conf WINGAUDIO_DB_MYSQL_ROOT_PASSWORD=<> WINGAUDIO_DB_MYSQL_PASSWORD=<> #+end_src #+begin_src conf GITEA_DB_MYSQL_ROOT_PASSWORD=<> GITEA_DB_MYSQL_PASSWORD=<> GITEA_SSH_PORT=2222 #+end_src #+begin_src conf PUREVPN_NAME=purevpn0s13581687 PUREVPN_PASS=<> #+end_src #+begin_src conf TRANSMISSION_NAME=tdehaeze TRANSMISSION_PASS=<> #+end_src #+begin_src conf GOTIFY_URL=https://gotify.tdehaeze.xyz/ GOTIFY_DEFAULTUSER_NAME=tdehaeze GOTIFY_DEFAULTUSER_PASS=<> #+end_src Gotify Tokken: #+begin_src conf QOBUZ_GOTIFY_TOKEN=<> RESTIC_GOTIFY_TOKEN=<> #+end_src #+begin_src conf QOBUZNAME=dehaeze.thomas@gmail.com QOBUZPASS=<> JELLYFINTOKEN=<> #+end_src #+begin_src conf AUTHELIA_NOTIFIER_SMTP_PASSWORD=<> AUTHELIA_JWT_SECRET=<> #+end_src #+begin_src conf JOALTOKEN=<> #+end_src #+begin_src conf GOOGLE_COMMENTO_PASS=<> GOOGLE_AUTHELIA_PASS=<> #+end_src #+begin_src conf COMMENTO_DB_PASSWORD=<> #+end_src * TODO Matrix ** Matrix server Use Ansible https://github.com/spantaleev/matrix-docker-ansible-deploy Must install newer version of ansible: - https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-ansible-on-ubuntu ** Basic Config #+begin_src yaml matrix_domain: tdehaeze.xyz matrix_ssl_lets_encrypt_support_email: 'dehaeze.thomas@gmail.com' matrix_coturn_turn_static_auth_secret: 'nxSdNOonPYXHmpog8j6dC1EciAmdYPNgpre1SZw1yc8VybtJcAQrzArVLAjzDR2z' matrix_synapse_macaroon_secret_key: 'exz3Wv7eWBDGYpnp5x3o3qGg6oalG04teu2eNlzMv6H7HxhW5U8Dr1HXZhMHafhl' matrix_postgres_connection_password: '4WmtV4utoNMKMOY1TxfJ9EsgCV8dTIV8hyB8YrCpZqd33bsursGKEP6BA1gY4YZJ' matrix_client_element_enabled: false matrix_homeserver_generic_secret_key: "{{ matrix_synapse_macaroon_secret_key }}" #+end_src #+begin_src yaml # ================================================================================================= # Setting up the Shared Secret Auth password provider module matrix_synapse_ext_password_provider_shared_secret_auth_enabled: true matrix_synapse_ext_password_provider_shared_secret_auth_shared_secret: Ru1kRNNyj8k7cVx2q2aAZCZL3R3Ph79Pq762W17CfExhmnAfxb9BI7zOktsBK32O #+end_src ** Use Traefik as reverse proxy #+begin_src yaml # ================================================================================================= # Disable Nginx and use Traefik instead # ================================================================================================= # Disable generation and retrieval of SSL certs matrix_ssl_retrieval_method: none # Configure Nginx to only use plain HTTP matrix_nginx_proxy_https_enabled: false # Don't bind any HTTP or federation port to the host # (Traefik will proxy directly into the containers) matrix_nginx_proxy_container_http_host_bind_port: '' matrix_nginx_proxy_container_federation_host_bind_port: '' # Disable Coturn because it needs SSL certs # (Clients can, though exposing IP address, use Matrix.org TURN) matrix_coturn_enabled: false # All containers need to be on the same Docker network as Traefik # (This network should already exist and Traefik should be using this network) matrix_docker_network: 't2_proxy' matrix_nginx_proxy_container_extra_arguments: - '--label "traefik.enable=true"' - '--label "traefik.http.routers.matrix-nginx-proxy.entrypoints=https"' - '--label "traefik.http.routers.matrix-nginx-proxy.rule=Host(`{{ matrix_server_fqn_matrix }}`,`{{ matrix_server_fqn_element }}`,`{{ matrix_server_fqn_dimension }}`,`{{ matrix_server_fqn_jitsi }}`)"' - '--label "traefik.http.routers.matrix-nginx-proxy.tls=true"' - '--label "traefik.http.services.matrix-nginx-proxy.loadbalancer.server.port=8080"' # - '--label "traefik.http.routers.matrix-nginx-proxy.middlewares=matrix-regex"' # - '--label "traefik.http.middlewares.matrix-regex.redirectregex.regex=https://matrix.tdehaeze.xyz/.well-known/matrix/(client|server)"' # - '--label "traefik.http.middlewares.matrix-regex.redirectregex.replacement=https://matrix.tdehaeze.xyz/"' matrix_synapse_container_extra_arguments: - '--label "traefik.enable=true"' - '--label "traefik.http.routers.matrix-synapse.entrypoints=synapse"' - '--label "traefik.http.routers.matrix-synapse.rule=Host(`{{ matrix_server_fqn_matrix }}`)"' - '--label "traefik.http.routers.matrix-synapse.tls=true"' - '--label "traefik.http.routers.matrix-synapse.service=matrix-synapse"' - '--label "traefik.http.services.matrix-synapse.loadbalancer.server.port=8048"' #+end_src ** Bridges *** Slack #+begin_src yaml # Slack matrix_mx_puppet_slack_enabled: true matrix_mx_puppet_slack_client_id: "299050134212.1969032215654" matrix_mx_puppet_slack_client_secret: "9a3240e570997645d4961d3cb595e798" #+end_src *** WhatsApp #+begin_src yaml # WhatsApp matrix_mautrix_whatsapp_enabled: true #+end_src *** Signal #+begin_src yaml # Signal matrix_mautrix_signal_enabled: true #+end_src *** Facebook #+begin_src yaml # Facebook matrix_mautrix_facebook_enabled: true #+end_src *** Telegram #+begin_src yaml # Telegram matrix_mautrix_telegram_enabled: true matrix_mautrix_telegram_api_id: 5596434 matrix_mautrix_telegram_api_hash: 29d6742e35799b88b9a7b5a46fe05ff2 #+end_src * Backup server ** Hardware [[https://www.hardkernel.com/shop/odroid-hc4-oled/][Odroid HC4]] ** Install *** Install MicroSD Ubuntu 20.04 minimal https://github.com/snakajim/odroidhc4-install *** First boot #+begin_quote Choose "Exit to shell" (switch to console then) # netboot_default # exit (back to petiboot menu) #+end_quote *** Setup SSH and Drive - create =thomas= user - add user to sudo group - add SSH key (use =ssh-copy-id=) - disable root ssh and password authentication - format disk drive - edit =/etc/fstab= to add the disk drive and mount it to =/srv/storage=. *** Install packages #+begin_src bash sudo apt install neovim tmux fd-find ripgrep fzf apache2-utils unrar ranger man git #+end_src *** Install docker https://blog.rylander.io/2020/12/23/setting-up-docker-on-ubuntu-20-04-focal-arm64/ ** Update #+begin_src bash :eval no sudo apt update sudo apt upgrade #+end_src ** Poweroff without =sudo= add the following at the end of =/etc/sudoers=: #+begin_src bash thomas backup =NOPASSWD: /usr/bin/systemctl poweroff,/usr/bin/systemctl halt,/usr/bin/systemctl reboot #+end_src ** Install Restic Restic is used for Backup. The binary is installed directly from [[https://github.com/restic/restic/releases][Github]] (for instance =restic_0.16.2_linux_arm64.bz2=). Then, the binary is copied in =/usr/local/bin=. To update restic, use the command =restic self-update=. * Cron Jobs ** Snapraid A snapraid Cron job is run with the Root user (use =sudo crontab -e= to edit). (See Section ref:sec:snapraid). ** Restic Backup Restart Container Sometimes the restic container fails and keeps restarting as it fails to reach the backup server (which is off). ** Music Multi-CD Create a script =~/cron/music-multi-cd.sh= with: #+begin_src bash :tangle /ssh:thomas@homelab:~/cron/music-multi-cd.sh :shebang "#!/usr/bin/env bash" shopt -s extglob globstar find /srv/storage/Music/ -maxdepth 2 -type d -name "Disc\ 1" -print0 | while read -d $'\0' file do echo $file cd_dir=$(dirname "$file") cd_name=$(basename "$cd_dir") mkdir "$cd_dir/$cd_name" && \ mv "$cd_dir"/Disc* "$cd_dir/$cd_name/" mv "$cd_dir/cover.jpg" "$cd_dir/$cd_name/" done #+end_src Type =crontab -e= and add this line: #+begin_src conf 1 2 * * * /home/thomas/cron/music-multi-cd.sh >> /home/thomas/cron/music-multi-cd.log 2>&1 #+end_src ** TODO Caddy Update - [ ] Is this even still in use? Create a script =~/cron/caddy_update.sh= with: #+begin_src bash :tangle /ssh:thomas@homelab:~/cron/caddy_update.sh :shebang "#!/usr/bin/env bash" docker exec caddy /bin/sh -c "cd /srv/www && echo -e \"Update repo $(date)\" && git submodule update --recursive --remote --merge" #+end_src Type =crontab -e= and add this line: #+begin_src conf */5 * * * * /home/thomas/cron/caddy_update.sh >> /home/thomas/cron/caddy_update.log 2>&1 #+end_src ** Back OpenWRT Config Create a script =~/cron/backup_openwrt_conf.sh= with: #+begin_src bash :tangle /ssh:thomas@homelab:~/cron/backup_openwrt_conf.sh :shebang "#!/usr/bin/env bash" ssh root@192.168.1.1 "umask go=; sysupgrade -b /tmp/backup-${HOSTNAME}-$(date +%F).tar.gz" && \ scp root@192.168.1.1:/tmp/backup-*.tar.gz /srv/storage/Backups/openWRT/ #+end_src Type =crontab -e= and add this line: #+begin_src conf */5 * * * * /home/thomas/cron/backup_openwrt_conf.sh >> /home/thomas/cron/backup_openwrt_conf.log 2>&1 #+end_src