literate-dotfiles/homelab.org

2817 lines
83 KiB
Org Mode

#+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 3 3200G |
| RAM | Corsair Vengeance LPX 16Go (2x8Go) DDR4 3200MHz |
| Cooler | ARCTIC Freezer 34 eSports DUO |
| PSU | Corsair SF450 |
| SSD M.2 | Samsung 970 EVO Plus 250Gb |
| Disk Drives | Various drives ranging from 3Tb to 8Tb |
* Installation
** Ubuntu
- Download *Ubuntu Server 20.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 "partitionname" ext4 0% 100%
#+end_src
#+begin_src bash :eval no
sudo mkfs.ext4 -L partitionname /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/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/6574b7ae-321c-4078-9793-bc41a4fa5588 /mnt/disk1 ext4 defaults 0 0
/dev/disk/by-uuid/6fcd38b9-0886-46bd-900d-cb1f170dbcee /mnt/parity ext4 defaults 0 0
/mnt/disk* /srv/storage fuse.mergerfs direct_io,defaults,allow_other,minfreespace=50G,fsname=mergerfs 0 0
#+end_src
** Automating with SnapRAID Runner
*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]]).
SnapRAID is here used inside a Docker container ([[https://hub.docker.com/r/xagaba/snapraid][link]]).
** 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:
#+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]].
** 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
* Maintenance - How To
** Update System/Packages
#+begin_src bash
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
** 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
** =snapraid=
To see all files "backed up" by snapraid, use:
#+begin_src bash
docker exec -ti snapraid snapraid list | fzf
#+end_src
In reality, snapraid is ran from the docker container:
#+begin_src bash
docker exec -ti snapraid snapraid fix -f <path_to_file>
#+end_src
The path to file should be relative: =/srv/storage/Cloud/org/file.org= -> =Cloud/org/file.org=
** Restore Online backup with =restic=
To list backups:
#+begin_src bash :dir /ssh:thomas@homelab:/ :results output replace
docker exec restic restic snapshots
#+end_src
#+RESULTS:
: ID Time Host Tags Paths
: --------------------------------------------------------------------------------
: a7b98408 2020-09-03 21:18:00 4803c2af7d4e /data/documents/manuals
: 088e31a4 2020-09-03 21:50:26 4803c2af7d4e /data/documents/manuals
: 9cf0b480 2020-09-03 22:05:47 4803c2af7d4e /data/documents/manuals
: --------------------------------------------------------------------------------
: 3 snapshots
Force backup of folder:
#+begin_src bash :dir /ssh:thomas@homelab:/ :results output replace
docker exec restic restic backup /data/documents/manuals
#+end_src
#+RESULTS:
:
: Files: 0 new, 2 changed, 8475 unmodified
: Dirs: 0 new, 2 changed, 0 unmodified
: Added to the repo: 1.010 KiB
:
: processed 8477 files, 589.800 MiB in 0:02
: snapshot 9cf0b480 saved
Find the path to the file within the snapshot:
#+begin_src bash :dir /ssh:thomas@homelab:/ :results output replace
docker exec restic restic find file_name
#+end_src
Find files only for a specific snapshot:
#+begin_src bash :dir /ssh:thomas@homelab:/ :results output replace
docker exec restic restic find -s latest file_name
#+end_src
Restore files/folders (replace file/folders):
#+begin_src bash :dir /ssh:thomas@homelab:/ :results output replace
docker exec restic restic restore --include /data/documents/manuals --target / 088e31a4
#+end_src
You can use =latest= instead of the ID.
If indeed, we want to make a copy of the file, we can use the backup folder
#+begin_src bash :dir /ssh:thomas@homelab:/ :results output replace
docker exec restic restic restore --include /data/documents/manuals --target /backup 088e31a4
#+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
* Docker-Compose
:PROPERTIES:
:header-args: :tangle /ssh:thomas@homelab:~/docker/docker-compose.yaml
:header-args+: :comments none :mkdirp yes
:END:
#+begin_src yaml
version: "3.4"
#+end_src
** Networks
#+begin_src yaml
networks:
t2_proxy:
external:
name: t2_proxy
backend:
external: false
default:
driver: bridge
#+end_src
** Logging
#+begin_src yaml
x-logging:
&default-logging
driver: "json-file"
options:
max-size: "200k"
max-file: "10"
#+end_src
** =traefik= - Application proxy ([[https://github.com/traefik/traefik][link]])
#+begin_src yaml
services:
#+end_src
#+begin_src yaml
traefik:
container_name: traefik
image: traefik:2.2.1
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/rules:/rules
- $CONFIGDIR/traefik2/acme/acme.json:/acme.json
- $CONFIGDIR/traefik2/shared:/shared
- $CONFIGDIR/traefik2/traefik.yaml:/etc/traefik/traefik.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=http"
- "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=https"
- "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.domains[0].main=$DOMAINNAME"
- "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINNAME"
- "traefik.http.services.traefik-svc.loadbalancer.server.port=8080"
# Services - API
- "traefik.http.routers.traefik-rtr.service=api@internal"
logging: *default-logging
#+end_src
*** =traefik.yaml=
#+begin_src yaml :tangle /ssh:thomas@homelab:~/docker/config/traefik2/traefik.yaml
global:
checkNewVersion: true
sendAnonymousUsage: false
entryPoints:
http:
address: :80
https:
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
synapse:
address: :8448
api:
dashboard: true
log:
level: ERROR
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
swarmMode: false
file:
directory: /rules
watch: true
certificatesResolvers:
dns-cloudflare:
acme:
email: $CLOUDFLARE_EMAIL
storage: /acme.json
dnsChallenge:
provider: cloudflare
resolvers: 1.1.1.1:53,1.0.0.1:53
#+end_src
** =authelia= - Single Sign-On Multi-Factor portal ([[https://github.com/authelia/authelia][link]])
#+begin_src yaml
authelia:
image: authelia/authelia:4.30
container_name: authelia
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=$AUTHELIA_NOTIFIER_SMTP_PASSWORD
- AUTHELIA_JWT_SECRET=$AUTHELIA_JWT_SECRET
labels:
- "traefik.enable=true"
- "traefik.http.routers.authelia-rtr.entrypoints=https"
- "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:~/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: traefik.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- domain: zigbee2mqttassistant.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- domain: scrutiny.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- domain: portainer.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- domain: syncthing.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- domain: octoprint.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- domain: uptime.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- domain: joal.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- domain: down.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- ["group:friends"]
- ["group:family"]
- domain: qobuz.tdehaeze.xyz
policy: bypass
resources:
- "^/download([/?].*)?$"
- domain: qobuz.tdehaeze.xyz
policy: one_factor
subject:
- ["group:admins"]
- ["group:friends"]
- ["group:family"]
session:
name: authelia_session
expiration: 3600
inactivity: 300
domain: tdehaeze.xyz
regulation:
max_retries: 3
find_time: 120
ban_time: 300
storage:
local:
path: /config/db.sqlite3
notifier:
smtp:
username: tdehaeze.xyz@gmail.com
host: smtp.gmail.com
port: 587
sender: tdehaeze.xyz@gmail.com
#+end_src
** TODO [#C] =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=https"
- "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
** =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=https"
- "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
** =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=https"
- "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:~/docker/config/root/Caddyfile
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;
}
location /.well-known/matrix/server {
proxy_pass https://matrix.tdehaeze.xyz/.well-known/matrix/server;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
#+end_src
** =homer= - Home page ([[https://github.com/bastienwirtz/homer][link]])
#+begin_src yaml
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=https"
- "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:~/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: "Wiki"
logo: "/assets/tools/wikijs.png"
subtitle: "Shared Wiki"
url: "https://wiki.tdehaeze.xyz"
- name: "Research"
logo: "/assets/tools/orgmode.png"
subtitle: "Research Pages"
url: "https://research.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: "Multimedia"
icon: "fas fa-photo-video"
items:
- name: "Jellyfin"
logo: "/assets/tools/jellyfin.png"
subtitle: "Media Library"
url: "https://jellyfin.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: "File Browser"
logo: "/assets/tools/cloud.png"
subtitle: "Simple Personnal Could"
url: "https://cloud.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: "Miniflux"
logo: "/assets/tools/miniflux.png"
subtitle: "RSS Feeds"
url: "https://rss.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: "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: "Transmission"
logo: "/assets/tools/transmission.png"
subtitle: "Torrent Client"
url: "http://torrent.tdehaeze.xyz:9091/transmission/web/"
- name: "Joal"
logo: "/assets/tools/joal.png"
subtitle: "Increase Ratio"
url: "https://joal.tdehaeze.xyz/joal/ui/#/"
- 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: "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: "http://192.168.1.1/"
- name: "Home Assistant"
logo: "/assets/tools/homeassistant.png"
subtitle: "Home Assistant"
url: "http://home.tdehaeze.xyz:8123"
- name: "Zigbee2MQTT"
logo: "/assets/tools/zigbee2mqtt.png"
subtitle: "Zigbee2MQTT Assistant"
url: "https://zigbee2mqttassistant.tdehaeze.xyz/"
- name: "OctoPrint"
logo: "/assets/tools/octoprint.png"
subtitle: "3D-Printing"
url: "https://octoprint.tdehaeze.xyz/"
#+end_src
** =linkding= - Bookmark manager ([[https://github.com/sissbruecker/linkding][link]])
#+begin_src yaml
linkding:
container_name: linkding
image: sissbruecker/linkding:latest
restart: unless-stopped
networks:
- t2_proxy
volumes:
- $CONFIGDIR/linkding:/etc/linkding/data
environment:
- TZ=$TZ
- PUID=$PUID
- PGID=$PGID
labels:
- "traefik.enable=true"
- "traefik.http.routers.linkding-rtr.entrypoints=https"
- "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
** =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:~/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
# Defines the data disks to use
# The order is relevant for parity, do not change it
# Format: "disk DISK_NAME DISK_MOUNT_POINT"
disk d0 /mnt/disk0
disk d1 /mnt/disk1
# 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 *.unrecoverable
exclude /tmp/
exclude /lost+found/
exclude *.!sync
exclude .AppleDouble
exclude ._AppleDouble
exclude .DS_Store
exclude ._.DS_Store
exclude .Thumbs.db
exclude .fseventsd
exclude .Spotlight-V100
exclude .TemporaryItems
exclude .Trashes
exclude .AppleDB
#+end_src
*** =snapraid-runner.conf=
#+begin_src conf :tangle /ssh:thomas@homelab:~/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
** =portainer= - Manage docker ([[https://github.com/portainer/portainer][link]])
#+begin_src yaml
portainer:
container_name: portainer
image: portainer/portainer
restart: unless-stopped
command: -H unix:///var/run/docker.sock
command: --no-auth
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=https"
- "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
** =wireguard= - VPN ([[https://github.com/linuxserver/docker-wireguard][link]])
#+begin_src yaml
wireguard:
container_name: wireguard
image: linuxserver/wireguard
restart: unless-stopped
networks:
- t2_proxy
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
- SERVERURL=wireguard.tdehaeze.xyz
- SERVERPORT=51820
- PEERS=3
- PEERDNS=auto
volumes:
- $CONFIGDIR/wireguard:/config
- /lib/modules:/lib/modules
ports:
- 51820:51820/udp
logging: *default-logging
#+end_src
** =gluetun= - Provide VPN connection to other containers ([[https://github.com/bubuntux/nordvpn][link]])
#+begin_src yaml
gluetun:
image: qmcgaw/gluetun
container_name: gluetun
restart: unless-stopped
cap_add:
- NET_ADMIN
network_mode: bridge
ports:
- 8065:8065 # For transmission
- 9091:9091 # For transmission
- 51413:51413 # For transmission
- 51413:51413/udp # For transmission
environment:
- OPENVPN_USER=$NORDVPN_NAME
- OPENVPN_PASSWORD=$NORDVPN_PASS
- VPNSP=nordvpn
- REGION=France
- SERVER_NUMBER=776
- TZ=$TZ
volumes:
- $CONFIGDIR/gluetun:/config
#+end_src
** =transmission= - Torrent client ([[https://hub.docker.com/r/linuxserver/transmission][link]])
#+begin_src yaml
transmission:
container_name: transmission
image: ghcr.io/linuxserver/transmission
restart: unless-stopped
network_mode: container:gluetun
depends_on:
- gluetun
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
- USER=$TRANSMISSION_NAME
- PASS=$TRANSMISSION_PASS
volumes:
- $CONFIGDIR/transmission:/config
- /srv/storage/Downloads:/downloads
- /srv/storage/Downloads/watch:/watch
logging: *default-logging
#+end_src
** =gitea= - Git server ([[https://github.com/go-gitea/gitea][link]])
#+begin_src yaml
gitea:
container_name: git
image: gitea/gitea:1.13.2
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=https"
- "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
environment:
- MYSQL_ROOT_PASSWORD=$GITEA_DB_MYSQL_ROOT_PASSWORD
- MYSQL_DATABASE=gitea
- MYSQL_USER=gitea
- MYSQL_PASSWORD=$GITEA_DB_MYSQL_PASSWORD
volumes:
- $CONFIGDIR/mariadb:/var/lib/mysql
#+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=https"
- "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
** =research= - Research Pages ([[https://git.tdehaeze.xyz/tdehaeze/research-home-page][link]])
#+begin_src yaml
caddy:
container_name: caddy
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/caddy/Caddyfile:/etc/Caddyfile
- $CONFIGDIR/web:/srv
# - ~/.ssh:/root/.ssh
labels:
- "traefik.enable=true"
- "traefik.http.routers.caddy-rtr.entrypoints=https"
- "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:~/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
}
}
#+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=https"
- "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:~/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
** =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=https"
- "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
** =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=https"
- "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
** =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=https"
- "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
restart: unless-stopped
networks:
- backend
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=$MINIFLUX_POSTGRES_PASSWORD
volumes:
- $CONFIGDIR/miniflux_db:/var/lib/postgresql/data
logging: *default-logging
#+end_src
** =homeassistant= - Home Automation ([[https://hub.docker.com/r/homeassistant/home-assistant][link]])
#+begin_src yaml
homeassistant:
container_name: homeassistant
image: homeassistant/home-assistant
restart: unless-stopped
#networks:
# - t2_proxy
#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=https"
- "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
** =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
- /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:
# - 122
# devices:
# # VAAPI Devices
# - /dev/dri/renderD128:/dev/dri/renderD128
# - /dev/dri/card0:/dev/dri/card0
ports:
- 8096:8096
labels:
- "traefik.enable=true"
- "traefik.http.routers.jellyfin-rtr.entrypoints=https"
- "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
** =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=https"
- "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
** =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=https"
- "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
** =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/database.db:/database.db
- $CONFIGDIR/filebrowser/.filebrowser.json:/.filebrowser.json
- /srv/storage:/srv/storage
user: "${PUID}:${PGID}"
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
labels:
- "traefik.enable=true"
- "traefik.http.routers.filebrowser-rtr.entrypoints=https"
- "traefik.http.routers.filebrowser-rtr.rule=Host(`cloud.$DOMAINNAME`)"
- "traefik.http.routers.filebrowser-rtr.tls=true"
- "traefik.http.routers.filebrowser-rtr.service=filebrowser-svc"
- "traefik.http.services.filebrowser-svc.loadbalancer.server.port=80"
logging: *default-logging
#+end_src
*** =.filebrowser.json=
#+begin_src json :tangle /ssh:thomas@homelab:~/docker/config/filebrowser/.filebrowser.json
{
"port": 80,
"baseURL": "",
"address": "",
"log": "stdout",
"database": "/database.db",
"root": "/srv/storage"
}
#+end_src
** =scrutiny= - Hard drive monitoring ([[https://hub.docker.com/r/hotio/scrutiny][link]])
#+begin_src yaml
scrutiny:
container_name: scrutiny
image: linuxserver/scrutiny
restart: unless-stopped
networks:
- t2_proxy
cap_add:
- SYS_RAWIO
- SYS_ADMIN
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
- SCRUTINY_WEB=true
- SCRUTINY_COLLECTOR=false
volumes:
- $CONFIGDIR/scrutiny:/config
- /run/udev:/run/udev:ro
devices:
- /dev/sda:/dev/sda
- /dev/sdb:/dev/sdb
- /dev/sdc:/dev/sdc
- /dev/sdd:/dev/sdd
- /dev/nvme0n1:/dev/nvme0n1
labels:
- "traefik.enable=true"
- "traefik.http.routers.scrutiny-rtr.entrypoints=https"
- "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
** =radicale= - CalDAV/CardDAV server ([[https://github.com/tomsquest/docker-radicale][link]])
#+begin_src yaml
radicale:
container_name: radicale
image: tomsquest/docker-radicale:latest
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=https"
- "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:~/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
** =restic= - Automatic online backups ([[https://github.com/djmaze/resticker/][link]])
#+begin_src yaml
restic:
container_name: restic
image: mazzolino/restic
restart: unless-stopped
networks:
- t2_proxy
environment:
- BACKUP_CRON=0 30 0 * * *
- RESTIC_REPOSITORY=b2:tdehaeze:/restic
- RESTIC_PASSWORD=$RESTIC_PASSWORD
- RESTIC_BACKUP_SOURCES=/source
- RESTIC_FORGET_ARGS=--group-by tag --keep-daily 7 --keep-weekly 4 --keep-monthly 12 --prune
- RESTIC_BACKUP_ARGS=--tag local --exclude-file /exclude.txt
- B2_ACCOUNT_ID=$RESTIC_B2_ACCOUNT_ID
- B2_ACCOUNT_KEY=$RESTIC_B2_ACCOUNT_KEY
- UID=$PUID
- GID=$PGID
- TZ=$TZ
volumes:
- $CONFIGDIR/restic/exclude.txt:/exclude.txt:ro
- /srv/storage/Cloud/thesis:/source/Cloud/thesis:ro
- /home/thomas/docker:/source/docker:ro
logging: *default-logging
#+end_src
*** =exclude.txt= - Exclude files
#+begin_src conf :tangle /ssh:thomas@homelab:~/docker/config/restic/exclude.txt
*.db
*.log
*.log.*
/source/docker/config/gitea/git/
/source/docker/config/guacamole/
/source/docker/config/guacamole_db/
/source/docker/config/mariadb/
/source/docker/config/miniflux_db/
/source/docker/config/jellyfin/data/
/source/docker/config/dotfiles/www/
/source/docker/config/web/www/
#+end_src
** =octoprint= - Web interface for 3D printing ([[https://github.com/OctoPrint/OctoPrint][link]])
#+begin_src yaml
octoprint:
container_name: octoprint
image: octoprint/octoprint
restart: unless-stopped
networks:
- t2_proxy
environment:
- UID=$PUID
- GID=$PGID
- TZ=$TZ
privileged: true
volumes:
- $CONFIGDIR/octoprint:/octoprint
- /dev/bus/usb:/dev/bus/usb
labels:
- "traefik.enable=true"
- "traefik.http.routers.octoprint-rtr.entrypoints=https"
- "traefik.http.routers.octoprint-rtr.rule=Host(`octoprint.$DOMAINNAME`)"
- "traefik.http.routers.octoprint-rtr.tls=true"
- "traefik.http.routers.octoprint-rtr.service=octoprint-svc"
- "traefik.http.routers.octoprint-rtr.middlewares=authelia@docker"
- "traefik.http.services.octoprint-svc.loadbalancer.server.port=80"
logging: *default-logging
#+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
- UID=$PUID
- GID=$PGID
- TZ=$TZ
volumes:
- $CONFIGDIR/mealie:/app/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.miam-rtr.entrypoints=https"
- "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=80"
logging: *default-logging
#+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
** =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=$GMAIL_PASS
- COMMENTO_SMTP_FROM_ADDRESS=tdehaeze.xyz@gmail.com
depends_on:
- commento_db
labels:
- "traefik.enable=true"
- "traefik.http.routers.commento-rtr.entrypoints=https"
- "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:
container_name: commento_db
image: postgres:13
restart: unless-stopped
networks:
- backend
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
** =uptime-kuma= - Monitoring Tool ([[https://github.com/louislam/uptime-kuma][link]])
#+begin_src yaml
uptime-kuma:
container_name: uptime-kuma
image: louislam/uptime-kuma
restart: unless-stopped
networks:
- t2_proxy
volumes:
environment:
- TZ=$TZ
- UID=$PUID
- GID=$PGID
volumes:
- $CONFIGDIR/uptime-kuma:/app/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.uptime-rtr.entrypoints=https"
- "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
** =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/data
- /srv/storage/Books:/books
- /srv/storage/Scans:/scans
- /srv/storage/Comics:/comics
labels:
- "traefik.enable=true"
- "traefik.http.routers.kavita-rtr.entrypoints=https"
- "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
** =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
devices:
- /dev/ttyACM0:/dev/ttyACM0
#+end_src
** =zigbee2mqttassistant= - GUI for Zigbee2Mqtt ([[https://github.com/yllibed/Zigbee2MqttAssistant][link]])
#+begin_src yaml
zigbee2mqttAssistant:
container_name: zigbee2mqttassistant
image: carldebilly/zigbee2mqttassistant
restart: unless-stopped
networks:
- t2_proxy
environment:
- Z2MA_SETTINGS__MQTTSERVER=192.168.1.21:1883
# - Z2MA_SETTINGS__MQTTUSERNAME={MQTTUSERNAME}
# - Z2MA_SETTINGS__MQTTPASSWORD={MQTTPASSWORD}
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
labels:
- "traefik.enable=true"
- "traefik.http.routers.zigbee2mqttassistant-rtr.entrypoints=https"
- "traefik.http.routers.zigbee2mqttassistant-rtr.rule=Host(`zigbee2mqttassistant.$DOMAINNAME`)"
- "traefik.http.routers.zigbee2mqttassistant-rtr.tls=true"
- "traefik.http.routers.zigbee2mqttassistant-rtr.service=zigbee2mqttassistant-svc"
- "traefik.http.routers.zigbee2mqttassistant-rtr.middlewares=authelia@docker"
- "traefik.http.services.zigbee2mqttassistant-svc.loadbalancer.server.port=80"
logging: *default-logging
#+end_src
** =qobuz= - Qobuz Downloader ([[https://github.com/tdehaeze/qobuz-docker][link]]) :noexport:
#+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=https"
- "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
** =joal= - Seeding Torrents ([[https://github.com/anthonyraymond/joal][link]]) :noexport:
#+begin_src yaml
joal:
image: anthonyraymond/joal
container_name: joal
restart: unless-stopped
networks:
- t2_proxy
volumes:
- $CONFIGDIR/joal:/data
command: ["--joal-conf=/data", "--spring.main.web-environment=true", "--server.port=80", "--joal.ui.path.prefix=joal", "--joal.ui.secret-token=$JOALTOKEN"]
labels:
- "traefik.enable=true"
- "traefik.http.routers.joal-rtr.entrypoints=https"
- "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=80"
logging: *default-logging
#+end_src
** =docker-torrent= - Download Torrents from YGG ([[https://github.com/tdehaeze/qobuz-docker][link]]) :noexport:
#+begin_src yaml
down:
container_name: down
image: tdehaeze/docker-torrent
restart: always
networks:
- t2_proxy
volumes:
- /srv/storage/Downloads/watch:/watch
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=https"
- "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.routers.down-rtr.middlewares=authelia@docker"
- "traefik.http.services.down-svc.loadbalancer.server.port=3000"
logging: *default-logging
#+end_src
* Docker-Compose OLD :noexport:
** =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=https"
- "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:~/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=https"
- "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:~/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=<<get-password(passname="nas/aria2")>>
auto-file-renaming=false
max-connection-per-server=16
min-split-size=1M
split=16
#+end_src
** =transmission-openvpn= - Torrent server ([[https://hub.docker.com/r/haugene/transmission-openvpn][link]])
#+begin_src yaml :tangle no
transmission-openvpn:
container_name: transmission
image: haugene/transmission-openvpn
restart: unless-stopped
environment:
- PUID=$PUID
- PGID=$PGID
- CREATE_TUN_DEVICE=true
- ENABLE_UFW=true
- WEBPROXY_ENABLED=false
- TRANSMISSION_WEB_UI=combustion
- OPENVPN_PROVIDER=NORDVPN
- OPENVPN_USERNAME=$NORDVPN_NAME
- OPENVPN_PASSWORD=$NORDVPN_PASS
- NORDVPN_COUNTRY=FR
- NORDVPN_CATEGORY=P2P
- NORDVPN_PROTOCOL=tcp
- LOCAL_NETWORK=192.168.0.0/16
volumes:
- /srv/storage/Downloads:/data
- /etc/localtime:/etc/localtime:ro
cap_add:
- NET_ADMIN
ports:
- 51413:51413
- 51413:51413/udp
labels:
- "traefik.enable=true"
- "traefik.http.routers.transmission-rtr.entrypoints=https"
- "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.routers.transmission-rtr.middlewares=private-auth"
- "traefik.http.services.transmission-svc.loadbalancer.server.port=9091"
logging: *default-logging
#+end_src
** TODO =adguardhome= - Network-wide ads & trackers blocking DNS server ([[https://github.com/AdguardTeam/AdGuardHome][link]])
#+begin_src yaml
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
- 853:853
labels:
- "traefik.enable=true"
- "traefik.http.routers.adguardhome-rtr.entrypoints=https"
- "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=private-auth"
- "traefik.http.services.adguardhome-svc.loadbalancer.server.port=3000"
logging: *default-logging
#+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=https"
- "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:~/docker/config/deemix/.arl :noweb yes
<<get-password(passname="nas/deemix_arl")>>
#+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=https"
- "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=https"
- "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=$GMAIL_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=https"
- "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
** TODO =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=https"
- "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
** =ombi= - Request movies/tv-shows
#+begin_src yaml
ombi:
container_name: ombi
image: linuxserver/ombi
restart: unless-stopped
networks:
- t2_proxy
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
# - BASE_URL=/ombi #optional
volumes:
- $CONFIGDIR/ombi:/config
labels:
- "traefik.enable=true"
- "traefik.http.routers.ombi-rtr.entrypoints=https"
- "traefik.http.routers.ombi-rtr.rule=Host(`ombi.$DOMAINNAME`)"
- "traefik.http.routers.ombi-rtr.tls=true"
- "traefik.http.routers.ombi-rtr.service=ombi-svc"
- "traefik.http.services.ombi-svc.loadbalancer.server.port=3579"
#+end_src
** =jackett= - API support for torrents
#+begin_src yaml
jackett:
container_name: jackett
image: linuxserver/jackett
restart: unless-stopped
networks:
- backend
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
- AUTO_UPDATE=true
# - RUN_OPTS=
volumes:
- $CONFIGDIR/jackett:/config
- /srv/storage/Downloads:/downloads
ports:
- 9117:9117
#+end_src
** =radarr= - Automatically download Movies
#+begin_src yaml
radarr:
container_name: radarr
image: linuxserver/radarr
restart: unless-stopped
networks:
- backend
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
- UMASK_SET=022
volumes:
- $CONFIGDIR/radarr:/config
- /srv/storage/Movies:/movies
- /srv/storage/Downloads:/downloads
ports:
- 7878:7878
#+end_src
** =sonarr= - Automatically download TVshows
#+begin_src yaml
sonarr:
container_name: sonarr
image: linuxserver/sonarr
restart: unless-stopped
networks:
- backend
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
- UMASK_SET=022
volumes:
- $CONFIGDIR/sonarr:/config
- /srv/storage/TVShows:/tv
- /srv/storage/Downloads:/downloads
ports:
- 8989:8989
#+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=https"
- "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=
#+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=https"
- "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=https"
- "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
** =transmission= - Torrent server
#+begin_src yaml
transmission:
container_name: transmission
image: linuxserver/transmission
restart: unless-stopped
networks:
- t2_proxy
environment:
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
volumes:
- $CONFIGDIR/transmission:/config
- /srv/storage/Downloads:/downloads
- /srv/storage/Downloads/watch:/watch
ports:
- 9091:9091
- 51413:51413
- 51413:51413/udp
labels:
- "traefik.enable=true"
- "traefik.http.routers.transmission-rtr.entrypoints=https"
- "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.routers.transmission-rtr.middlewares=private-auth"
- "traefik.http.services.transmission-svc.loadbalancer.server.port=9091"
#+end_src
** =navidrome= - Music server
#+begin_src yaml
navidrome:
container_name: navidrome
image: deluan/navidrome
restart: unless-stopped
networks:
- t2_proxy
environment:
ND_MUSICFOLDER: /music
ND_DATAFOLDER: /data
ND_SCANINTERVAL: 10m
ND_LOGLEVEL: info
ND_PORT: 4533
ND_TRANSCODINGCACHESIZE: 100MB
ND_SESSIONTIMEOUT: 24h
ND_BASEURL: ""
volumes:
- $CONFIGDIR/navidrome:/data
- /srv/storage/Music:/music:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.navidrome-rtr.entrypoints=https"
- "traefik.http.routers.navidrome-rtr.rule=Host(`music.$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"
#+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=https"
- "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=https"
- "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
CONFIGDIR=/home/thomas/docker/config
DOMAINNAME=tdehaeze.xyz
#+end_src
#+begin_src conf
CLOUDFLARE_EMAIL=dehaeze.thomas@gmail.com
CLOUDFLARE_API_KEY=<<get-password(passname="nas/cloudflare_api_key")>>
#+end_src
#+begin_src conf
MINIFLUX_ADMIN_NAME=tdehaeze
MINIFLUX_ADMIN_PASS=<<get-password(passname="nas/miniflux_admin_pass")>>
MINIFLUX_POSTGRES_PASSWORD=<<get-password(passname="nas/miniflux_postgres_pass")>>
#+end_src
#+begin_src conf
RESTIC_PASSWORD=<<get-password(passname="nas/restic_pass")>>
RESTIC_B2_ACCOUNT_ID=<<get-password(passname="nas/restic_B2_id")>>
RESTIC_B2_ACCOUNT_KEY=<<get-password(passname="nas/restic_B2_key")>>
#+end_src
#+begin_src conf
AUDIOSERVE_SHARED_SECRET=<<get-password(passname="nas/audioserve_secret")>>
#+end_src
#+begin_src conf
GITEA_DB_MYSQL_ROOT_PASSWORD=<<get-password(passname="nas/gitea_mysql_root_pass")>>
GITEA_DB_MYSQL_PASSWORD=<<get-password(passname="nas/gitea_mysql_pass")>>
GITEA_SSH_PORT=2222
#+end_src
#+begin_src conf
NORDVPN_NAME=dehaeze.thomas@gmail.com
NORDVPN_PASS=<<get-password(passname="nordvpn.com/dehaeze.thomas@gmail.com")>>
#+end_src
#+begin_src conf
TRANSMISSION_NAME=tdehaeze
TRANSMISSION_PASS=<<get-password(passname="nas/transmission")>>
#+end_src
#+begin_src conf
GOTIFY_URL=https://gotify.tdehaeze.xyz/
GOTIFY_DEFAULTUSER_NAME=tdehaeze
GOTIFY_DEFAULTUSER_PASS=<<get-password(passname="nas/gotify")>>
#+end_src
#+begin_src conf
DOWN_GOTIFY_TOKEN=<<get-password(passname="nas/gotify_down_token")>>
QOBUZ_GOTIFY_TOKEN=<<get-password(passname="nas/gotify_qobuz_token")>>
DIUN_GOTIFY_TOKEN=<<get-password(passname="nas/gotify_diun_token")>>
#+end_src
#+begin_src conf
QOBUZNAME=jeanmarie.dehaeze@wanadoo.fr
QOBUZPASS=<<get-password(passname="qobuz.com/jeanmarie.dehaeze@wanadoo.fr")>>
JELLYFINTOKEN=<<get-password(passname="nas/jellyfin_token")>>
#+end_src
#+begin_src conf
AUTHELIA_NOTIFIER_SMTP_PASSWORD=<<get-password(passname="google.com/tdehaeze.xyz")>>
AUTHELIA_JWT_SECRET=<<get-password(passname="nas/authelia_jwt_secret")>>
#+end_src
#+begin_src conf
YGGTORRENTNAME=deoldeol
YGGTORRENTPASS=<<get-password(passname="yggtorrent/deoldeol")>>
#+end_src
#+begin_src conf
JOALTOKEN=<<get-password(passname="joal.tdehaeze.xyz/secret-token")>>
#+end_src
#+begin_src conf
GUACAMOLE_POSTGRES_PASSWORD=<<get-password(passname="nas/guacamole_postgres_pass")>>
#+end_src
#+begin_src conf
DEEMIX_ARL=<<get-password(passname="nas/deemix_arl")>>
#+end_src
#+begin_src conf
GMAIL_PASS=<<get-password(passname="google.com/tdehaeze.xyz")>>
#+end_src
#+begin_src conf
COMMENTO_DB_PASSWORD=<<get-password(passname="nas/commento_db_pass")>>
#+end_src
* Cron Jobs
** Caddy Update
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