#+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 apache2-utils unrar ranger fzf stow #+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 * 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 ** Add User and Password for Basic Authentication - Go to https://www.web2generators.com/apache-tools/htpasswd-generator and type the username and password - Alternatively, type =htpasswd -nb username mystrongpassword= in the shell - Or use the following docker container: #+begin_src bash docker run --rm -it httpd echo $(htpasswd -nb username-here password-here) | sed -e s/\\$/\\$\\$/g #+end_src - Paste the output in =~/docker/shared/.htpasswd= ** 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 #+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@grenoble:/ :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@grenoble:/ :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@grenoble:/ :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@grenoble:/ :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@grenoble:/ :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@grenoble:/ :results output replace docker exec restic restic restore --include /data/documents/manuals --target /backup 088e31a4 #+end_src * Docker-Compose :PROPERTIES: :header-args: :tangle /ssh:thomas@grenoble:~/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 networks: t2_proxy: ipv4_address: 192.168.90.254 # You can specify a static IP security_opt: - no-new-privileges:true ports: - 80:80 - 443:443 - 8080:8080 - 8448:8448 volumes: - $CONFIGDIR/traefik2/rules:/rules - $CONFIGDIR/traefik2/acme/acme.json:/acme.json - $CONFIGDIR/traefik2/shared:/shared - $CONFIGDIR/traefik2/traefik.yaml:/etc/traefik/traefik.yaml - $CONFIGDIR/traefik2/usersfile:/usersfile - /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.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" # Services - API - "traefik.http.routers.traefik-rtr.service=api@internal" # Middlewares - "traefik.http.routers.traefik-rtr.middlewares=middlewares-basic-auth@file" - "traefik.http.routers.traefik-rtr.middlewares=middlewares-rate-limit@file,middlewares-basic-auth@file" # - "traefik.http.routers.traefik-rtr.middlewares=test" - "traefik.http.middlewares.traefik-auth.basicauth.users=tdehaeze:$$apr1$$d.JmbY5J$$K8btOi1fwwVYOkCnicCVi." - "traefik.http.middlewares.public-auth.basicauth.users=tdehaeze:$$apr1$$d.JmbY5J$$K8btOi1fwwVYOkCnicCVi.,dehaeze:$$apr1$$ICU0hKjc$$D7buBzZDvokvMP1O6ptc5/" # Authelia # - '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' logging: *default-logging #+end_src *** =usersfile= #+begin_src conf :tangle /ssh:thomas@grenoble:~/docker/config/traefik2/usersfile tdehaeze:$$apr1$$d.JmbY5J$$K8btOi1fwwVYOkCnicCVi. #+end_src *** =traefik.yaml= #+begin_src yaml :tangle /ssh:thomas@grenoble:~/docker/config/traefik2/traefik.yaml global: checkNewVersion: true sendAnonymousUsage: false entryPoints: traefik: address: :8080 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 ** =nginx= - Root #+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@grenoble:~/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@grenoble:~/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: "Wiki" 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: "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: "Utilities" icon: "fas fa-rss" items: - name: "Miniflux" logo: "/assets/tools/miniflux.png" subtitle: "RSS Feeds" url: "https://rss.tdehaeze.xyz" # - name: "Bitwarden" # logo: "/assets/tools/bitwarden.png" # subtitle: "Password Manager" # url: "https://bw.tdehaeze.xyz" - name: "Home Assistant" logo: "/assets/tools/homeassistant.png" subtitle: "Home Assistant" url: "http://home.tdehaeze.xyz:8123" # - name: "Guacamole" # logo: "/assets/tools/guacamole.png" # subtitle: "SSH Access" # url: "https://guacamole.tdehaeze.xyz/" - name: "Cloud" icon: "fas fa-cloud" items: - name: "Cloud" 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: "Gitea" logo: "/assets/tools/gitea.png" subtitle: "Git Server" url: "https://git.tdehaeze.xyz" - name: "Download" icon: "fas fa-download" items: - name: "Transmission" logo: "/assets/tools/transmission.png" subtitle: "Torrents" url: "https://torrent.tdehaeze.xyz/transmission/web/" # - name: "transfer" # logo: "/assets/tools/transfer.png" # subtitle: "Transfer.sh" # url: "https://file.tdehaeze.xyz" - name: "deemix" subtitle: "Download Music" logo: "/assets/tools/deezer.png" url: "https://deemix.tdehaeze.xyz" - name: "qobuz" subtitle: "Qobuz-DL" logo: "/assets/tools/qobuz.png" url: "https://qobuz.tdehaeze.xyz" - name: "Aria2" logo: "/assets/tools/aria2.png" subtitle: "Direct Downloads" url: "http://dl.tdehaeze.xyz" - name: "Media" icon: "fas fa-film" items: - name: "Jellyfin" logo: "/assets/tools/jellyfin.png" subtitle: "Media Library" url: "https://jellyfin.tdehaeze.xyz" - name: "Config" icon: "fas fa-cog" items: - name: "Portainer" logo: "/assets/tools/portainer.png" subtitle: "Manger Docker" url: "https://portainer.tdehaeze.xyz" - name: "Traefik" logo: "/assets/tools/traefik.png" subtitle: "Reverse Proxy" url: "https://traefik.tdehaeze.xyz" - name: "Local" icon: "fas fa-home" items: # - name: "Jackett" # logo: "/assets/tools/jackett.png" # subtitle: "Download API" # url: "http://192.168.1.150:9117/" # - name: "Radarr" # logo: "/assets/tools/radarr.png" # subtitle: "Movie Manager" # url: "http://192.168.1.150:7878/" # - name: "Sonarr" # logo: "/assets/tools/sonarr.png" # subtitle: "TV Shows Manager" # url: "http://192.168.1.150:8989/" # - name: "Ombi" # logo: "/assets/tools/ombi.png" # subtitle: "Request Content" # url: "https://ombi.tdehaeze.xyz/" # - name: "Bazarr" # logo: "/assets/tools/bazarr.png" # subtitle: "Subtitles Manager" # url: "http://192.168.1.150:6767/" - name: "Scrutiny" logo: "/assets/tools/scrutiny.png" subtitle: "S.M.A.R.T" url: "http://192.168.1.150:8089/web/dashboard" - name: "OctoPrint" logo: "/assets/tools/octoprint.png" subtitle: "3D-Printing" url: "https://octoprint.tdehaeze.xyz/" #+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@grenoble:~/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@grenoble:~/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=traefik-auth" - "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 ** =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 ** =caddy= - Research Pages #+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@grenoble:~/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 ** =caddy= - Dotfiles #+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@grenoble:~/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 #+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=traefik-auth" - "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 network_mode: host volumes: - $CONFIGDIR/homeassistant:/config - /etc/localtime:/etc/localtime:ro - /dev/bus/usb:/dev/bus/usb # - ${USERDIR}/docker/shared:/shared environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.homeassistant-rtr.entrypoints=https,http" - "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.servers.url=http://172.17.0.1:8123" #- "traefik.http.services.homeassistant-svc.loadbalancer.server.port=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/LiveMusic:/data/livemusic - /srv/storage/Animes:/data/animes - /srv/storage/Movies:/data/movies - /srv/storage/Music:/data/music environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ 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 ** =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@grenoble:~/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: - backend cap_add: - SYS_RAWIO - SYS_ADMIN environment: - PUID=$PUID - PGID=$PGID - SCRUTINY_API_ENDPOINT=http://localhost:8080 - TZ=$TZ - SCRUTINY_WEB=true - SCRUTINY_COLLECTOR=true 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 ports: - 8089:8080 logging: *default-logging #+end_src ** =transmission= - Torrent server ([[https://hub.docker.com/r/haugene/transmission-openvpn][link]]) #+begin_src yaml transmission-openvpn: container_name: transmission image: haugene/transmission-openvpn restart: unless-stopped networks: - t2_proxy - backend 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: - 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=traefik-auth" - "traefik.http.services.transmission-svc.loadbalancer.server.port=9091" 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 environment: - PUID=$PUID - PGID=$PGID ports: - 6880:6880 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@grenoble:~/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=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=public-auth" - "traefik.http.services.deemix-svc.loadbalancer.server.port=6595" logging: *default-logging #+end_src *** =.arl= #+begin_src conf :tangle /ssh:thomas@grenoble:~/docker/config/deemix/.arl :noweb yes <> #+end_src ** =qobuz= - Qobuz Downloader ([[https://github.com/tdehaeze/qobuz-docker][link]]) :noexport: #+begin_src yaml qobuz: container_name: qobuz image: tdehaeze/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 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=public-auth" - "traefik.http.services.qobuz-svc.loadbalancer.server.port=8080" logging: *default-logging #+end_src ** =radicale= - CalDAC/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@grenoble:~/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=--keep-daily 7 --keep-weekly 4 --keep-monthly 12 - RESTIC_BACKUP_ARGS=--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@grenoble:~/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=traefik-auth" - "traefik.http.services.octoprint-svc.loadbalancer.server.port=80" logging: *default-logging #+end_src ** TODO =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.routers.linkding-rtr.middlewares=traefik-auth" - "traefik.http.services.linkding-svc.loadbalancer.server.port=9090" 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=traefik-auth" - "traefik.http.services.adguardhome-svc.loadbalancer.server.port=3000" 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_MAIL_HOST=smtp.gmail.com - DIUN_NOTIF_MAIL_PORT=465 - DIUN_NOTIF_MAIL_SSL=true - DIUN_NOTIF_MAIL_USERNAME=tdehaeze.xyz@gmail.com - DIUN_NOTIF_MAIL_PASSWORD=$GMAIL_PASS - DIUN_NOTIF_MAIL_FROM=tdehaeze.xyz@gmail.com - DIUN_NOTIF_MAIL_TO=dehaeze.thomas@gmail.com volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - $CONFIGDIR/diun:/data #+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 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 #+end_src * Docker-Compose OLD :noexport: ** =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 ** =duplicity= - Bookmark manager #+begin_src yaml duplicity: container_name: duplicity image: tecnativa/duplicity restart: unless-stopped networks: - t2_proxy environment: - TZ=$TZ - DST=megav2://mega@mega.nz/backup volumes: - $CONFIGDIR/duplicity/.megav2rc:/root/.megav2rc - /srv/storage/Cloud/thesis:/mnt/backup/src/thesis:ro #+end_src *** =.megarc= #+begin_src conf :tangle /ssh:thomas@grenoble:~/docker/config/duplicity/.megav2rc :noweb yes [Login] user = dehaeze.thomas@gmail.com pass = <> #+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=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 ** =gotify= - Notification service #+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(`notify.$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 ** =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=traefik-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 ** =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=traefik-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 ** =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=traefik-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=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=traefik-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 ** =authelia= - Single Sign-On Multi-Factor portal ([[https://github.com/authelia/authelia][link]]) #+begin_src yaml authelia: image: authelia/authelia container_name: authelia restart: unless-stopped networks: - t2_proxy volumes: - $CONFIGDIR/authelia:/config expose: - 9091 environment: - UID=$PUID - GID=$PGID - TZ=$TZ labels: - "traefik.enable=true" - "traefik.http.routers.authelia-rtr.entrypoints=https" - "traefik.http.routers.authelia-rtr.rule=Host(`login.$DOMAINNAME`)" - "traefik.http.routers.authelia-rtr.tls=true" - "traefik.http.routers.authelia-rtr.service=authelia-svc" #+end_src * =.env= - Variable used for Docker Compose :PROPERTIES: :header-args: :tangle /ssh:thomas@grenoble:~/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=<> #+end_src #+begin_src conf MINIFLUX_ADMIN_NAME=tdehaeze MINIFLUX_ADMIN_PASS=<> MINIFLUX_POSTGRES_PASSWORD=<> #+end_src #+begin_src conf RESTIC_PASSWORD=<> RESTIC_B2_ACCOUNT_ID=<> RESTIC_B2_ACCOUNT_KEY=<> #+end_src #+begin_src conf GITEA_DB_MYSQL_ROOT_PASSWORD=<> GITEA_DB_MYSQL_PASSWORD=<> GITEA_SSH_PORT=2222 #+end_src #+begin_src conf NORDVPN_NAME=dehaeze.thomas@gmail.com NORDVPN_PASS=<> #+end_src #+begin_src conf QOBUZNAME=jeanmarie.dehaeze@wanadoo.fr QOBUZPASS=<> JELLYFINTOKEN=<> #+end_src #+begin_src conf GOTIFY_DEFAULTUSER_NAME=tdehaeze GOTIFY_DEFAULTUSER_PASS=<> #+end_src #+begin_src conf GUACAMOLE_POSTGRES_PASSWORD=<> #+end_src #+begin_src conf DEEMIX_ARL=<> #+end_src #+begin_src conf GMAIL_PASS=<> #+end_src #+begin_src conf COMMENTO_DB_PASSWORD=<> #+end_src * Cron Jobs ** Caddy Update Create a script =~/cron/caddy_update.sh= with: #+begin_src bash :tangle /ssh:thomas@grenoble:~/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