diff --git a/.env.sample b/.env.sample index 7978b18..d108c91 100644 --- a/.env.sample +++ b/.env.sample @@ -1,3 +1,6 @@ +# Internal settings (they will not be passed to running services) +CHECK_FOR_OUTDATED_CONFIG=true + # General Traefik (reverse proxy) settings TRAEFIK_DOMAIN=mydomain.com ACME_MAIL=my-email@my-provider.com @@ -10,7 +13,11 @@ TZ="Europe/Paris" HTTP_USER=myuser HTTP_PASSWORD='mypassword_encoded' # Keep these simple quotes! -# Containers permissions mapping +# Host paths + containers permissions mapping +HOST_CONFIG_PATH="/data/config" +HOST_MEDIA_PATH="/data/torrents" +# Will be located in $HOST_MEDIA_PATH +DOWNLOAD_SUBFOLDER="deluge" PGID=1000 PUID=1000 @@ -29,4 +36,11 @@ PORTAINER_ADMIN_PASSWORD=h4ckMePleAse # Flood username declared in deluge rpc daemon FLOOD_PASSWORD=myfloodpassword -FLOOD_AUTOCREATE_USER_IN_DELUGE_DAEMON=false \ No newline at end of file +FLOOD_AUTOCREATE_USER_IN_DELUGE_DAEMON=false + +# Wireguard custom endpoint +WIREGUARD_ENDPOINT= +WIREGUARD_PORT=51820 +WIREGUARD_PUBLIC_KEY= +WIREGUARD_PRIVATE_KEY= +WIREGUARD_ADDRESS= \ No newline at end of file diff --git a/.gitignore b/.gitignore index a8655bd..5657fae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,16 @@ .DS_Store -/config **/tunnel-options.sh **/.env **/traefik/http_auth backup/ services.conf + +traefik/custom/dynamic*.yaml +traefik/custom/custom-*.yaml +samples/custom*/*.yaml + +config.yaml +services/custom/*.yaml +services/custom/*.yml +services/generated/*.yaml \ No newline at end of file diff --git a/README.md b/README.md index 6af1570..4f82ec3 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,33 @@ -# Seedbox +

Seedbox

+

+ An extensive and hackable collection of containerized services to set up a seedbox and personal media server. +

+
-A collection of Dockerfiles and a docker-compose configuration to set up a -seedbox and personal media server. +## ✨ Features -## Included Applications +* Easy to configure personal media server without needing too much technical skills +* Compatible with multiple systems (Linux servers, desktops, Synology NAS...) +* Automatic HTTPS ceritificates management and renewal + * Support for HTTP only too if required for your use-case +* Everything is hackable + * Add your own services + * Disable the ones you do not want + * Customize or add your own routing rules to integrate with existing services + * Tweak any service to your need by using custom file parameter on any service +* VPN support with multiple providers + * Hide the service(s) of your choice behind a VPN tunnel + * Non mandatory +* Declarative configuration +* Persistent data for your media +* Install & update using the same script +* Start with the [Configuration Guide](doc/configuration.md) + +## ⚠️ News + +Version 2 is released, please make sure you read [this V2 Migration Guide](doc/UPGRADE_V2.md) as there are breaking changes! + +## 📦 Included Applications | Application | Web Interface | Docker image | Version (image tag) | Notes | -----------------------|----------------------------|------------------------------------------------------------------------|-------------------------|---------------------| @@ -14,6 +38,9 @@ seedbox and personal media server. | Radarr | radarr.yourdomain.com | [linuxserver/radarr](https://hub.docker.com/r/linuxserver/radarr) | *develop* | Movies monitor | | Bazarr | bazarr.yourdomain.com | [linuxserver/bazarr](https://hub.docker.com/r/linuxserver/bazarr) | *latest* | Subtitles monitor | | Lidarr | lidarr.yourdomain.com | [linuxserver/lidarr](https://hub.docker.com/r/linuxserver/lidarr) | *develop* | Music monitor | +| Readarr | readarr.yourdomain.com | [linuxserver/readarr](https://hub.docker.com/r/linuxserver/readarr) | *nightly* | Ebook and comic monitor | +| Komga | komga.yourdomain.com | [gotson/komga](https://hub.docker.com/r/gotson/komga) | *latest* | Comic Book Manager | +| Kavita | Kavita.yourdomain.com | [gotson/komga](https://hub.docker.com/r/gotson/komga) | *latest* | Comic Book Manager | | Ombi | ombi.yourdomain.com | [linuxserver/ombi](https://hub.docker.com/r/linuxserver/ombi) | *latest* | Plex content requests | | Overseerr | overseerr.yourdomain.com | [linuxserver/overseerr](https://hub.docker.com/r/linuxserver/overseerr) | *latest* | Plex content requests | | Jackett | jackett.yourdomain.com | [linuxserver/jackett](https://hub.docker.com/r/linuxserver/jackett) | *latest* | Tracker indexer | @@ -22,58 +49,41 @@ seedbox and personal media server. | Tautulli (plexPy) | tautulli.yourdomain.com | [linuxserver/tautulli](https://hub.docker.com/r/linuxserver/tautulli) | *latest* | Plex stats and admin| | Tdarr | tdarr.yourdomain.com | [haveagitgat/tdarr](https://hub.docker.com/r/haveagitgat/tdarr) | *latest* | Re-encode files | | NextCloud | nextcloud.yourdomain.com | [linuxserver/nextcloud](https://hub.docker.com/r/linuxserver/nextcloud) | *latest* | Files management | -| NextCloud-db (MariaDB) | not reachable | [mariadb](https://hub.docker.com/r/_/mariadb) | *10* | DB for Nextcloud | +| NextCloud-db (MariaDB) | *not reachable* | [mariadb](https://hub.docker.com/r/_/mariadb) | *10* | DB for Nextcloud | | Portainer | portainer.yourdomain.com | [portainer/portainer](https://hub.docker.com/r/portainer/portainer) | *latest* | Container management| | Netdata | netdata.yourdomain.com | [netdata/netdata](https://hub.docker.com/r/netdata/netdata) | *latest* | Server monitoring | | Duplicati | duplicati.yourdomain.com | [linuxserver/duplicati](https://hub.docker.com/r/linuxserver/duplicati)| *latest* | Backups | +| Heimdall | yourdomain.com | [linuxserver/heimdall](https://hub.docker.com/r/linuxserver/heimdall)| *latest* | Main dashboard | +| Syncthing | syncthing.yourdomain.com | [linuxserver/syncthing](https://hub.docker.com/r/linuxserver/syncthing) | *latest* | P2P files sharing | +| Traefik | traefik.yourdomain.com | [traefik](https://hub.docker.com/_/traefik) | *latest* | Traefik reverse proxy (access to admin dashboard) | +| Gluetun | - | [qmcgaw/gluetun](https://hub.docker.com/r/qmcgaw/gluetun)| *latest* | VPN client | +| *Any application you want!* | *whatever.yourdomain.com* | *Any image* | *Any tag* | *Any service - See the [Configuration Guide](doc/configuration.md)* | -The front-end reverse proxy (Traefik - **check the next section if you have already the seedbox with Traefik v1**) routes based on the lowest level subdomain - (e.g. `deluge.example.com` would route to deluge). Since this is how the router -works, it is recommended for you to get a top level domain. If you do not have -one, you can edit your domains locally by changing your hosts file or use a -browser plugin that changes the host header. +## 🌐 Traefik + +The front-end reverse proxy (Traefik - **check [this guide](doc/traefik_v2.md) if you still have the seedbox with Traefik v1**) routes based on the lowest level subdomain (e.g. `deluge.example.com` would route to deluge). Since this is how the router works, it is recommended for you to get a top level domain. If you do not have one, you can edit your domains locally by changing your hosts file or use a browser plugin that changes the host header. Traefik takes care of valid Let's Encrypt certificates and auto-renewal. -Note: Plex is also available directly through the `32400` port without going -through the reverse proxy. +Note: Plex is also available directly through the `32400` port without going through the reverse proxy. -## September 2020 - Upgrade to Traefik v2 instructions +You can also add your own Traefik rules to integrate with other services (deployed wihthin docker or somewhere else on your LAN, or even on the Internet). +Check the [Configuration Guide](doc/configuration.md). -Before upgrading Traefik to version 2, please check the following: +## ⚙️ Installation -- In this repo, Traefik v2 upgrade is as seamless as possible (same environment variables than before, out-of-the-box config file...). -- **First, ``git pull`` to grab the latest code.** -- The ``HTTP_PASSWORD`` variable now must be simple-quoted in the .env file. See the updated ``.env.sample`` file (which has also been reorganized) -- Run ``init.sh`` in order to create required Docker objects (network name has changed). -- You can update your acme.json to a Traefik v2-compliant one by doing the following (before launching Traefik v2): - -```sh -mkdir -p /tmp/migration -cd /tmp/migration -sudo cp /opt/traefik/acme.json . -sudo chmod 775 /tmp/migration/acme.json -# Do *NOT* forget the --resolver at the end! (le = Let's Encrypt resolver, see traefik/traefik.yml) -docker run --rm -v ${PWD}:/data -w /data containous/traefik-migration-tool acme -i acme.json -o acme2.json --resolver le -mkdir -p /data/config/traefik -sudo cp acme2.json /data/config/traefik/acme.json -sudo chmod 600 /data/config/traefik/acme.json -# When you already have a backup! -sudo rm -rf /opt/traefik /tmp/migration -``` - -- As from Traefik v2, as Http Authentication is now possible on the Traefik console, the latter is enabled at ``traefik.yourdomain.com``. -- After all this, you can simply do: ``./update-all.sh``! Voilà! - -## Dependencies +### Dependencies - [Docker](https://github.com/docker/docker) >= 20.10 -- [Docker Compose](https://github.com/docker/compose) >= 1.28.0 -- [local-persist Docker plugin](https://github.com/MatchbookLab/local-persist): installed directly on host (not in container). This is a volume plugin that extends the default local driver’s functionality by allowing you specify a mountpoint anywhere on the host, which enables the files to always persist, even if the volume is removed via `docker volume rm`. Use *systemd* install for Ubuntu 16.04. +- [Docker Compose](https://github.com/docker/compose) >= 2.2 +- [local-persist Docker plugin](https://github.com/MatchbookLab/local-persist): installed directly on host (not in container). This is a volume plugin that extends the default local driver’s functionality by allowing you specify a mountpoint anywhere on the host, which enables the files to always persist, even if the volume is removed via `docker volume rm`. Use *systemd* install for Ubuntu. +- [jq](https://stedolan.github.io/jq/download/) >= 1.5 +- [yq](https://github.com/mikefarah/yq/releases) >= 4 -## Configuration +### Prepare your host Before running, please create the volumes which will be statically mapped to the ones on the host: +For example: ```sh sudo su -c "mkdir /data && mkdir /data/config && mkdir /data/torrents" @@ -83,29 +93,23 @@ sudo su -c "mkdir /data && mkdir /data/config && mkdir /data/torrents" Edit the `.env` file and change the variables as desired. The variables are all self-explanatory. -**NEW** -You can also disable a service if you do not need it by editing the ``services.conf`` file. -Simply change the "*enable*" key with the "*disable*" one for the service you want to disable. -If you remove a line in this file, it will be considered as "enabled" as all services are enabled by default. +### Review the configuration -## Running & updating +The configuration lives in the ``config.yaml`` file. + +All you need to know is located in the [Configuration Guide](doc/configuration.md). + +### Running & updating ```sh -./update-all.sh +./run-seedbox.sh ``` -docker-compose should manage all the volumes and network setup for you. If it -does not, verify that your docker and docker-compose version is updated. +All services and synamic configuration will be automatically created without further action from your part. -Make sure you install the dependencies and finish configuration before doing -this. +Make sure you install the dependencies and finish configuration before doing this. -## PlexPass - -Just set the `VERSION` environment variable to `latest` on the Plex service (enabled by default). -See https://hub.docker.com/r/linuxserver/plex. - -## Where is my data? +### Where is my data? All data is saved in the docker volumes `seedbox_config` or `seedbox_torrents`. diff --git a/config-updater.sh b/config-updater.sh new file mode 100755 index 0000000..f150423 --- /dev/null +++ b/config-updater.sh @@ -0,0 +1,120 @@ +#!/bin/bash +set -e +################################################################################ +### === config-updater.sh === ### +### Script which takes as input the old format config file (services.conf) ### +### and transforms it in the new format in yaml, using jq and yq ### +################################################################################ + +cleanup_on_exit() { + rm -f tmp.json config.json +} +trap cleanup_on_exit EXIT + +# Load common functions +source config/tools.sh + +# Check that required tools are installed +check_utilities + +if [[ ! -f services.conf ]]; then + echo "[$0] ERROR. Could nof find services.conf. Exiting." + exit 1 +fi + +jq -n '{"services": []}' > config.json + +# First, add Traefik as it was not explicitely set by default in old config file (services.conf) +if ! grep -q "traefik" services.conf; then + jq -r '.services[.services| length] |= . + + { + "name": "traefik", + "enabled": true, + "traefik": { + "enabled": true, + "rules": [ + { + "host": "traefik.'$(echo '${TRAEFIK_DOMAIN}')'", + "service": "api@internal", + "httpAuth": true, + } + ] + } + }' config.json > tmp.json + rm -f config.json + mv tmp.json config.json +fi + +cat services.conf | while read line || [[ -n $line ]]; do + key=$(echo $line | sed -r "s/^(.*):.*$/\1/") + enabled="true" + if grep -q "disable" <<< $line; then + enabled="false" + fi + + # Compatibility for services.conf already on dev (with temporary syntax -vpn) + if grep -q "\-vpn" <<< $line; then continue; fi + + enableVpn="false" + # If this service is disabled AND another one in the file is enabled with VPN mode, keep that information + if grep -q "$key-vpn: enable" services.conf; then + if [[ enabled="false" ]]; then + #echo "[$0] $key => another service detected enabled with vpn..." + enableVpn="true" + enabled="true" + fi + fi + + if grep -q "\-hardware-transcoding" <<< $line; then continue; fi + + # Define if Traefik should be enabled on the service + case $key in + flaresolverr|gluetun) + enableTraefik="false" + rules=$(jq -n '[]') + ;; + *) + enableTraefik="true" + # If Traefik enabled => define if http auth Traefik middleware must be set by default + case $key in + kavita|komga|nextcloud|ombi|overseerr|plex|portainer|tautulli) + defaultHttpAuth="false" + ;; + *) + defaultHttpAuth="true" + ;; + esac + # Define scheme // For nextcloud, scheme must be https + internalScheme="http" + [[ $key == "nextcloud" ]] && internalScheme="https" + + # Define service default port from bundled config file + internalPort=$(cat config/ports | { grep $key || true; } | sed -r "s/^${key}: (.*)$/\1/") + rules=$(jq -n '[ + { + "host": "'"$key"'.'$(echo '${TRAEFIK_DOMAIN}')'", + "httpAuth": '"${defaultHttpAuth}"', + "internalPort": '"${internalPort}"', + "internalScheme": "'"${internalScheme}"'" + } + ]') + ;; + esac + + jq -r --argjson RULES "$rules" '.services[.services| length] |= . + + { + "name": "'"$key"'", + "enabled": '"${enabled}"', + "vpn": '"${enableVpn}"', + "traefik": { + "enabled": '"${enableTraefik}"', + "rules": $RULES + } + }' config.json > tmp.json + rm -f config.json + mv tmp.json config.json + +done + +# Transform json into yaml, easier to manipulate for the user +cat config.json | yq e -P - > config.yaml \ No newline at end of file diff --git a/config.sample.yaml b/config.sample.yaml new file mode 100644 index 0000000..9eb973b --- /dev/null +++ b/config.sample.yaml @@ -0,0 +1,238 @@ +services: + - name: traefik + enabled: true + traefik: + enabled: true + rules: + - host: traefik.${TRAEFIK_DOMAIN} + service: api@internal + httpAuth: true + - name: deluge + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: deluge.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8112 + # Uncomment to specify custom schme (http by default) + # internalScheme: http + # Uncomment to *NOT* generate LetsEncrypt certificate (useful for local domains) + # httpOnly: true + - name: flood + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: flood.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 3000 + - name: plex + enabled: true + vpn: false + # uncomment to use custom file with specific parameters for hardware transcoding + # customFile: plex-hardware-transcoding.yaml + # You can also place you own file in services/custom/ and call it here like this: + # customFile: custom/my_own_file.yaml + traefik: + enabled: true + rules: + - host: plex.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 32400 + - name: flaresolverr + enabled: true + vpn: false + traefik: + enabled: false + rules: [] + - name: jackett + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: jackett.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 9117 + - name: prowlarr + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: prowlarr.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 9696 + - name: sonarr + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: sonarr.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8989 + - name: radarr + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: radarr.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 7878 + - name: bazarr + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: bazarr.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 6767 + - name: lidarr + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: lidarr.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8686 + - name: readarr + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: readarr.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8787 + - name: komga + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: komga.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 8080 + - name: kavita + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: kavita.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 5000 + - name: ombi + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: ombi.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 3579 + - name: overseerr + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: overseerr.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 5055 + - name: tautulli + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: tautulli.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 8181 + - name: jdownloader + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: jdownloader.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 5800 + - name: tdarr + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: tdarr.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8265 + - name: nextcloud + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: nextcloud.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 443 + internalScheme: https + - name: portainer + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: portainer.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 9443 + - name: netdata + enabled: true + vpn: false + traefik: + enabled: true + rules: + - host: netdata.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 19999 + - name: duplicati + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: duplicati.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8200 + - name: syncthing + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: syncthing.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8384 + - name: heimdall + # Beware to the host when enabling it! + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: ${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 80 + # Gluetun is the VPN client service. + - name: gluetun + enabled: false + traefik: + enabled: false + rules: [] diff --git a/config/ports b/config/ports new file mode 100644 index 0000000..54f4b74 --- /dev/null +++ b/config/ports @@ -0,0 +1,24 @@ +bazarr: 6767 +deluge: 8112 +flood: 3000 +heimdall: 80 +jackett: 9117 +jdownloader: 5800 +ombi: 3579 +overseerr: 5055 +plex: 32400 +prowlarr: 9696 +radarr: 7878 +sonarr: 8989 +lidarr: 8686 +readarr: 8787 +komga: 8080 +kavita: 5000 +nextcloud: 443 +portainer: 9443 +syncthing: 8384 +tdarr: 8265 +netdata: 19999 +duplicati: 8200 +tautulli: 8181 +traefik: 80 diff --git a/config/tools.sh b/config/tools.sh new file mode 100755 index 0000000..a87b794 --- /dev/null +++ b/config/tools.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +############################################################################## +############################### UTIL FUNCTIONS ############################### +############################################################################## + +check_utilities () { + # Check that jq is installed + if ! which jq >/dev/null; then + echo "[$0] jq does not exist. Install it from here: https://stedolan.github.io/jq/download/" + echo "[$0] Please install jq version 1.5 or above." + echo "[$0] Also, please make sure it is in the PATH." + exit 1 + fi + + # Check that yq is installed + if ! which yq >/dev/null; then + echo "[$0] yq does not exist. Install it from here: https://github.com/mikefarah/yq/releases" + echo "[$0] Please install yq version 4 or above." + echo "[$0] Also, please make sure it is in the PATH." + exit 1 + fi +} \ No newline at end of file diff --git a/doc/UPGRADE_V2.md b/doc/UPGRADE_V2.md new file mode 100644 index 0000000..916b86d --- /dev/null +++ b/doc/UPGRADE_V2.md @@ -0,0 +1,92 @@ +# Upgrade to V2 + +**Seedbox version 2 is here!** 🔥 + +Since there are some breaking changes and a configuration structure migration, a major version was mandatory. + +## What's new? + +* **Configuration change to new YAML format** + * Run ``config-updater.sh`` to migrate your old services.conf to the new config.yaml format. + * ⚠️ ``jq`` (v1.5+) and ``yq`` (v4+) are now requirements + * Easier feature switches + * If a service is missing, it won't be enabled by default like before. The config is now more declarative. + * Traefik routing rules are now dynamically generated in a file in Traefik config directory, so no more Docker labels. They became hard to maintain due to all possibilities caused by VPN support or custom files for example. + * New config syntax documented in the [Configuration Guide](./configuration.md#configuration-structure-and-parameters). +* **VPN support** + * With ``gluetun`` service, you can now place any service behind a VPN. + * Default gluetun configuration is Wireguard "custom" mode, but see below... + * More details in the [VPN section of the Configuration Guide](./configuration.md#vpn). +* **Support custom services and docker-compose yaml files** + * Place a docker-compose yaml file in ``services/custom/`` directory, add a service in your config.yaml specifying a ``customFile``, and you are set. + * Support Plex hardware transcoding using a custom-file, already available in the ``services`` directory (just specify a ``customFile`` on plex service - see [config.sample.yaml](../config.sample.yaml)). + * More details in the [Configuration Guide](./configuration.md#add-your-own-service). +* **Support arbitrary Traefik rules** + * Place a Traefik YAML in ``samples/custom-traefik/`` directory, it will be copied in the Traefik configuration folder. + * Ideal to forward traffic to other services which do not belong to this seedbox. + * More details in [this section of the Configuration Guide](./configuration.md#integration-with-other-services-custom-traefik-config) +* **Disable certificates for some domains** + * Using the flag ``httpOnly: true`` on a service, access any service in unsecure mode, delegating certificates management on a higher level (reverse proxy, firewall...). More details in the [Configuration Guide](./configuration.md#disable-https-completely). +* **Multiple hosts for any services** + * The new config structure allows for more customization, for example you can now have many routes on the same service. Let's say, a local unsecured route + a secured one for remote access. Or anything you want. +* **More customization** + * Such as http authentication which is no more hardcoded but configurable for each service. + * Configurable paths on host for persistent data +* **New services** + * ``Gluetun``: [VPN client (see above)](https://github.com/qdm12/gluetun) + * ``Heimdall``: [Dashboard](https://github.com/linuxserver/Heimdall) + * ``Readarr``: [Ebook and comic monitor](https://github.com/Readarr/Readarr) + * ``Komga``: [Comic Book Manager](https://github.com/gotson/komga) + * ``Kavita``: [Comic / Book Manager](https://github.com/Kareadita/Kavita) + * ``Syncthing``: [P2P files synchronization](https://github.com/linuxserver/docker-syncthing) +* ⚠️ Docker compose v2.2+ is now required + +And also: + +* ``update-all.sh`` is now called ``run-seedbox.sh`` but its purpose is the same. +* More checks in ``run-seedbox.sh``. For example, throws an error if Flood is enabled but not Deluge, or if VPN is enabled on a service but the VPN client is not. +* You can now specify where your data lives on your host through new environments variables (see [.env.sample](.env.sample)). + * This change is backward-compatible as the ``run-seedbox.sh`` script will default to the old "/data/torrents" and "/data/config" paths if these variables are not set. +* ``networks:`` section is now aligned with the new docker compose syntax +* ⚠️ Nextcloud-db has moved. It is now in ``/data/config`` (or somewhere else if you set the new variables for host paths) (see below how to mitigate the errors). [See the dedicated section below](#nextcloud-db-has-moved). +* Disable Traefik access logs +* New flag ``--debug`` for ``run-seedbox.sh`` to see what is happening during configuration parsing. +* Releases are named after LOST mythology. I exhausted all the characters of Person of Interest, so that's time for a change. Only geeks will get it, I know. + +## Some reading about configuration + +📖 Do not forget to read the [Configuration Guide](./configuration.md). + +## How to migrate + +```sh +./config-updater.sh +# Check the content of your .env file (in comparison with .env.sample which brings new variables) +# Also, check your generated config.yaml and read the config documentation (in doc/configuration.md) +./run-seedbox.sh +``` + +When everything runs smoothly, you can delete your old configuration file which is now useless: + +```sh +rm -f services.conf +``` + +> ⚠️ Also, please make sure you have read the next section about Nextcloud Database location. + +## Nextcloud-db has moved + +Since commit e4ede925a8ce09b177206f30487a889da9e10334, nextcloud-db directory (mapped on /var/lib/mysql) has moved from +``/data/nextcloud-db`` to ``$HOST_CONFIG_PATH/nextcloud-db`` (*/data/config/nextcloud-db by default*). + +To ensure a smooth transition, you will have to move the directory nextcloud-db into the correct new location, then run some commands to fix the schema: + +```sh +mv /data/nextcloud-db/ /data/config/ +./run-seedbox.sh +source .env +docker exec -it nextcloud-db mysql_upgrade -u root -p${MYSQL_ROOT_PASSWORD} +docker restart nextcloud nextcloud-db +``` + +Ensure everything runs nicely by looking at nextcloud-db and nextcloud logs, and by accessing your Nextcloud web UI. diff --git a/doc/configuration.md b/doc/configuration.md new file mode 100644 index 0000000..b90d90e --- /dev/null +++ b/doc/configuration.md @@ -0,0 +1,318 @@ +# Seedbox configuration + +## Table of content + +* [General principles](#general-principles) +* [Configuration structure and parameters](#configuration-structure-and-parameters) +* [Environment variables](#environment-variables) +* [Add your own service](#add-your-own-service) + * [Particular case: Plex with Hardware Transcoding](#particular-case-plex-with-hardware-transcoding) +* [Integration with other services (custom Traefik config)](#integration-with-other-services-custom-traefik-config) +* [Disable HTTPS completely](#disable-https-completely) +* [VPN](#vpn) + * [Default mode - Wireguard custom](#default-mode---wireguard-custom) + * [Your own mode (VPN provider supported by gluetun)](#your-own-mode-vpn-provider-supported-by-gluetun) + * [How does VPN is handled?](#how-does-vpn-is-handled) +* [Make the services communicate with each other](#make-the-services-communicate-with-each-other) +* [How does the configuration work?](#how-does-the-configuration-work) + +## General principles + +Every service (Plex, Sonarr, Jackett, Nextcloud...) is defined in a dedicated file (in docker-compose format) in the [services](../services/) directory. + +All your configuration such as: + +* Which services must be enabled +* What docker-compose file they are using if a a particular one must be applied instead of the default one (which is the one with the same name as the service) +* Routing rules (example: ``sonarr.yourdomain.com`` for Sonarr) +* If http authentication must be enabled (example: *enable* for Sonarr, *disable* for Nextcloud has it has built-in authentication) +* Some other parameters (see below) + +... is located in ``config.yaml``. If you are starting fresh, copy ``config.sample.yaml`` into ``config.yaml``. If you don't, on the first run, ``./run-seedbox.sh`` will copy the sample file for you. + +Then, all your "sensitive" (or "personal") data configuration (passwords, usernames, domain name, paths on the machine for persistent data...) is located in ``.env`` file. + +When running ``./run-seedbox.sh``: + +* ``.env`` is loaded +* ``config.yaml`` is parsed, some checks are performed +* For each service, if enabled, Traefik rules are generated ([see this section](#how-does-the-configuration-work)) dynamically +* docker-compose commands (pull, up...) are executed against all relevant files + +## Configuration structure and parameters + +Almost the whole stack can be configured by using the main configuration item: ``config.yaml``. +Here is what it looks like: + +```yaml +# List of all services +services: + # Name of the service + - name: traefik + # Flag indicating if the service will be created or not + enabled: true + # Define traefik (reverse proxy) behavior for this service + traefik: + # Enable or disable Traefik routing. For example, if your service is a DB, disable Traefik. + enabled: true + # Routing rules, which will be processed and rendered as Traefik "dynamic configuration" via file provider + rules: + # Host to match request. Any environment variable is supported here, as long as there are braces around it. + - host: traefik.${TRAEFIK_DOMAIN} + # Traefik service to match (if it is a particular one). Here the "api@internal" service is internal to Traefik (dashboard access). If not specified, a "traefik service" with the same name as the docker service will be created. + service: api@internal + # Enable http authentication + httpAuth: true + # Another service + - name: deluge + enabled: true + # Enable VPN (default to false). Service "gluetun" must be configured and enabled (with proper variables set in .env) to be able to use vpn mode on any service. + vpn: true + traefik: + enabled: true + rules: + - host: deluge.${TRAEFIK_DOMAIN} + # No service is defined here => a traefik service named "deluge" will be created automatically + httpAuth: true + # Internal container port on which we want to bind the Traefik routing + internalPort: 8112 + # Another service + - name: flaresolverr + enabled: true + # Do not use VPN (same as nothing as false is default) + vpn: false + traefik: + # This service is not reachable directly (no UI). So Traefik is disabled and rules are an empty array. + enabled: false + # Optional, won't be evaluated as Traefik is disabled + rules: [] + # Another service with 2 Traefik rules + - name: sonarr + enabled: true + vpn: false + traefik: + enabled: true + rules: + # First "regular" routing rule + - host: sonarr.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8989 + # Another rule which bypasses certificate generation using Let's Encrypt (ACME challenge). + - host: sonarr-unsecure.${TRAEFIK_DOMAIN} + httpAuth: true + internalPort: 8989 + # Using this flag, sonarr-unsecure.domain.com (for example) will be accessible ONLY via http protocol + httpOnly: true + # Another service with backend using https + - name: nextcloud + enabled: false + vpn: false + traefik: + enabled: true + rules: + - host: nextcloud.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 443 + # Specify that the routing will be on https://nextcloud:443 (internally), while by default services expose only http. + # Nextcloud is known to be an exception and exposes only port 443 with SSL + internalScheme: https +``` + +The provided ``config.sample.yaml`` is good enough to get started and will be used if no ``config.yaml`` is found. + +Some general rules: + +* In order to enable VPN (``vpn: true``) on a service, you must configure and enable gluetun service. +* By default, all services match "http://service_name:port" for routing. +* By default, when ``httpOnly`` is false or not set, service will be accessible from both http and https, but a redirection will be created from http to https. + * And when ``httpOnly`` is set to true, the service will be accessible ONLY via http, bypassing certificate generation. It is useful when you do not want Traefik to handle certificates for this service. + +## Environment variables + +Also, do not forget to edit your ``.env`` file, which is where all the data which will be sent to containers (passwords, tokens, uid for disk permission...) lives. + +## Add your own service + +Let's say you want to add a container nginx without interfering or creating conflicts in this git repository. That's possible. + +Start by creating a file named nginx.yaml in the [services/custom/](services/custom/) directory: + +```yaml +services: + nginx: + image: nginx:latest + container_name: nginx + restart: always + # ... +``` + +Then, enable it in your ``config.yaml``: + +```yaml +services: + # ... + - name: nginx + enabled: true + vpn: false + # Specify the path to your custom docker-compose file, relative to the "services" directory + customFile: custom/nginx.yaml + traefik: + enabled: true + rules: + - host: nginx.${TRAEFIK_DOMAIN} + httpAuth: false + # 80 because official nginx image uses this port + internalPort: 80 + # ... +``` + +...and you're set! Just run ``./run-seedbox.sh`` to apply configuration changes. + +> Please note that the ``customFile`` flag **MUST** be relative to the "services" directory, because in some cases, some alternatives yaml files for bundled services are provided in the services directory. See the next section for more details. + +### Particular case: Plex with Hardware Transcoding + +This project provides a custom [plex-hardware-transcoding.yaml](../services/plex-hardware-transcoding.yaml) file, with all the necessary adaptations to make Plex run with hardware transcoding enabled. + +Just add the ``customFile: plex-hardware-transcoding.yaml`` field in the ``plex`` service and this file will be used, instead of the default "plex.yaml": + +```yaml +services: + # ... + - name: plex + enabled: true + vpn: false + # Here is the change: by default, without this flag, the applied file was "plex.yaml" + customFile: plex-hardware-transcoding.yaml + traefik: + enabled: true + rules: + - host: plex.${TRAEFIK_DOMAIN} + httpAuth: false + internalPort: 32400 + # ... +``` + +Then, run ``./run-seedbox.sh`` to make these changes taken into account and the new container Plex will have hardware transcoding. + +> Note that you also have to enable Hardware Transcoding in your Plex Server settings after the container has started. + +## Integration with other services (custom Traefik config) + +You can also add you own Traefik configuration to integrate with local services on your LAN. +Just put your Traefik configuration file in the [samples/custom-traefik/](../samples/custom-traefik/) directory. +All files will be copied in the Traefik configuration directory on each ``run-seedbox`` execution. +Example: + +```yaml +http: + routers: + synology-admin: + rule: 'Host(`synology-admin.{{ env "TRAEFIK_DOMAIN" }}`)' + middlewares: + - common-auth@file + service: admin + services: + synology-admin: + loadBalancer: + servers: + - url: "https://your-nas-hostname-on-your-local-network:5001" +``` + +## Disable HTTPS completely + +If you want to handle your certificates on a firewall or another reverse proxy somewhere else on your network, it is now possible. +You just have to set ``httpOnly: true`` on all your services in ``config.yaml``. +Then, make the machine which acts as reverse proxy (and handles certificates) points on every Traefik URL with the corresponding certificate, or make a wildcard redirection, based on your reverse proxy. + +## VPN + +In order to hide a service behind a VPN, just enable ``gluetun`` service. + +By default, the file used is [gluetun.yaml](../services/gluetun.yaml), which is in "Wireguard custom" mode, meaning you must have somewhere a Wireguard server running and access to its client configuration. But you can add your own config to match your requirements. See sections below. + +### Default mode - Wireguard custom + +* Edit the ``.env`` file and replace the Wireguard variables with your own (take them in ``.env.sample``). +* Enable ``gluetun`` service. +* Enable vpn (``vpn: true``) on any service. +* Run ``./run-seedbox.sh``. +* The service now uses Wireguard. If gluetun is down or if the VPN link is broken, your service won't have any access to Internet. + +### Your own mode (VPN provider supported by gluetun) + +* Create a ``gluetun-custom.yaml`` in the [services/custom/](../services/custom/) directory. You can duplicate [this one](../services/gluetun.yaml) to avoid starting from scratch. +* Adapt it to your needs (variables, mode...) according to your provider. + * Add all variables you may need (used in your custom yaml file) in your ``.env`` file (replacing the wireguard ones). +* Edit your ``config.yaml`` and add ``customFile: custom/gluetun-custom.yaml`` in the ``gluetun`` section. +* Enable vpn (``vpn: true``) on any service. +* Run ``./run-seedbox.sh``. +* The service now uses your VPN by tunneling via gluetun container. If gluetun is down or if the VPN link is broken, your service won't have any access to Internet. + +### How does VPN is handled? + +Behind the scenes, the ``run-seedbox.sh`` script will mainly add 2 overrides when enabling VPN on a service: + +* Adds a file in [services/generated/](../services/generated/) which adds a ``network_mode: gluetun`` for your service. +* Specify in Traefik rule that the backend host is gluetun instead of the service directly. + +## Make the services communicate with each other + +With docker-compose, all services are in the same Docker network (it is called ``traefik-network`` and is defined [here](../docker-compose.yaml)). Docker provides DNS resolution in the same network based on the name of the services, which act as hostnames. + +So, for example, in order to setup Deluge in Sonarr, just add ``http://deluge:8112`` in the Download Clients settings section in Sonarr. + +⚠️ If you are trying to contact a container which has ``vpn`` flag enabled, you will have to point your config to ``gluetun`` instead, which acts as relay to contact the service. So if Deluge is behind the VPN, add ``http://gluetun:8112`` in Sonarr instead. + +## How does the configuration work? + +Behind the scenes, the ``run-seedbox.sh`` script will parse your ``config.yaml`` file and will generate a Traefik dynamic configuration file, which looks like this: + +```yaml +http: + routers: + deluge-1: + rule: 'Host(`deluge.{{ env "TRAEFIK_DOMAIN" }}`)' + middlewares: + - common-auth@file + - redirect-to-https + service: deluge-1 + sonarr-1: + rule: 'Host(`sonarr.{{ env "TRAEFIK_DOMAIN" }}`)' + middlewares: + - common-auth@file + - redirect-to-https + service: sonarr-1 + sonarr-2: + rule: 'Host(`sonarr-unsecure.{{ env "TRAEFIK_DOMAIN" }}`)' + middlewares: + - common-auth@file + service: sonarr-2 + entryPoints: + - insecure + nextcloud: + rule: 'Host(`nextcloud.{{ env "TRAEFIK_DOMAIN" }}`)' + middlewares: + - redirect-to-https + service: nextcloud-1 + services: + deluge-1: + loadBalancer: + servers: + # Gluetun is automatically set by run-seedbox.sh (instead of "deluge") because vpn was enabled on this service + - url: "http://gluetun:8112" + sonarr-1: + loadBalancer: + servers: + - url: "http://sonarr:8989" + sonarr-2: + loadBalancer: + servers: + - url: "http://sonarr:8989" + nextcloud-1: + loadBalancer: + servers: + - url: "https://nextcloud:443" +``` + +This file will be automatically placed in [traefik/custom/](../traefik/custom/) directory (mounted by Traefik container) so the config will dynamically apply. This file is updated on each ``run-seedbox.sh`` execution. \ No newline at end of file diff --git a/doc/traefik_v2.md b/doc/traefik_v2.md new file mode 100644 index 0000000..3b00b4f --- /dev/null +++ b/doc/traefik_v2.md @@ -0,0 +1,28 @@ +# September 2020 - Upgrade to Traefik v2 instructions + +> This guide is useful if you already are using the seedbox but did not update before September 2020. + +Before upgrading Traefik to version 2, please check the following: + +- In this repo, Traefik v2 upgrade is as seamless as possible (same environment variables than before, out-of-the-box config file...). +- **First, ``git pull`` to grab the latest code.** +- The ``HTTP_PASSWORD`` variable now must be simple-quoted in the .env file. See the updated ``.env.sample`` file (which has also been reorganized) +- Run ``init.sh`` in order to create required Docker objects (network name has changed). +- You can update your acme.json to a Traefik v2-compliant one by doing the following (before launching Traefik v2): + +```sh +mkdir -p /tmp/migration +cd /tmp/migration +sudo cp /opt/traefik/acme.json . +sudo chmod 775 /tmp/migration/acme.json +# Do *NOT* forget the --resolver at the end! (le = Let's Encrypt resolver, see traefik/traefik.yml) +docker run --rm -v ${PWD}:/data -w /data containous/traefik-migration-tool acme -i acme.json -o acme2.json --resolver le +mkdir -p /data/config/traefik +sudo cp acme2.json /data/config/traefik/acme.json +sudo chmod 600 /data/config/traefik/acme.json +# When you already have a backup! +sudo rm -rf /opt/traefik /tmp/migration +``` + +- As from Traefik v2, as Http Authentication is now possible on the Traefik console, the latter is enabled at ``traefik.yourdomain.com``. +- After all this, you can simply do: ``./update-all.sh``! Voilà! diff --git a/docker-compose.yaml b/docker-compose.yaml index 9d62242..97e8dcb 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -6,21 +6,20 @@ version: "3.8" # Common network used by all services networks: - default: - external: - name: "traefik-network" + default: + name: "traefik-network" # Common volumes used by at least 2 services volumes: config: driver: local-persist driver_opts: - mountpoint: /data/config + mountpoint: $HOST_CONFIG_PATH torrents: driver: local-persist driver_opts: - mountpoint: /data/torrents + mountpoint: $HOST_MEDIA_PATH downloads: driver: local-persist driver_opts: - mountpoint: /data/torrents/deluge + mountpoint: $HOST_MEDIA_PATH/$DOWNLOAD_SUBFOLDER diff --git a/run-seedbox.sh b/run-seedbox.sh new file mode 100755 index 0000000..bddd2e4 --- /dev/null +++ b/run-seedbox.sh @@ -0,0 +1,286 @@ +#!/bin/bash + +set -e + +# Load common functions +source config/tools.sh + +# Check that required tools are installed +check_utilities + +SKIP_PULL=0 +DEBUG=0 + +for i in "$@"; do + case $i in + --no-pull) + SKIP_PULL=1 + ;; + --debug) + DEBUG=1 + ;; + *) + echo "[$0] ❌ ERROR: unknown parameter \"$i\"" + exit 1 + ;; + esac +done + +cleanup_on_exit() { + rm -f rules.props *-vpn.props config.json +} +trap cleanup_on_exit EXIT + +echo-debug() { + if [[ ${DEBUG} == "1" ]]; then echo "$@"; fi +} + +############################################################################################### +####################################### Load variables ######################################## +############################################################################################### + +echo "[$0] ***** Checking environment variables and files... *****" + +if [[ ! -f .env ]]; then + echo "[$0] ERROR. \".env\" file not found. Please copy \".env.sample\" and edit its values. Then, re-run this script." + exit 1 +fi + +# Create/update http_auth file according to values in .env file +source .env +echo "${HTTP_USER}:${HTTP_PASSWORD}" > traefik/http_auth + +# Docker-compose settings +export COMPOSE_HTTP_TIMEOUT=240 + +# Retro-compatibility +[[ -z $HOST_CONFIG_PATH ]] && export HOST_CONFIG_PATH="/data/config" +[[ -z $HOST_MEDIA_PATH ]] && export HOST_MEDIA_PATH="/data/torrents" +[[ -z $DOWNLOAD_SUBFOLDER ]] && export DOWNLOAD_SUBFOLDER="deluge" + +if [[ ! -f config.yaml ]]; then + echo "[$0] No config.yaml file found. Copying from sample file..." + cp config.sample.yaml config.yaml +fi + +############################################################################################### +###################################### Pre-flight checks ###################################### +############################################################################################### + +echo "[$0] ***** Checking configuration... *****" + +yq eval -o json config.yaml > config.json + +if [[ ${CHECK_FOR_OUTDATED_CONFIG} == true ]]; then + nb_services=$(cat config.json | jq '.services | length') + nb_services_sample=$(yq eval -o json config.sample.yaml | jq '.services | length') + if [[ $nb_services_sample -gt $nb_services ]]; then + echo "[$0] There are more services in the config.sample.yaml than in your config.yaml" + echo "[$0] You should check config.sample.yaml because it seems there are new services available for you:" + diff -u config.yaml config.sample.yaml | grep "name:" | grep -E "^\+" || true + fi +fi + +# Check if some services have vpn enabled, that gluetun itself is enabled +nb_vpn=$(cat config.json | jq '[.services[] | select(.enabled==true and .vpn==true)] | length') +gluetun_enabled=$(cat config.json | jq '[.services[] | select(.name=="gluetun" and .enabled==true)] | length') +if [[ ${nb_vpn} -gt 0 && ${gluetun_enabled} == 0 ]]; then + echo "[$0] ERROR. ${nb_vpn} VPN-enabled services have been enabled BUT gluetun has not been enabled. Please check your config.yaml file." + echo "[$0] ******* Exiting *******" + exit 1 +fi + +# Determine what host Flood should connect to +# => If deluge vpn is enabled => gluetun +# => If deluge vpn is disabled => deluge +if [[ $(cat config.json | jq '[.services[] | select(.name=="flood" and .enabled==true)] | length') -eq 1 ]]; then + # Check that if flood is enabled, deluge should also be enabled + if [[ $(cat config.json | jq '[.services[] | select(.name=="deluge" and .enabled==false)] | length') -eq 1 ]]; then + echo "[$0] ERROR. Flood is enabled but Deluge is not. Please either enable Deluge or disable Flood as Flood depends on Deluge." + echo "[$0] ******* Exiting *******" + exit 1 + fi + # Determine deluge hostname (for flood) based on the VPN status (enabled or not) of deluge + if [[ $(cat config.json | jq '[.services[] | select(.name=="deluge" and .enabled==true and .vpn==true)] | length') -eq 1 ]]; then + export DELUGE_HOST="gluetun" + elif [[ $(cat config.json | jq '[.services[] | select(.name=="deluge" and .enabled==true and .vpn==false)] | length') -eq 1 ]]; then + export DELUGE_HOST="deluge" + fi + + # Specific instructions for Flood + # User for Deluge daemon RPC has to be created in deluge auth config file + if [[ ! -z ${FLOOD_PASSWORD} && ${FLOOD_AUTOCREATE_USER_IN_DELUGE_DAEMON} == true ]]; then + if ! grep -q "flood" $HOST_CONFIG_PATH/deluge/auth; then + echo "flood:${FLOOD_PASSWORD}:10" >> $HOST_CONFIG_PATH/deluge/auth + else + echo "[$0] No need to add user/password for flood as it has already been created." + echo "[$0] Consider setting FLOOD_AUTOCREATE_USER_IN_DELUGE_DAEMON variable to false in .env file." + fi + fi +fi + +# Apply other arbitrary custom Traefik config files +rm -f $f traefik/custom/custom-* +for f in `find samples/custom-traefik -maxdepth 1 -mindepth 1 -type f | grep -E "\.yml$|\.yaml$" | sort`; do + echo "[$0] Applying custom Traefik config $f..." + cp $f traefik/custom/custom-$(basename $f) +done + +# Detect Synology devices for Netdata compatibility +if [[ $(cat config.json | jq '[.services[] | select(.name=="netdata" and .enabled==true)] | length') -eq 1 ]]; then + if [[ $(uname -a | { grep synology || true; } | wc -l) -eq 1 ]]; then + export OS_RELEASE_FILEPATH="/etc/VERSION" + else + export OS_RELEASE_FILEPATH="/etc/os-release" + fi +fi + +############################################################################################### +####################################### SERVICES PARSING ###################################### +############################################################################################### + +echo "[$0] ***** Generating configuration... *****" + +# Cleanup files before start, in case there was a change we start from scratch at every script execution +rm -f services/generated/*-vpn.yaml + +ALL_SERVICES="-f docker-compose.yaml" + +# Parse the config.yaml master configuration file +for json in $(yq eval -o json config.yaml | jq -c ".services[]"); do + name=$(echo $json | jq -r .name) + enabled=$(echo $json | jq -r .enabled) + vpn=$(echo $json | jq -r .vpn) + + # Skip disabled services + if [[ ${enabled} == "false" ]]; then + echo-debug "[$0] Service $name is disabled. Skipping it." + continue + fi + + echo-debug "[$0] ➡️ Parsing service: \"$name\"..." + + # Default docker-compose filename is the service name + .yaml. + # Take into account explicit filename if specified in config + customFile=$(echo $json | jq -r .customFile) + file="$name.yaml" + if [[ ${customFile} != "null" ]]; then + file=${customFile} + fi + echo-debug "[$0] File: \"$file\"..." + + # Append $file to global list of files which will be passed to docker commands + ALL_SERVICES="${ALL_SERVICES} -f services/${file}" + + # For services with VPN enabled, add a docker-compose "override" file specifying that the service network should + # go through gluetun (main vpn client service). + if [[ ${vpn} == "true" ]]; then + echo "services.${name}.network_mode: service:gluetun" > ${name}-vpn.props + yq -p=props ${name}-vpn.props > services/generated/${name}-vpn.yaml + rm -f ${name}-vpn.props + # Append config/${name}-vpn.yaml to global list of files which will be passed to docker commands + ALL_SERVICES="${ALL_SERVICES} -f services/generated/${name}-vpn.yaml" + fi + + ###################################### TRAEFIK RULES ###################################### + + # Skip this part for services which have Traefik rules disabled in config + traefikEnabled=$(echo $json | jq -r .traefik.enabled) + if [[ ${traefikEnabled} == "false" ]]; then + echo-debug "[$0] Traefik is disabled. Skipping rules creation..." + continue + fi + + # Loop over all Traefik rules and create the corresponding entries in the generated rules.yaml + echo-debug "[$0] Generating Traefik rules..." + i=0 + for rule in $(echo $json | jq -c .traefik.rules[]); do + ((i=i+1)) + host=$(echo $rule | jq -r .host) + internalPort=$(echo $rule | jq -r .internalPort) + httpAuth=$(echo $rule | jq -r .httpAuth) + echo-debug "[$0] Host => ${host}" + echo-debug "[$0] Internal Port => ${internalPort}" + echo-debug "[$0] Http Authentication => ${httpAuth}" + + # If VPN => Traefik rule should redirect to gluetun container + backendHost=${name} + [[ ${vpn} == "true" ]] && backendHost="gluetun" + + # Handle custom scheme (default if non-specified is http) + internalScheme="http" + customInternalScheme=$(echo $rule | jq -r .internalScheme) + [[ ${customInternalScheme} != "null" ]] && internalScheme=${customInternalScheme} + + # Transform the bash syntax into Traefik/go one => anything.${TRAEFIK_DOMAIN} to anything.{{ env "TRAEFIK_DOMAIN" }} + hostTraefik=$(echo ${host} | sed --regexp-extended 's/^(.*)(\$\{(.*)\})/\1\{\{ env "\3" \}\}/') + + ruleId="${name}-${i}" + echo 'http.routers.'"${ruleId}"'.rule: Host(`'${hostTraefik}'`)' >> rules.props + + middlewareCount=0 + if [[ ${httpAuth} == "true" ]]; then + echo "http.routers.${ruleId}.middlewares.${middlewareCount}: common-auth@file" >> rules.props + ((middlewareCount=middlewareCount+1)) + fi + + traefikService=$(echo $rule | jq -r .service) + if [[ ${traefikService} != "null" ]]; then + echo "http.routers.${ruleId}.service: ${traefikService}" >> rules.props + else + echo "http.routers.${ruleId}.service: ${ruleId}" >> rules.props + fi + + # Check if httpOnly flag is enabled + # If enabled => Specify to use only "insecure" (port 80) entrypoint + # If not => use all entryPoints (by not specifying any) but force redirection to https + httpOnly=$(echo $rule | jq -r .httpOnly) + if [[ ${httpOnly} == true ]]; then + echo "http.routers.${ruleId}.entryPoints.0: insecure" >> rules.props + else + echo "http.routers.${ruleId}.middlewares.${middlewareCount}: redirect-to-https" >> rules.props + ((middlewareCount=middlewareCount+1)) + fi + + # If the specified service does not contain a "@" => we create it + # If the service has a @, it means it is defined elsewhere so we do not create it (custom file, @internal...) + if echo ${traefikService} | grep -vq "@"; then + echo "http.services.${ruleId}.loadBalancer.servers.0.url: ${internalScheme}://${backendHost}:${internalPort}" >> rules.props + fi + + done +done + +# Convert properties files into Traefik-ready YAML and place it in the correct folder loaded by Traefik +mv traefik/custom/dynamic-rules.yaml traefik/custom/dynamic-rules-old.yaml || true +yq -p=props rules.props > traefik/custom/dynamic-rules.yaml +rm -f rules.props + +# Post-transformations on the rules file +# sed -i "s/EMPTYMAP/{}/g" traefik/custom/dynamic-rules.yaml +# Add simple quotes around Host rule +sed -i --regexp-extended "s/^(.*: )(Host.*$)/\1'\2'/g" traefik/custom/dynamic-rules.yaml +# Add double quotes around the backend traefik service +sed -i --regexp-extended "s/^(.*url: )(.*$)/\1\"\2\"/g" traefik/custom/dynamic-rules.yaml + +rm -f traefik/custom/dynamic-rules-old.yaml + +echo-debug "[$0] Here is the list of all files which are going to be processed: ${ALL_SERVICES}" + +echo "[$0] ***** Config OK. Launching services... *****" + +if [[ "${SKIP_PULL}" != "1" ]]; then + echo "[$0] ***** Pulling all images... *****" + docker-compose ${ALL_SERVICES} pull +fi + +echo "[$0] ***** Recreating containers if required... *****" +docker-compose ${ALL_SERVICES} up -d --remove-orphans +echo "[$0] ***** Done updating containers *****" + +echo "[$0] ***** Clean unused images and volumes... *****" +docker image prune -af +docker volume prune -f + +echo "[$0] ***** Done! *****" +exit 0 \ No newline at end of file diff --git a/samples/custom-traefik/README.md b/samples/custom-traefik/README.md new file mode 100644 index 0000000..60eebd1 --- /dev/null +++ b/samples/custom-traefik/README.md @@ -0,0 +1,3 @@ +# Custom Traefik config files + +Place in this directory any custom Traefik config file, they will be copied to Traefik folder when running ``run-seedbox.sh`` script. diff --git a/services.conf.sample b/services.conf.sample deleted file mode 100644 index 3d4078d..0000000 --- a/services.conf.sample +++ /dev/null @@ -1,19 +0,0 @@ -deluge: enable -flood: enable -plex: enable -flaresolverr: enable -jackett: enable -prowlarr: enable -sonarr: enable -radarr: enable -bazarr: enable -lidarr: enable -ombi: disable -overseerr: enable -tautulli: enable -jdownloader: enable -tdarr: enable -nextcloud: enable -portainer: enable -netdata: enable -duplicati: enable \ No newline at end of file diff --git a/services/bazarr.yaml b/services/bazarr.yaml old mode 100644 new mode 100755 index 568ad3d..b543402 --- a/services/bazarr.yaml +++ b/services/bazarr.yaml @@ -10,13 +10,9 @@ services: - PGID=${PGID} - PUID=${PUID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.routers.bazarr.rule=Host(`bazarr.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.bazarr.middlewares=common-auth@file" volumes: configbazarr: driver: local-persist driver_opts: - mountpoint: /data/config/bazarr \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/bazarr \ No newline at end of file diff --git a/services/custom/README.md b/services/custom/README.md new file mode 100644 index 0000000..c1252f2 --- /dev/null +++ b/services/custom/README.md @@ -0,0 +1,4 @@ +# Services custom folder + +Here, you can place all custom docker-compose files (yaml format) which will be specified in your ``config.yaml``. +All YAML files placed here are ignored in .gitignore. diff --git a/services/deluge.yaml b/services/deluge.yaml old mode 100644 new mode 100755 index d304ae3..21244aa --- a/services/deluge.yaml +++ b/services/deluge.yaml @@ -11,13 +11,9 @@ services: - PGID=${PGID} - PUID=${PUID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.routers.deluge.rule=Host(`deluge.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.deluge.middlewares=common-auth@file" volumes: configdeluge: driver: local-persist driver_opts: - mountpoint: /data/config/deluge \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/deluge \ No newline at end of file diff --git a/services/duplicati.yaml b/services/duplicati.yaml old mode 100644 new mode 100755 index ce6aef0..f2c24d3 --- a/services/duplicati.yaml +++ b/services/duplicati.yaml @@ -10,22 +10,14 @@ services: volumes: - configduplicati:/config - backups:/backups - - alldata:/source - labels: - - "traefik.enable=true" - - "traefik.http.routers.duplicati.rule=Host(`duplicati.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.duplicati.middlewares=common-auth@file" + - config:/source volumes: - alldata: - driver: local-persist - driver_opts: - mountpoint: /data configduplicati: driver: local-persist driver_opts: - mountpoint: /data/config/duplicati + mountpoint: $HOST_CONFIG_PATH/duplicati backups: driver: local-persist driver_opts: - mountpoint: /data/backups \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/backups \ No newline at end of file diff --git a/services/flaresolverr.yaml b/services/flaresolverr.yaml old mode 100644 new mode 100755 diff --git a/services/flood.yaml b/services/flood.yaml old mode 100644 new mode 100755 index 8a89089..aa672c8 --- a/services/flood.yaml +++ b/services/flood.yaml @@ -8,7 +8,7 @@ services: user: ${PUID}:${PGID} command: - --auth=none - - --dehost=deluge + - --dehost=${DELUGE_HOST} - --deport=58846 - --deuser=flood - --depass=${FLOOD_PASSWORD} @@ -18,15 +18,9 @@ services: - torrents:/torrents - downloads:/downloads - /etc/localtime:/etc/localtime:ro - labels: - - "traefik.enable=true" - - "traefik.http.routers.flood.rule=Host(`flood.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.flood.middlewares=common-auth@file" - - "traefik.http.routers.flood.service=flood-service" - - "traefik.http.services.flood-service.loadbalancer.server.port=3000" volumes: configflood: driver: local-persist driver_opts: - mountpoint: /data/config/flood \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/flood \ No newline at end of file diff --git a/services/generated/README.md b/services/generated/README.md new file mode 100644 index 0000000..b2d4f84 --- /dev/null +++ b/services/generated/README.md @@ -0,0 +1,3 @@ +# Generated files + +This directory contains all generated overrides files. They are in .gitignore so there should be no conflict when running ``git pull``. diff --git a/services/gluetun.yaml b/services/gluetun.yaml new file mode 100755 index 0000000..ab02491 --- /dev/null +++ b/services/gluetun.yaml @@ -0,0 +1,25 @@ +services: + gluetun: + image: qmcgaw/gluetun + container_name: gluetun + restart: always + cap_add: + - NET_ADMIN + environment: + - PUID=${PUID} + - PGIDq=${PGID} + - TZ=${TZ} + - VPNSP=custom + - VPN_TYPE=wireguard + # For Wireguard + - VPN_ENDPOINT_IP=${WIREGUARD_ENDPOINT} + - VPN_ENDPOINT_PORT=${WIREGUARD_PORT} + - WIREGUARD_PUBLIC_KEY=${WIREGUARD_PUBLIC_KEY} + - WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY} + - WIREGUARD_ADDRESS=${WIREGUARD_ADDRESS} + +volumes: + configgluetun: + driver: local-persist + driver_opts: + mountpoint: $HOST_CONFIG_PATH/gluetun \ No newline at end of file diff --git a/services/heimdall.yaml b/services/heimdall.yaml new file mode 100644 index 0000000..b059aba --- /dev/null +++ b/services/heimdall.yaml @@ -0,0 +1,17 @@ +services: + heimdall: + image: lscr.io/linuxserver/heimdall + container_name: heimdall + restart: always + volumes: + - configheimdall:/config + environment: + - PGID=${PGID} + - PUID=${PUID} + - TZ=${TZ} + +volumes: + configheimdall: + driver: local-persist + driver_opts: + mountpoint: $HOST_CONFIG_PATH/heimdall \ No newline at end of file diff --git a/services/jackett.yaml b/services/jackett.yaml old mode 100644 new mode 100755 index ca3b1f8..c6c3f44 --- a/services/jackett.yaml +++ b/services/jackett.yaml @@ -12,7 +12,3 @@ services: - PUID=${PUID} - TZ=${TZ} - RUN_OPTS='-FlareSolverrURL="http://flaresolverr:8191"' - labels: - - "traefik.enable=true" - - "traefik.http.routers.jackett.rule=Host(`jackett.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.jackett.middlewares=common-auth@file" diff --git a/services/jdownloader.yaml b/services/jdownloader.yaml old mode 100644 new mode 100755 index 4850c36..b9b7dc2 --- a/services/jdownloader.yaml +++ b/services/jdownloader.yaml @@ -10,14 +10,9 @@ services: - USER_ID=${PUID} - GROUP_ID=${PGID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.services.jdownloader-seedbox.loadbalancer.server.port=5800" - - "traefik.http.routers.jdownloader.rule=Host(`jdownloader.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.jdownloader.middlewares=common-auth@file" volumes: configjdownloader: driver: local-persist driver_opts: - mountpoint: /data/config/jdownloader \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/jdownloader \ No newline at end of file diff --git a/services/kavita.yaml b/services/kavita.yaml new file mode 100755 index 0000000..8b12b9e --- /dev/null +++ b/services/kavita.yaml @@ -0,0 +1,19 @@ +services: + kavita: + image: kizaing/kavita:latest + container_name: kavita + restart: always + volumes: + - configkavita:/kavita/config + - torrents:/torrents + - /etc/localtime:/etc/localtime:ro + environment: + - TZ=${TZ} + # Wait for https://github.com/Kareadita/Kavita/issues/301 to be resolved + #user: "${PUID}:${PGID}" + +volumes: + configkavita: + driver: local-persist + driver_opts: + mountpoint: $HOST_CONFIG_PATH/kavita \ No newline at end of file diff --git a/services/komga.yaml b/services/komga.yaml new file mode 100755 index 0000000..c4945fa --- /dev/null +++ b/services/komga.yaml @@ -0,0 +1,18 @@ +services: + komga: + image: gotson/komga + container_name: komga + restart: always + volumes: + - configkomga:/config + - torrents:/torrents + - /etc/localtime:/etc/localtime:ro + environment: + - TZ=${TZ} + user: "${PUID}:${PGID}" + +volumes: + configkomga: + driver: local-persist + driver_opts: + mountpoint: $HOST_CONFIG_PATH/komga \ No newline at end of file diff --git a/services/lidarr.yaml b/services/lidarr.yaml old mode 100644 new mode 100755 index d13b01f..87242c1 --- a/services/lidarr.yaml +++ b/services/lidarr.yaml @@ -10,13 +10,9 @@ services: - PGID=${PGID} - PUID=${PUID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.routers.lidarr.rule=Host(`lidarr.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.lidarr.middlewares=common-auth@file" volumes: configlidarr: driver: local-persist driver_opts: - mountpoint: /data/config/lidarr \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/lidarr \ No newline at end of file diff --git a/services/netdata.yaml b/services/netdata.yaml old mode 100644 new mode 100755 index bc118c6..3d64f3a --- a/services/netdata.yaml +++ b/services/netdata.yaml @@ -15,9 +15,5 @@ services: - /sys:/host/sys:ro - /etc/passwd:/host/etc/passwd:ro - /etc/group:/host/etc/group:ro - - /etc/os-release:/host/etc/os-release:ro + - ${OS_RELEASE_FILEPATH}:/host/etc/os-release:ro - /var/run/docker.sock:/var/run/docker.sock:ro - labels: - - "traefik.enable=true" - - "traefik.http.routers.netdata.rule=Host(`netdata.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.netdata.middlewares=common-auth@file" \ No newline at end of file diff --git a/services/nextcloud.yaml b/services/nextcloud.yaml old mode 100644 new mode 100755 index 094054f..f45253f --- a/services/nextcloud.yaml +++ b/services/nextcloud.yaml @@ -3,6 +3,7 @@ services: image: mariadb:10 container_name: nextcloud-db command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1 --skip-innodb-read-only-compressed + user: ${PUID}:${PGID} restart: always environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} @@ -31,22 +32,17 @@ services: - nextclouddata:/data - torrents:/torrents - config:/seedbox-config - labels: - - "traefik.enable=true" - - "traefik.http.routers.nextcloud.rule=Host(`nextcloud.${TRAEFIK_DOMAIN}`)" - - "traefik.http.services.nextcloud-seedbox.loadbalancer.server.scheme=https" - - "traefik.http.services.nextcloud-seedbox.loadbalancer.server.port=443" volumes: nextclouddb: driver: local-persist driver_opts: - mountpoint: /data/nextcloud-db + mountpoint: $HOST_CONFIG_PATH/nextcloud-db confignextcloud: driver: local-persist driver_opts: - mountpoint: /data/config/nextcloud + mountpoint: $HOST_CONFIG_PATH/nextcloud nextclouddata: driver: local-persist driver_opts: - mountpoint: /data/config/nextcloud-data \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/nextcloud-data \ No newline at end of file diff --git a/services/ombi.yaml b/services/ombi.yaml old mode 100644 new mode 100755 index ab41549..15f9f21 --- a/services/ombi.yaml +++ b/services/ombi.yaml @@ -10,13 +10,9 @@ services: - PUID=${PUID} - TZ=${TZ} - BASE_URL=/ - labels: - - "traefik.enable=true" - - "traefik.http.routers.ombi.rule=Host(`ombi.${TRAEFIK_DOMAIN}`)" - #- "traefik.http.routers.ombi.middlewares=common-auth@file" volumes: configombi: driver: local-persist driver_opts: - mountpoint: /data/config/ombi \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/ombi \ No newline at end of file diff --git a/services/overseerr.yaml b/services/overseerr.yaml old mode 100644 new mode 100755 index 0c9a0bb..2ed8948 --- a/services/overseerr.yaml +++ b/services/overseerr.yaml @@ -9,12 +9,9 @@ services: - PGID=${PGID} - PUID=${PUID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.routers.overseerr.rule=Host(`overseerr.${TRAEFIK_DOMAIN}`)" volumes: configoverseerr: driver: local-persist driver_opts: - mountpoint: /data/config/overseerr \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/overseerr \ No newline at end of file diff --git a/services/plex-hardware-transcoding.yaml b/services/plex-hardware-transcoding.yaml new file mode 100755 index 0000000..7d8b671 --- /dev/null +++ b/services/plex-hardware-transcoding.yaml @@ -0,0 +1,27 @@ +services: + plex: + image: ghcr.io/linuxserver/plex + container_name: plex + restart: always + ports: + - "32400:32400" + - "32400:32400/udp" + - "32469:32469" + - "32469:32469/udp" + devices: + - /dev/dri:/dev/dri # for hardware transcoding + volumes: + - configplex:/config + - torrents:/torrents + - /dev/shm:/transcode + environment: + - PGID=${PGID} + - PUID=${PUID} + - TZ=${TZ} + - VERSION=latest + +volumes: + configplex: + driver: local-persist + driver_opts: + mountpoint: $HOST_CONFIG_PATH/Plex \ No newline at end of file diff --git a/services/plex.yaml b/services/plex.yaml old mode 100644 new mode 100755 index 33d1b5c..bd66677 --- a/services/plex.yaml +++ b/services/plex.yaml @@ -8,8 +8,6 @@ services: - "32400:32400/udp" - "32469:32469" - "32469:32469/udp" - - "5353:5353/udp" - - "1900:1900/udp" volumes: - configplex:/config - torrents:/torrents @@ -18,13 +16,9 @@ services: - PUID=${PUID} - TZ=${TZ} - VERSION=latest - labels: - - "traefik.enable=true" - - "traefik.http.services.plex-seedbox.loadbalancer.server.port=32400" - - "traefik.http.routers.plex.rule=Host(`plex.${TRAEFIK_DOMAIN}`)" volumes: configplex: driver: local-persist driver_opts: - mountpoint: /data/config/Plex \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/Plex \ No newline at end of file diff --git a/services/portainer.yaml b/services/portainer.yaml old mode 100644 new mode 100755 index a9da06f..493692c --- a/services/portainer.yaml +++ b/services/portainer.yaml @@ -5,8 +5,4 @@ services: restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock - command: --admin-password ${PORTAINER_ADMIN_PASSWORD} --host=unix:///var/run/docker.sock - labels: - - "traefik.enable=true" - - "traefik.http.routers.portainer.rule=Host(`portainer.${TRAEFIK_DOMAIN}`)" - - "traefik.http.services.portainer-seedbox.loadbalancer.server.port=9000" \ No newline at end of file + command: --admin-password ${PORTAINER_ADMIN_PASSWORD} --host=unix:///var/run/docker.sock \ No newline at end of file diff --git a/services/prowlarr.yaml b/services/prowlarr.yaml old mode 100644 new mode 100755 index 9c2f910..5ec3dc4 --- a/services/prowlarr.yaml +++ b/services/prowlarr.yaml @@ -9,13 +9,9 @@ services: - PGID=${PGID} - PUID=${PUID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.routers.prowlarr.rule=Host(`prowlarr.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.prowlarr.middlewares=common-auth@file" volumes: configprowlarr: driver: local-persist driver_opts: - mountpoint: /data/config/prowlarr \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/prowlarr \ No newline at end of file diff --git a/services/radarr.yaml b/services/radarr.yaml old mode 100644 new mode 100755 index 65fc73d..a151a40 --- a/services/radarr.yaml +++ b/services/radarr.yaml @@ -11,13 +11,9 @@ services: - PGID=${PGID} - PUID=${PUID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.routers.radarr.rule=Host(`radarr.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.radarr.middlewares=common-auth@file" volumes: configradarr: driver: local-persist driver_opts: - mountpoint: /data/config/radarr \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/radarr \ No newline at end of file diff --git a/services/readarr.yaml b/services/readarr.yaml new file mode 100755 index 0000000..8461025 --- /dev/null +++ b/services/readarr.yaml @@ -0,0 +1,19 @@ +services: + readarr: + image: lscr.io/linuxserver/readarr:nightly + container_name: readarr + restart: always + volumes: + - configreadarr:/config + - torrents:/torrents + - /etc/localtime:/etc/localtime:ro + environment: + - PGID=${PGID} + - PUID=${PUID} + - TZ=${TZ} + +volumes: + configreadarr: + driver: local-persist + driver_opts: + mountpoint: $HOST_CONFIG_PATH/readarr \ No newline at end of file diff --git a/services/sonarr.yaml b/services/sonarr.yaml old mode 100644 new mode 100755 index 6ce4d6f..1526db6 --- a/services/sonarr.yaml +++ b/services/sonarr.yaml @@ -11,13 +11,9 @@ services: - PGID=${PGID} - PUID=${PUID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.routers.sonarr.rule=Host(`sonarr.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.sonarr.middlewares=common-auth@file" volumes: configsonarr: driver: local-persist driver_opts: - mountpoint: /data/config/sonarr \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/sonarr \ No newline at end of file diff --git a/services/syncthing.yaml b/services/syncthing.yaml new file mode 100644 index 0000000..d69766c --- /dev/null +++ b/services/syncthing.yaml @@ -0,0 +1,24 @@ +services: + syncthing: + image: lscr.io/linuxserver/syncthing + container_name: syncthing + restart: unless-stopped + environment: + - PGID=${PGID} + - PUID=${PUID} + - TZ=${TZ} + volumes: + - configsyncthing:/config + - torrents:/torrents + - config:/allconfig + ports: + # #- 8384:8384 + - 22000:22000/tcp + - 22000:22000/udp + - 21027:21027/udp + +volumes: + configsyncthing: + driver: local-persist + driver_opts: + mountpoint: $HOST_CONFIG_PATH/configsyncthing \ No newline at end of file diff --git a/services/tautulli.yaml b/services/tautulli.yaml old mode 100644 new mode 100755 index 5470396..0f02d81 --- a/services/tautulli.yaml +++ b/services/tautulli.yaml @@ -10,12 +10,9 @@ services: - PGID=${PGID} - PUID=${PUID} - TZ=${TZ} - labels: - - "traefik.enable=true" - - "traefik.http.routers.tautulli.rule=Host(`tautulli.${TRAEFIK_DOMAIN}`)" volumes: configtautulli: driver: local-persist driver_opts: - mountpoint: /data/config/tautulli \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/tautulli \ No newline at end of file diff --git a/services/tdarr.yaml b/services/tdarr.yaml old mode 100644 new mode 100755 index d5ddffc..7dd179b --- a/services/tdarr.yaml +++ b/services/tdarr.yaml @@ -15,11 +15,6 @@ services: - transcodes:/temp - configtdarrv2:/app/server - settingstdarrv2:/app/configs - labels: - - "traefik.enable=true" - - "traefik.http.services.tdarrv2-seedbox.loadbalancer.server.port=8265" - - "traefik.http.routers.tdarrv2.rule=Host(`tdarr.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.tdarrv2.middlewares=common-auth@file" tdarr_node: image: haveagitgat/tdarr_node:latest @@ -45,12 +40,12 @@ volumes: configtdarrv2: driver: local-persist driver_opts: - mountpoint: /data/config/tdarrv2/server + mountpoint: $HOST_CONFIG_PATH/tdarrv2/server settingstdarrv2: driver: local-persist driver_opts: - mountpoint: /data/config/tdarrv2/configs + mountpoint: $HOST_CONFIG_PATH/tdarrv2/configs transcodes: driver: local-persist driver_opts: - mountpoint: /data/config/tdarrv2/transcodes \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/tdarrv2/transcodes \ No newline at end of file diff --git a/services/traefik.yaml b/services/traefik.yaml old mode 100644 new mode 100755 index d216921..b454ec1 --- a/services/traefik.yaml +++ b/services/traefik.yaml @@ -16,15 +16,9 @@ services: environment: - TRAEFIK_DOMAIN=${TRAEFIK_DOMAIN} - TZ=${TZ} - labels: - - "traefik.enable=true" - # Docker labels for enabling Traefik dashboard - - "traefik.http.routers.traefik.rule=Host(`traefik.${TRAEFIK_DOMAIN}`)" - - "traefik.http.routers.traefik.service=api@internal" - - "traefik.http.routers.traefik.middlewares=common-auth@file" volumes: configtraefik: driver: local-persist driver_opts: - mountpoint: /data/config/traefik \ No newline at end of file + mountpoint: $HOST_CONFIG_PATH/traefik \ No newline at end of file diff --git a/tools/wip/clean-fs.sh b/tools/wip/clean-fs.sh index cd850a8..d52961c 100755 --- a/tools/wip/clean-fs.sh +++ b/tools/wip/clean-fs.sh @@ -25,7 +25,7 @@ find $1 -maxdepth 10 -type f | grep -v -E "\.webm$|\.flv$|\.vob$|\.ogg$|\.ogv$|\ while true; do read -p "[$0] Do you want to REMOVE these files?" yn case $yn in - [Yy]* ) find $1 -maxdepth 10 -type f | grep -v -E "\.webm$|\.flv$|\.vob$|\.ogg$|\.ogv$|\.drc$|\.gifv$|\.mng$|\.avi$|\.mov$|\.qt$|\.wmv$|\.yuv$|\.rm$|\.rmvb$|/.asf$|\.amv$|\.mp4$|\.m4v$|\.mp*$|\.m?v$|\.svi$|\.3gp$|\.flv$|\.f4v$" | xargs rm -f; break;; + [Yy]* ) find $1 -maxdepth 10 -type f | grep -v -E "\.webm$|\.flv$|\.vob$|\.ogg$|\.ogv$|\.drc$|\.gifv$|\.mng$|\.avi$|\.mov$|\.qt$|\.wmv$|\.yuv$|\.rm$|\.rmvb$|/.asf$|\.amv$|\.mp4$|\.m4v$|\.mp*$|\.m?v$|\.svi$|\.3gp$|\.flv$|\.f4v$" | xargs -0 rm -f; break;; [Nn]* ) echo "[$0] Skipping this part. Continuing...";; * ) echo "[$0] Please answer yes or no.";; esac diff --git a/traefik/custom/middlewares.yaml b/traefik/custom/middlewares.yaml index da09072..e0d2a75 100644 --- a/traefik/custom/middlewares.yaml +++ b/traefik/custom/middlewares.yaml @@ -15,3 +15,7 @@ http: frameDeny: true contentTypeNosniff: true browserXssFilter: true + redirect-to-https: + redirectScheme: + scheme: https + permanent: false diff --git a/traefik/traefik.yaml b/traefik/traefik.yaml index a2dfe1a..91d7823 100644 --- a/traefik/traefik.yaml +++ b/traefik/traefik.yaml @@ -2,10 +2,10 @@ api: dashboard: true # Set Access logs timezone -accessLog: - fields: - names: - StartUTC: drop +# accessLog: +# fields: +# names: +# StartUTC: drop providers: docker: @@ -19,11 +19,11 @@ providers: entryPoints: insecure: address: ":80" - http: - redirections: - entryPoint: - to: secure - scheme: https + # http: + # redirections: + # entryPoint: + # to: secure + # scheme: https secure: address: ":443" http: diff --git a/update-all.sh b/update-all.sh deleted file mode 100755 index c77d1f0..0000000 --- a/update-all.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash - -SKIP_PULL=0 - -for i in "$@"; do - case $i in - --no-pull) - SKIP_PULL=1 - ;; - *) - echo "[$0] ❌ ERROR: unknown parameter \"$i\"" - exit 1 - ;; - esac -done - -# Create/update http_auth file according to values in .env file -source .env -echo "${HTTP_USER}:${HTTP_PASSWORD}" > traefik/http_auth - -# Docker-compose settings -export COMPOSE_HTTP_TIMEOUT=240 - -if [[ ! -f services.conf ]]; then - echo "[$0] No services.conf file found. Copying from sample file..." - cp services.conf.sample services.conf -fi - -# Alert in case new services have been added (or removed) in sample but active file has not changed -NB_SERVICES_ACTIVE=$(cat services.conf | wc -l) -NB_SERVICES_ORIG=$(cat services.conf.sample | wc -l) -if [[ ${NB_SERVICES_ACTIVE} != ${NB_SERVICES_ORIG} ]]; then - echo "[$0] Your services.conf file seems outdated. It appears there are new services available, or services that have been removed." - diff -yt services.conf services.conf.sample -fi - -# Fetch all YAML files -disabled_pattern="" -while read -r line ; do - disabled_pattern="${disabled_pattern} ! -name $line.yaml" -done < <(grep "disable" services.conf | awk -F : '{print $1}' ) - -SERVICES=$(find services -mindepth 1 -maxdepth 1 -name "*.yaml" ${disabled_pattern} | sed -e 's/^/-f /') -ALL_SERVICES="-f docker-compose.yaml $SERVICES" - -# Specific instructions for Flood -# User for Deluge daemon RPC has to be created in deluge auth config file -if [[ ! -z ${FLOOD_PASSWORD} && ${FLOOD_AUTOCREATE_USER_IN_DELUGE_DAEMON} == true ]]; then - if ! grep -q "flood" /data/config/deluge/auth; then - echo "flood:${FLOOD_PASSWORD}:10" >> /data/config/deluge/auth - else - echo "[$0] No need to add user/password for flood as it has already been created." - echo "[$0] Consider setting FLOOD_AUTOCREATE_USER_IN_DELUGE_DAEMON variable to false in .env file." - fi -fi - -if [[ "${SKIP_PULL}" != "1" ]]; then - echo "[$0] ***** Pulling all images... *****" - docker-compose ${ALL_SERVICES} pull -fi - -echo "[$0] ***** Recreating containers if required... *****" -docker-compose ${ALL_SERVICES} up -d --remove-orphans -echo "[$0] ***** Done updating containers *****" -echo "[$0] ***** Clean unused images and volumes... *****" -docker image prune -af -docker volume prune -f -echo "[$0] ***** Done! *****" -exit 0 \ No newline at end of file