From 83e62eb2e975585b95e952d52e3ab71ea2bb5bc5 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Sat, 27 Apr 2024 20:56:08 +0200 Subject: [PATCH 01/14] add support for Flaresolverr, automatic timezone detection --- container_configs.py | 16 ++++++++++++++++ main.py | 14 ++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/container_configs.py b/container_configs.py index 6125a6e..92e749b 100644 --- a/container_configs.py +++ b/container_configs.py @@ -282,3 +282,19 @@ def sabnzbd(self): ' - "8081:8080"\n' ' restart: unless-stopped\n\n' ) + + def flaresolverr(self): + return ( + ' flaresolverr:\n' + ' image: ghcr.io/flaresolverr/flaresolverr:latest\n' + ' container_name: flaresolverr\n' + ' environment:\n' + ' - LOG_LEVEL=${LOG_LEVEL:-info}\n' + ' - LOG_HTML=${LOG_HTML:-false}\n' + ' - CAPTCHA_SOLVER=${CAPTCHA_SOLVER:-none}\n' + ' - TZ=' + self.timezone + '\n' + ' ports:\n' + ' - "8191:8191"\n' + ' restart: unless-stopped\n\n' + ) + diff --git a/main.py b/main.py index 8a5fbab..5f66ed5 100644 --- a/main.py +++ b/main.py @@ -65,6 +65,11 @@ def take_directory_input(): if len(services_classed['indexer']) == 0: print('Warning: no indexing service selected.') +print('\n===CLOUDFLARE BYPASS===') +services_classed['bypass'] = [] +print('Use Flaresolverr? [Y/n]', end=" ") +take_input('flaresolverr', 'bypass') + print('\n===MEDIA SERVERS===') services_classed['ms'] = [] print('Use PleX? [Y/n]', end=" ") @@ -105,10 +110,15 @@ def take_directory_input(): exit(1) print('\n===CONFIGURATION===') -print('Please enter your timezone (like "Europe/Amsterdam")', end=' ') + +print('Please enter your timezone (like "Europe/Amsterdam") or press enter to use your PCs configured timezone:', end=' ') timezone = input() -if len(timezone) == 0: +if (timezone == ''): + timezone = open("/etc/timezone", "r").readline() + +if len(timezone) == 0: # if user pressed enter and reading timezone from /etc/timezone failed then default to Amsterdam timezone = 'Europe/Amsterdam' + plex_claim = '' if services.__contains__('plex'): print('If you have a PleX claim token, enter it now. Otherwise, just press enter.', end=' ') From 22527a52bbf8b645c83be42856cc8824b672f241 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Sat, 27 Apr 2024 22:41:50 +0200 Subject: [PATCH 02/14] add scripts for cleaning up old users, and updating the containers --- remove_old_users.sh | 23 +++++++++++++++++++++++ setup.sh | 6 ++++++ update_containers.sh | 9 +++++++++ 3 files changed, 38 insertions(+) create mode 100755 remove_old_users.sh create mode 100755 update_containers.sh diff --git a/remove_old_users.sh b/remove_old_users.sh new file mode 100755 index 0000000..e48436c --- /dev/null +++ b/remove_old_users.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# shut down all ezarr containers referenced by docker-compose.yml +# If you previously had ezarr installed somewhere else you have to do this manually in the directory where the docker-compose file is. +sudo docker compose down + +# Remove old users and group +sudo userdel sonarr +sudo userdel radarr +sudo userdel lidarr +sudo userdel readarr +sudo userdel mylar +sudo userdel audiobookshelf +sudo userdel bazarr +sudo userdel prowlarr +sudo userdel jackett +sudo userdel plex +sudo userdel overseerr +sudo userdel jellyseerr +sudo userdel qbittorrent +sudo userdel sabnzbd +sudo groupdel mediacenter + diff --git a/setup.sh b/setup.sh index 390986d..4437f6f 100755 --- a/setup.sh +++ b/setup.sh @@ -15,6 +15,12 @@ sudo useradd sabnzbd -u 13011 sudo useradd jellyseerr -u 13012 sudo useradd bazarr -u 13013 sudo groupadd mediacenter -g 13000 + +# Adds current user to the mediacenter group. This is recommended so that you can still have access to files inside the ezarr folder structure for manual manipulation. +# This is way better than just doing everything as root, especially on NFS shares. Also some services run as the default user anyway (Jellyfin, Tautulli) so this is necessary +sudo usermod -a -G mediacenter $USER + +# adds all the service users to the group sudo usermod -a -G mediacenter sonarr sudo usermod -a -G mediacenter radarr sudo usermod -a -G mediacenter lidarr diff --git a/update_containers.sh b/update_containers.sh new file mode 100755 index 0000000..b356f49 --- /dev/null +++ b/update_containers.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Shutds down all the containers, updates them and removes the old images. +# If you want to keep the old images remove or comment the last line. + +sudo docker-compose pull +sudo docker-compose down +sudo docker-compose up -d +sudo docker image prune -f From d2b3ff36e553886b2a3fcaea0922e91b9ac9f6c9 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Sun, 28 Apr 2024 11:32:05 +0200 Subject: [PATCH 03/14] fix audiobookshelf, re-add jacket support --- container_configs.py | 27 ++++-- docker-compose.yml | 196 ------------------------------------------ main.py | 2 + setup.sh | 3 + users_groups_setup.py | 31 +++---- 5 files changed, 40 insertions(+), 219 deletions(-) delete mode 100644 docker-compose.yml diff --git a/container_configs.py b/container_configs.py index 92e749b..b4faf6c 100644 --- a/container_configs.py +++ b/container_configs.py @@ -181,13 +181,13 @@ def audiobookshelf(self): ' image: ghcr.io/advplyr/audiobookshelf:latest\n' ' container_name: audiobookshelf\n' ' environment:\n' - ' - AUDIOBOOKSHELF_UID=13009\n' - ' - AUDIOBOOKSHELF_GID=13000\n' + ' - user=13014:13000\n' + ' - TZ=' + self.timezone + '\n' ' volumes:\n' ' - ' + self.config_dir + '/audiobookshelf:/config\n' - ' - ' + self.root_dir + '/data/audiobooks:/audiobooks\n' - ' - ' + self.root_dir + '/data/podcasts:/podcasts\n' - ' - ' + self.root_dir + '/data/metadata:/metadata\n' + ' - ' + self.root_dir + '/data/media/audiobooks:/audiobooks\n' + ' - ' + self.root_dir + '/data/media/podcasts:/podcasts\n' + ' - ' + self.root_dir + '/data/media/audiobookshelf-metadata:/metadata\n' ' ports:\n' ' - "13378:80"\n' ' restart: unless-stopped\n\n' @@ -283,6 +283,23 @@ def sabnzbd(self): ' restart: unless-stopped\n\n' ) + def jackett(self): + return ( + ' jackett:\n' + ' image: lscr.io/linuxserver/jackett:latest\n' + ' container_name: jackett\n' + ' environment:\n' + ' - PUID=13008\n' + ' - PGID=13000\n' + ' - UMASK=002\n' + ' - TZ=' + self.timezone + '\n' + ' volumes:\n' + ' - ' + self.config_dir + '/jackett-config:/config\n' + ' ports:\n' + ' - 9117:9117\n' + ' restart: unless-stopped\n\n' + ) + def flaresolverr(self): return ( ' flaresolverr:\n' diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 85c11f6..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,196 +0,0 @@ ---- -version: "3.1" -services: - sonarr: - image: lscr.io/linuxserver/sonarr:latest - container_name: sonarr - environment: - - PUID=13001 - - PGID=13000 - - UMASK=002 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/sonarr-config:/config - - /home/user/ezarr/data:/data - ports: - - "8989:8989" - restart: unless-stopped - - radarr: - image: lscr.io/linuxserver/radarr:latest - container_name: radarr - environment: - - PUID=13002 - - PGID=13000 - - UMASK=002 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/radarr-config:/config - - /home/user/ezarr/data:/data - ports: - - "7878:7878" - restart: unless-stopped - - bazarr: - image: lscr.io/linuxserver/bazarr:latest - container_name: bazarr - environment: - - PUID=13012 - - PGID=13000 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/bazarr-config:/config - - /home/user/ezarr/data/media:/media - ports: - - "6767:6767" - restart: unless-stopped - - lidarr: - image: lscr.io/linuxserver/lidarr:latest - container_name: lidarr - environment: - - PUID=13003 - - PGID=13000 - - UMASK=002 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/lidarr-config:/config - - /home/user/ezarr/data:/data - ports: - - "8686:8686" - restart: unless-stopped - - readarr: - image: lscr.io/linuxserver/readarr:develop - container_name: readarr - environment: - - PUID=13004 - - PGID=13000 - - UMASK=002 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/readarr-config:/config - - /home/user/ezarr/data:/data - ports: - - "8787:8787" - restart: unless-stopped - - mylar3: - image: lscr.io/linuxserver/mylar3:latest - container_name: mylar3 - environment: - - PUID=13005 - - PGID=13000 - - UMASK=002 - volumes: - - /home/user/ezarr/config/mylar-config:/config - - /home/user/ezarr/data:/data - ports: - - "8090:8090" - restart: unless-stopped - - audiobookshelf: - image: ghcr.io/advplyr/audiobookshelf:latest - container_name: audiobookshelf - environment: - - AUDIOBOOKSHELF_UID=13009 - - AUDIOBOOKSHELF_GID=13000 - volumes: - - /home/user/ezarr/config/audiobookshelf:/config - - /home/user/ezarr/data/audiobooks:/audiobooks - - /home/user/ezarr/data/podcasts:/podcasts - - /home/user/ezarr/data/metadata:/metadata - ports: - - "13378:80" - restart: unless-stopped - - prowlarr: - image: lscr.io/linuxserver/prowlarr:develop - container_name: prowlarr - environment: - - PUID=13006 - - PGID=13000 - - UMASK=002 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/prowlarr-config:/config - ports: - - "9696:9696" - restart: unless-stopped - - plex: - image: lscr.io/linuxserver/plex:latest - container_name: plex - network_mode: host - environment: - - PUID=13010 - - PGID=13000 - - VERSION=docker - - PLEX_CLAIM= - volumes: - - /home/user/ezarr/config/plex-config:/config - - /home/user/ezarr/data/media:/media - restart: unless-stopped - - tautulli: - image: lscr.io/linuxserver/tautulli:latest - container_name: tautulli - depends_on: - - plex - environment: - - PUID=${UID} - - PGID=13000 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/tautulli-config:/config - ports: - - "8181:8181" - restart: unless-stopped - - jellyfin: - image: lscr.io/linuxserver/jellyfin:latest - container_name: jellyfin - environment: - - PUID=${UID} - - PGID=13000 - - UMASK=002 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/jellyfin-config:/config - - /home/user/ezarr/data/media:/data - ports: - - "8096:8096" - restart: unless-stopped - - qbittorrent: - image: lscr.io/linuxserver/qbittorrent:latest - container_name: qbittorrent - environment: - - PUID=13007 - - PGID=13000 - - UMASK=002 - - TZ=Europe/Amsterdam - - WEBUI_PORT=8080 - volumes: - - /home/user/ezarr/config/qbittorrent-config:/config - - /home/user/ezarr/data/torrents:/data/torrents - ports: - - "8080:8080" - - "6881:6881" - - "6881:6881/udp" - restart: unless-stopped - - sabnzbd: - image: lscr.io/linuxserver/sabnzbd:latest - container_name: sabnzbd - environment: - - PUID=13011 - - PGID=13000 - - UMASK=002 - - TZ=Europe/Amsterdam - volumes: - - /home/user/ezarr/config/sabnzbd-config:/config - - /home/user/ezarr/data/usenet:/data/usenet - ports: - - "8081:8080" - restart: unless-stopped diff --git a/main.py b/main.py index 5f66ed5..3da4bdb 100644 --- a/main.py +++ b/main.py @@ -62,6 +62,8 @@ def take_directory_input(): services_classed['indexer'] = [] print('Use Prowlarr? [Y/n]', end=" ") take_input('prowlarr', 'indexer') +print('Use Jackett? [Y/n]', end=" ") +take_input('jackett', 'indexer') if len(services_classed['indexer']) == 0: print('Warning: no indexing service selected.') diff --git a/setup.sh b/setup.sh index 4437f6f..ed23b41 100755 --- a/setup.sh +++ b/setup.sh @@ -14,6 +14,7 @@ sudo useradd plex -u 13010 sudo useradd sabnzbd -u 13011 sudo useradd jellyseerr -u 13012 sudo useradd bazarr -u 13013 +sudo useradd audiobookshelf -u 13014 sudo groupadd mediacenter -g 13000 # Adds current user to the mediacenter group. This is recommended so that you can still have access to files inside the ezarr folder structure for manual manipulation. @@ -34,6 +35,7 @@ sudo usermod -a -G mediacenter plex sudo usermod -a -G mediacenter sabnzbd sudo usermod -a -G mediacenter jellyseerr sudo usermod -a -G mediacenter bazarr +sudo usermod -a -G mediacenter audiobookshelf # Make directories sudo mkdir -pv config/{sonarr,radarr,lidarr,readarr,mylar,prowlarr,qbittorrent,jackett,audiobookshelf,overseerr,plex,tautulli,sabnzbd,jellyseerr,bazarr}-config @@ -55,5 +57,6 @@ sudo chown -R plex:mediacenter config/plex-config sudo chown -R sabnzbd:mediacenter config/sabnzbd-config sudo chown -R jellyseerr:mediacenter config/jellyseerr-config sudo chown -R bazarr:mediacenter config/bazarr-config +sudo chown -R audiobookshelf:mediacenter config/audiobookshelf-config echo "UID=$(id -u)" >> .env diff --git a/users_groups_setup.py b/users_groups_setup.py index 17895d0..a726876 100644 --- a/users_groups_setup.py +++ b/users_groups_setup.py @@ -5,21 +5,19 @@ class UserGroupSetup: def __init__(self, root_dir='/'): self.root_dir = root_dir os.system('sudo groupadd mediacenter -g 13000') + os.system('sudo usermod -a -G mediacenter $USER') def create_config_dir(self, service_name): os.system( - f'sudo mkdir -p {self.root_dir}/config/{service_name}-config' + f'sudo mkdir -p {self.root_dir}/config/{service_name}-config -m 775' # -m 775 gives read/write access to the whole mediacenter group, change to 755 for only read f' ; sudo chown -R {service_name}:mediacenter {self.root_dir}/config/{service_name}-config' - f' ; sudo chown $(id -u):mediacenter {self.root_dir}/config' ) def sonarr(self): os.system( '/bin/bash -c "sudo useradd sonarr -u 13001' ' ; sudo mkdir -pv ' + self.root_dir + '/data/{media,usenet,torrents}/tv -m 775' - ' ; sudo chown -R sonarr:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/tv' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}"' + ' ; sudo chown -R sonarr:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/tv"' ) self.create_config_dir('sonarr') os.system('sudo usermod -a -G mediacenter sonarr') @@ -28,9 +26,7 @@ def radarr(self): os.system( '/bin/bash -c "sudo useradd radarr -u 13002' ' ; sudo mkdir -pv ' + self.root_dir + '/data/{media,usenet,torrents}/movies -m 775' - ' ; sudo chown -R radarr:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/movies' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}"' + ' ; sudo chown -R radarr:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/movies"' ) self.create_config_dir('radarr') os.system('sudo usermod -a -G mediacenter radarr') @@ -44,9 +40,7 @@ def lidarr(self): os.system( '/bin/bash -c "sudo useradd lidarr -u 13003' ' ; sudo mkdir -pv ' + self.root_dir + '/data/{media,usenet,torrents}/music -m 775' - ' ; sudo chown -R lidarr:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/music' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}"' + ' ; sudo chown -R lidarr:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/music"' ) self.create_config_dir('lidarr') os.system('sudo usermod -a -G mediacenter lidarr') @@ -55,9 +49,7 @@ def readarr(self): os.system( '/bin/bash -c "sudo useradd readarr -u 13004' ' ; sudo mkdir -pv ' + self.root_dir + '/data/{media,usenet,torrents}/books -m 775' - ' ; sudo chown -R readarr:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/books' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}"' + ' ; sudo chown -R readarr:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/books"' ) self.create_config_dir('readarr') os.system('sudo usermod -a -G mediacenter readarr') @@ -66,16 +58,14 @@ def mylar3(self): os.system( '/bin/bash -c "sudo useradd mylar -u 13005' ' ; sudo mkdir -pv ' + self.root_dir + '/data/{media,usenet,torrents}/comics -m 775' - ' ; sudo chown -R mylar:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/comics' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}"' + ' ; sudo chown -R mylar:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/comics"' ) self.create_config_dir('mylar') os.system('sudo usermod -a -G mediacenter mylar') def audiobookshelf(self): os.system( - '/bin/bash -c "sudo useradd audiobookshelf -u 13009' + '/bin/bash -c "sudo useradd audiobookshelf -u 13014' ' ; sudo mkdir -pv ' + self.root_dir + '/data/{media,usenet,torrents}/audiobooks -m 775' ' ; sudo chown -R audiobookshelf:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/audiobooks' ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data' @@ -112,3 +102,8 @@ def jellyseerr(self): os.system('sudo useradd jellyseerr -u 13012') self.create_config_dir('jellyseerr') os.system('sudo usermod -a -G mediacenter jellyseerr') + + def jackett(self): + os.system('sudo useradd jackett -u 13008') + self.create_config_dir('jackett') + os.system('sudo usermod -a -G mediacenter jackett') From 2f6a5112c76c1a685dfbabc3f35d056dbbc24489 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Thu, 2 May 2024 12:32:15 +0200 Subject: [PATCH 04/14] add optional folder and permission generation also use a previously unused function to clean up code --- main.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/main.py b/main.py index 3da4bdb..43ee281 100644 --- a/main.py +++ b/main.py @@ -4,14 +4,6 @@ services_classed = dict() -def take_input(service_name, service_type): - choice = input() - if choice == 'Y' or choice == 'y' or choice == '': - services_classed[service_type].append(service_name) - elif choice != 'n' and choice != 'N': - print('Invalid input, please enter Y or N. Not adding ' + service_name + ".") - - def take_boolean_input(default=True): while True: ans = input() @@ -23,6 +15,12 @@ def take_boolean_input(default=True): return False print('Please answer with y or n.', end=' ') +def take_input(service_name, service_type): + choice = take_boolean_input() + if choice: + services_classed[service_type].append(service_name) + else: + print('Invalid input, please enter Y or N. Not adding ' + service_name + ".") def take_directory_input(): while True: @@ -137,15 +135,24 @@ def take_directory_input(): ) container_config = ContainerConfig(root_dir, timezone, plex_claim=plex_claim) -permission_setup = UserGroupSetup(root_dir=root_dir) for service in services: - try: - getattr(permission_setup, service)() - except AttributeError: - pass compose.write(getattr(container_config, service)()) compose.close() +print("Docker compose file generated successfully.") + +print("Do you want to also generate the required folder structure and permissions? (this is required for first time setup) [Y/N]: ") +generate_permissions = take_boolean_input() +if generate_permissions: + permission_setup = UserGroupSetup(root_dir=root_dir) + for service in services: + try: + getattr(permission_setup, service)() + except AttributeError: + pass +else: + print("Aborted.") + print('Process complete. You can now run "docker compose up -d" to start your containers.') print('Thank you for using EZarr. If you experience any issues or have feature requests, add them to our issues.') From 82536b06f27ffe8e1c96c125c5870ec8a81be1f4 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Fri, 3 May 2024 23:13:50 +0200 Subject: [PATCH 05/14] fix python UID for tautulli and jellyfin --- container_configs.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/container_configs.py b/container_configs.py index b4faf6c..dca0eed 100644 --- a/container_configs.py +++ b/container_configs.py @@ -1,3 +1,5 @@ +import os + class ContainerConfig: def __init__(self, root_dir, @@ -15,6 +17,7 @@ def __init__(self, self.comic_dir = root_dir + '/media/comics' self.torrent_dir = root_dir + '/data/torrents' self.usenet_dir = root_dir + '/data/usenet' + self.UID = os.popen('id -u').read().rstrip('\n') def plex(self): return ( @@ -41,7 +44,7 @@ def tautulli(self): ' depends_on:\n' ' - plex\n' ' environment:\n' - ' - PUID=${UID}\n' + ' - PUID='+ self.UID + '\n' ' - PGID=13000\n' ' - TZ=' + self.timezone + '\n' ' volumes:\n' @@ -57,7 +60,7 @@ def jellyfin(self): ' image: lscr.io/linuxserver/jellyfin:latest\n' ' container_name: jellyfin\n' ' environment:\n' - ' - PUID=${UID}\n' + ' - PUID='+ self.UID + '\n' ' - PGID=13000\n' ' - UMASK=002\n' ' - TZ=' + self.timezone + '\n' From 77e1cc0a3dee0f3af4b2df2f2039431df3cfd416 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Fri, 3 May 2024 23:14:41 +0200 Subject: [PATCH 06/14] remove empty file --- take_input.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 take_input.py diff --git a/take_input.py b/take_input.py deleted file mode 100644 index e69de29..0000000 From e943e4004bfe2211e00a4bdee64e0efc44d92f94 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Fri, 3 May 2024 23:15:00 +0200 Subject: [PATCH 07/14] docker-compose sample that uses env variables new .env sample, fixed setup --- .env.sample | 28 ++++- docker-compose.yml.sample | 252 ++++++++++++++++++++++++++++++++++++++ setup.sh | 58 +++++---- 3 files changed, 316 insertions(+), 22 deletions(-) create mode 100644 docker-compose.yml.sample diff --git a/.env.sample b/.env.sample index 4987e06..4a4d383 100644 --- a/.env.sample +++ b/.env.sample @@ -1,8 +1,34 @@ # If you're not sure what timezone you should fill in, you can look at the following list: # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones # Use the column that says "TZ database name". +# to find your system's preconfigured timezone run: cat /etc/timezone TIMEZONE=Europe/Amsterdam + # The PleX claim token is used to connect your server to your account. It can be obtained at # https://www.plex.tv/claim/ and is valid for 4 minutes after generating the token. PLEX_CLAIM= -ROOT_DIR=/ + +# Choose your root directory for keeping all your container configs and data. +ROOT_DIR=/ezarr + +# USER IDs for each container that requires their own user. The default values will most likely suffice, but in case one of these IDs is already in use on your system it will have to be changed. Any value should work as long as there aren't conflicts with other users. +# If you've already set up the containers and want to change user IDs after the fact, you have to remove the old users first and re-set permissions. First run remove_old_users.sh and then the steps for manual installation. +# If you're doing a manual installation make sure to first change the IDs in this file, and then run setup.sh to set up the directory structure and permissions before you start the docker containers. +MEDIACENTER_GID=13000 +SONARR_UID=13001 +RADARR_UID=13002 +LIDARR_UID=13003 +READARR_UID=13004 +MYLAR_UID=13005 +AUDIOBOOKSHELF_UID=13014 +BAZARR_UID=13013 +PROWLARR_UID=13006 +QBITTORRENT_UID=13007 +JACKETT_UID=13008 +PLEX_UID=13010 +OVERSEERR_UID=13009 +SABNZBD_UID=13011 +JELLYSEERR_UID=13012 + +# The user used to run docker-compose. To find this run: id -u +UID=1000 \ No newline at end of file diff --git a/docker-compose.yml.sample b/docker-compose.yml.sample new file mode 100644 index 0000000..99d65c8 --- /dev/null +++ b/docker-compose.yml.sample @@ -0,0 +1,252 @@ +--- +name: ezarr +services: + sonarr: + image: lscr.io/linuxserver/sonarr:latest + container_name: sonarr + environment: + - PUID=${SONARR_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/sonarr-config:/config + - ${ROOT_DIR}/data:/data + ports: + - "8989:8989" + restart: unless-stopped + + radarr: + image: lscr.io/linuxserver/radarr:latest + container_name: radarr + environment: + - PUID=${RADARR_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/radarr-config:/config + - ${ROOT_DIR}/data:/data + ports: + - "7878:7878" + restart: unless-stopped + + lidarr: + image: lscr.io/linuxserver/lidarr:latest + container_name: lidarr + environment: + - PUID=${LIDARR_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/lidarr-config:/config + - ${ROOT_DIR}/data:/data + ports: + - "8686:8686" + restart: unless-stopped + + readarr: + image: lscr.io/linuxserver/readarr:develop + container_name: readarr + environment: + - PUID=${READARR_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/readarr-config:/config + - ${ROOT_DIR}/data:/data + ports: + - "8787:8787" + restart: unless-stopped + + mylar3: + image: lscr.io/linuxserver/mylar3:latest + container_name: mylar3 + environment: + - PUID=${MYLAR_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + volumes: + - ${ROOT_DIR}/config/mylar-config:/config + - ${ROOT_DIR}/data:/data + ports: + - "8090:8090" + restart: unless-stopped + + audiobookshelf: + image: ghcr.io/advplyr/audiobookshelf:latest + container_name: audiobookshelf + environment: + - user=${AUDIOBOOKSHELF_UID}:${MEDIACENTER_GID} + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/audiobookshelf:/config + - ${ROOT_DIR}/data/media/audiobooks:/audiobooks + - ${ROOT_DIR}/data/media/podcasts:/podcasts + - ${ROOT_DIR}/data/media/audiobookshelf-metadata:/metadata + ports: + - "13378:80" + restart: unless-stopped + + bazarr: + image: lscr.io/linuxserver/bazarr:latest + container_name: bazarr + environment: + - PUID=${BAZARR_UID} + - PGID=${MEDIACENTER_GID} + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/bazarr-config:/config + - ${ROOT_DIR}/data/media:/media + ports: + - "6767:6767" + restart: unless-stopped + + overseerr: + image: sctx/overseerr:latest + container_name: overseerr + environment: + - PUID=${OVERSEERR_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/overseerr-config:/app/config + ports: + - "5055:5055" + restart: unless-stopped + + jellyseerr: + image: fallenbagel/jellyseerr:latest + container_name: jellyseerr + environment: + - PUID=${JELLYSEERR_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/jellyseerr-config:/app/config + ports: + - "5056:5055" + restart: unless-stopped + + prowlarr: + image: lscr.io/linuxserver/prowlarr:develop + container_name: prowlarr + environment: + - PUID=${PROWLARR_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/prowlarr-config:/config + ports: + - "9696:9696" + restart: unless-stopped + + jackett: + image: lscr.io/linuxserver/jackett:latest + container_name: jackett + environment: + - PUID=${JACKETT_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/jackett-config:/config + ports: + - 9117:9117 + restart: unless-stopped + + flaresolverr: + image: ghcr.io/flaresolverr/flaresolverr:latest + container_name: flaresolverr + environment: + - LOG_LEVEL=${LOG_LEVEL:-info} + - LOG_HTML=${LOG_HTML:-false} + - CAPTCHA_SOLVER=${CAPTCHA_SOLVER:-none} + - TZ=${TIMEZONE} + ports: + - "8191:8191" + restart: unless-stopped + + plex: + image: lscr.io/linuxserver/plex:latest + container_name: plex + network_mode: host + environment: + - PUID=${PLEX_UID} + - PGID=${MEDIACENTER_GID} + - VERSION=docker + - PLEX_CLAIM=${PLEX_CLAIM} + volumes: + - ${ROOT_DIR}/config/plex-config:/config + - ${ROOT_DIR}/data/media:/media + restart: unless-stopped + + tautulli: + image: lscr.io/linuxserver/tautulli:latest + container_name: tautulli + # commented out because plex can also run outside of docker + #depends_on: + # - plex + environment: + - PUID=${UID} + - PGID=${MEDIACENTER_GID} + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/tautulli-config:/config + ports: + - "8181:8181" + restart: unless-stopped + + jellyfin: + image: lscr.io/linuxserver/jellyfin:latest + container_name: jellyfin + environment: + - PUID=${UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/jellyfin-config:/config + - ${ROOT_DIR}/data/media:/data + ports: + - "8096:8096" + restart: unless-stopped + + qbittorrent: + image: lscr.io/linuxserver/qbittorrent:latest + container_name: qbittorrent + environment: + - PUID=${QBITTORRENT_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + - WEBUI_PORT=8080 + volumes: + - ${ROOT_DIR}/config/qbittorrent-config:/config + - ${ROOT_DIR}/data/torrents:/data/torrents + ports: + - "8080:8080" + - "6881:6881" + - "6881:6881/udp" + restart: unless-stopped + + sabnzbd: + image: lscr.io/linuxserver/sabnzbd:latest + container_name: sabnzbd + environment: + - PUID=${SABNZBD_UID} + - PGID=${MEDIACENTER_GID} + - UMASK=002 + - TZ=${TIMEZONE} + volumes: + - ${ROOT_DIR}/config/sabnzbd-config:/config + - ${ROOT_DIR}/data/usenet:/downloads + ports: + - "8081:8080" + restart: unless-stopped + diff --git a/setup.sh b/setup.sh index ed23b41..fcef1f5 100755 --- a/setup.sh +++ b/setup.sh @@ -1,25 +1,36 @@ #!/bin/bash +# Set up your .env file BEFORE running this script!!! +# export all variables from .env +set -a +source .env +set +a +# This is always going to complain about UID being a read-only variable. +# However that is not a problem and it's necessary for UID to be defined in the .env so that docker-compose.yml can take it. +# Reminder to set the UID variable in .env if you haven't already. It needs to be the user you want to run docker as. Find what it should be by running "id -u" from that user's shell. + # Make users and group -sudo useradd sonarr -u 13001 -sudo useradd radarr -u 13002 -sudo useradd lidarr -u 13003 -sudo useradd readarr -u 13004 -sudo useradd mylar -u 13005 -sudo useradd prowlarr -u 13006 -sudo useradd qbittorrent -u 13007 -sudo useradd jackett -u 13008 -sudo useradd overseerr -u 13009 -sudo useradd plex -u 13010 -sudo useradd sabnzbd -u 13011 -sudo useradd jellyseerr -u 13012 -sudo useradd bazarr -u 13013 -sudo useradd audiobookshelf -u 13014 -sudo groupadd mediacenter -g 13000 +sudo useradd sonarr -u $SONARR_UID +sudo useradd radarr -u $RADARR_UID +sudo useradd lidarr -u $LIDARR_UID +sudo useradd readarr -u $READARR_UID +sudo useradd mylar -u $MYLAR_UID +sudo useradd prowlarr -u $PROWLARR_UID +sudo useradd qbittorrent -u $QBITTORRENT_UID +sudo useradd jackett -u $JACKETT_UID +sudo useradd overseerr -u $OVERSEERR_UID +sudo useradd plex -u $PLEX_UID +sudo useradd sabnzbd -u $SABNZBD_UID +sudo useradd jellyseerr -u $SABNZBD_UID +sudo useradd bazarr -u $BAZARR_UID +sudo useradd audiobookshelf -u $AUDIOBOOKSHELF_UID +sudo groupadd mediacenter -g $MEDIACENTER_GID -# Adds current user to the mediacenter group. This is recommended so that you can still have access to files inside the ezarr folder structure for manual manipulation. -# This is way better than just doing everything as root, especially on NFS shares. Also some services run as the default user anyway (Jellyfin, Tautulli) so this is necessary +# Adds current user to the mediacenter group. This is recommended so that you can still have access to files inside the ezarr folder structure for manual control. +# This is way better than just doing everything as root, especially on NFS shares. Also some services run as the default user anyway (Jellyfin, Tautulli). sudo usermod -a -G mediacenter $USER +# When you add the user to the group the cahanges don't take effect immediately. +# You can force them by running "sudo newgrp mediacenter" but that won't always work and it's better to just reboot after the script finishes running. # adds all the service users to the group sudo usermod -a -G mediacenter sonarr @@ -38,12 +49,15 @@ sudo usermod -a -G mediacenter bazarr sudo usermod -a -G mediacenter audiobookshelf # Make directories -sudo mkdir -pv config/{sonarr,radarr,lidarr,readarr,mylar,prowlarr,qbittorrent,jackett,audiobookshelf,overseerr,plex,tautulli,sabnzbd,jellyseerr,bazarr}-config -sudo mkdir -pv data/{torrents,usenet,media}/{tv,movies,music,books,comics,audiobooks,podcasts,audiobookshelf-metadata} +# ${ROOT_DIR:-.}/ means take the value from ROOT_DIR value, if failed or empty place it in the current folder +sudo mkdir -pv ${ROOT_DIR:-.}/config/{sonarr,radarr,lidarr,readarr,mylar,prowlarr,qbittorrent,jackett,audiobookshelf,overseerr,plex,jellyfin,tautulli,sabnzbd,jellyseerr,bazarr}-config +sudo mkdir -pv ${ROOT_DIR:-.}/data/{torrents,usenet,media}/{tv,movies,music,books,comics,audiobooks,podcasts,audiobookshelf-metadata} # Set permissions sudo chmod -R 775 data/ -sudo chown -R $(id -u):mediacenter data/ +sudo chmod -R 775 config/ +sudo chown -R $UID:mediacenter data/ +sudo chown -R $UID:mediacenter config/ sudo chown -R sonarr:mediacenter config/sonarr-config sudo chown -R radarr:mediacenter config/radarr-config sudo chown -R lidarr:mediacenter config/lidarr-config @@ -54,9 +68,11 @@ sudo chown -R qbittorrent:mediacenter config/qbittorrent-config sudo chown -R jackett:mediacenter config/jackett-config sudo chown -R overseerr:mediacenter config/overseerr-config sudo chown -R plex:mediacenter config/plex-config +sudo chown -R $UID:mediacenter config/jellyfin-config +sudo chown -R $UID:mediacenter config/tautulli-config sudo chown -R sabnzbd:mediacenter config/sabnzbd-config sudo chown -R jellyseerr:mediacenter config/jellyseerr-config sudo chown -R bazarr:mediacenter config/bazarr-config sudo chown -R audiobookshelf:mediacenter config/audiobookshelf-config -echo "UID=$(id -u)" >> .env +echo "Done! It is recommended to reboot now." \ No newline at end of file From 01ae3c1cd77d8012fb1ee95ea76a980b6e6e7150 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Sat, 4 May 2024 13:35:30 +0200 Subject: [PATCH 08/14] change default install directory to current dir --- .env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.sample b/.env.sample index 4a4d383..3462765 100644 --- a/.env.sample +++ b/.env.sample @@ -9,7 +9,7 @@ TIMEZONE=Europe/Amsterdam PLEX_CLAIM= # Choose your root directory for keeping all your container configs and data. -ROOT_DIR=/ezarr +ROOT_DIR= # USER IDs for each container that requires their own user. The default values will most likely suffice, but in case one of these IDs is already in use on your system it will have to be changed. Any value should work as long as there aren't conflicts with other users. # If you've already set up the containers and want to change user IDs after the fact, you have to remove the old users first and re-set permissions. First run remove_old_users.sh and then the steps for manual installation. From 4d513a1d8f2f037750ff3f21c1c3210f52d72cb7 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Fri, 3 May 2024 23:15:44 +0200 Subject: [PATCH 09/14] fix update_containers --- update_containers.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/update_containers.sh b/update_containers.sh index b356f49..463709b 100755 --- a/update_containers.sh +++ b/update_containers.sh @@ -3,7 +3,13 @@ # Shutds down all the containers, updates them and removes the old images. # If you want to keep the old images remove or comment the last line. -sudo docker-compose pull -sudo docker-compose down -sudo docker-compose up -d -sudo docker image prune -f +# If the following commands throw permission errors, uncomment the following lines +#sudo groupadd docker +#sudo usermod -aG docker $USER +#newgrp docker +# if that isnt enough then reboot + +docker compose pull +docker compose down +docker compose up -d +docker image prune -f From 9ef99180ac4df14b992cd3ba443547a167919bfb Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Sat, 4 May 2024 12:03:30 +0200 Subject: [PATCH 10/14] remove obsolete version line --- main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/main.py b/main.py index 43ee281..a010a8c 100644 --- a/main.py +++ b/main.py @@ -130,7 +130,6 @@ def take_directory_input(): compose = open('docker-compose.yml', 'w') compose.write( '---\n' - 'version: "3.1"\n' 'services:\n' ) From 812d046ecb043ea2f6a690b779595c834bd98c48 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Sat, 4 May 2024 12:13:02 +0200 Subject: [PATCH 11/14] fix directory ownership --- users_groups_setup.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/users_groups_setup.py b/users_groups_setup.py index a726876..f1c110e 100644 --- a/users_groups_setup.py +++ b/users_groups_setup.py @@ -5,12 +5,18 @@ class UserGroupSetup: def __init__(self, root_dir='/'): self.root_dir = root_dir os.system('sudo groupadd mediacenter -g 13000') - os.system('sudo usermod -a -G mediacenter $USER') + os.system('sudo usermod -a -G mediacenter $USER') + os.system( + '/bin/bash -c "sudo mkdir -pv ' + self.root_dir + '/data/{media,usenet,torrents} -m 775' + ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data' + ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}"' + ) def create_config_dir(self, service_name): os.system( f'sudo mkdir -p {self.root_dir}/config/{service_name}-config -m 775' # -m 775 gives read/write access to the whole mediacenter group, change to 755 for only read f' ; sudo chown -R {service_name}:mediacenter {self.root_dir}/config/{service_name}-config' + f' ; sudo chown $(id -u):mediacenter {self.root_dir}/config' ) def sonarr(self): @@ -66,10 +72,8 @@ def mylar3(self): def audiobookshelf(self): os.system( '/bin/bash -c "sudo useradd audiobookshelf -u 13014' - ' ; sudo mkdir -pv ' + self.root_dir + '/data/{media,usenet,torrents}/audiobooks -m 775' - ' ; sudo chown -R audiobookshelf:mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}/audiobooks' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data' - ' ; sudo chown $(id -u):mediacenter ' + self.root_dir + '/data/{media,usenet,torrents}"' + ' ; sudo mkdir -pv ' + self.root_dir + '/data/media/{audiobooks,podcasts,audiobookshelf-metadata} -m 775' + ' ; sudo chown -R audiobookshelf:mediacenter ' + self.root_dir + '/data/media/{audiobooks,podcasts,audiobookshelf-metadata}"' ) self.create_config_dir('audiobookshelf') os.system('sudo usermod -a -G mediacenter audiobookshelf') From e1777eb73aaf344fa117ad4707e0a9ec2af0e92b Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Sat, 27 Apr 2024 22:51:08 +0200 Subject: [PATCH 12/14] update README --- README.md | 68 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a0ade49..cb7629c 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ Ezarr is a project built to make it EZ to deploy a Servarr mediacenter on an Ubuntu server. The badge above means that the shell script and docker-compose file in this repository at least *don't -crash*. It doesn't necessarily mean it will run well on your system ;) It features: +crash*. It doesn't necessarily mean it will run well on your system ;) +It's set up to follow the [TRaSH guidelines](https://trash-guides.info/Hardlinks/How-to-setup-for/Docker/) so it should at least perform optimally. It features: - [Sonarr](https://sonarr.tv/) is an application to manage TV shows. It is capable of keeping track of what you'd like to watch, at what quality, in which language and more, and can find a place to download this if connected to Prowlarr and qBittorrent. It can also reorganize the media you @@ -24,6 +25,7 @@ crash*. It doesn't necessarily mean it will run well on your system ;) It featur less than 1. Less than 1 means that you upload less than you download. Not only is this unfriendly towards your fellow users, but it can also get you banned from certain indexers. - [Jackett](https://github.com/Jackett/Jackett) is an alternative to Prowlarr. +- [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) is a proxy server to bypass Cloudflare and DDoS-GUARD protection. - [qBittorrent](https://www.qbittorrent.org/) can download torrents and provides a bunch more features for management. - [SABnzbd](https://sabnzbd.org/) can download nzb's @@ -39,35 +41,60 @@ crash*. It doesn't necessarily mean it will run well on your system ;) It featur tool. - [Jellyseerr](https://github.com/Fallenbagel/jellyseerr) is like Overseerr, but for Jellyfin. +## Requirements +Currently this script only works on Linux. The only requirements other than that are **Python 3** and **docker** with **docker-compose-v2**. +While this script _may_ work on docker-compose-v1 it's made to be and highly recommended to be run using v2. +The easiest way to install these dependencies on Ubuntu is by running: +``` +sudo apt-get install python3 docker.io docker-compose-v2 +``` +For other Linux distros you may have to use a different package manager or download directly from docker's website. + ## Using ### Using the CLI To make things easier, a CLI has been developed. First, clone the repository in a directory of your -choosing. You can run it by entering `python main.py` and the CLI will guide you through the -process. Please take a look at [important notes](#important-notes) before you continue. +choosing. You can run it by entering `python3 main.py` and the CLI will guide you through the +process. This is the recommended method if you're setting this up for the first time on a new system. +Please take a look at [important notes](#important-notes) before you continue. +**NOTE: This script will create users for each container with IDs ranging from 13001 to 13014. +If you want to choose your own IDs (or some of them are occupied) you have to go through the manual install.** ### Manually -1. To get started, clone the repository in a directory of your choosing. **Note: this will be where - your installation and media will be as well, so think about this a bit.** +If you're installing this for the first time simply follow these steps. +If you're coming from an older version or reinstalling with different IDs, run `remove_old_users.sh` to clean up old users and then follow these steps. +1. To get started, clone the repository in a directory of your choosing. `git clone https://github.com/Luctia/ezarr.git` 2. Copy `.env.sample` to a real `.env` by running `$ cp .env.sample .env`. -3. Set the environment variables to your liking. Note that `ROOT_DIR` should be the directory you - have cloned this in. -4. Run `setup.sh` as superuser. This will set up your users, a system of directories, ensure - permissions are set correctly and sets some more environment variables for docker compose. -5. Take a look at the `docker-compose.yml` file. If there are services you would like to ignore +3. Set the environment variables to your liking. Pay special attention `ROOT_DIR` as this is where everything is going to be stored in. + The path in this value needs to be **absolute**. If you leave it empty it's going to install in the directory the .env file is currently in. + `UID` should be set to the ID of the user that you want to run docker with. You can find this by running `id -u` from that user's shell. +4. Run `setup.sh` as superuser. This will set up your users, a system of directories and ensure permissions are set correctly. +5. Copy `docker-compose.yml.sample` to a real `docker-compose.yml` by running `$ cp docker-compose.yml.sample docker-compose.yml`. +6. Take a look at the `docker-compose.yml` file. If there are services you would like to ignore (for example, running PleX and Jellyfin at the same time is a bit unusual), you can comment them - out by placing `#` in front of the lines. This ensures they are ignored by Docker compose. -6. Run `docker compose up`. + out by placing `#` in front of the lines. This ensures they are ignored by Docker compose. + Double check that your .env file is set up properly. +7. Run `docker compose up -d` to start the containers. If it complains about permissions run the following commands to add your current user to the docker group and apply changes: + ``` + sudo groupadd docker + sudo usermod -aG docker $USER + newgrp docker + ``` + If it still doesn't work reboot your system. That's it! Your containers are now up and you can continue to set up the settings in them. Please take a look at [important notes](#important-notes) before you continue. ## Important notes +- If you already used this script previously and want to clean up old users, run `remove_old_users.sh`. + This is also recommended if you are updating from an earlier version of this script, since there were previously some conflicts in user IDs. +- It is recommended to restart your system after script completion, so that newly created users and groups can be loaded properly. - When linking one service to another, remember to use the container name instead of `localhost`. - Please set the settings of the -arr containers as soon as possible to the following (use advanced): - Media management: - Use hardlinks instead of Copy: `true` - Root folder: `/data/media/` and then tv, movies or music depending on service + - qBittorrent ships with a default username `admin` and a one-time password that can be viewed by running `docker logs qbittorrent`. - Make sure to set a username and password for all servarr services and qBittorrent! - In qBittorrent, after connecting it to the -arr services, you can indicate it should move torrents in certain categories to certain directories, like torrents in the `radarr` category @@ -76,6 +103,18 @@ take a look at [important notes](#important-notes) before you continue. field: `chmod -R 775 "%F/"`. - You'll have to add indexers in Prowlarr by hand. Use Prowlarrs settings to connect it to the other -arr apps. + +### IMPORTANT IF USING NFS SHARES +- NFS shares' permissions are mapped by user IDs. If you want to access a file as a client, your user ID needs to match the user ID of the owner (or group) of that file on the NFS server. +Note that if you are a group member (and not the owner), having matching group IDs won't be enough, there also needs to be a corresponding user on the NFS server. The easiest way to make sure +the users and groups are set up on both sides correctly is to run `setup.sh` on both your NFS server and your client. +On your server: +- Copy `.env` and `setup.sh` to your NFS server. +- You may have to adjust `.env` so that `ROOT_DIR` reflects where it will be stored on your server, which is most likely different from the mapped location on the client. +- Make sure that the `.env` file is not a .sample. Run `setup.sh`. +- Now follow all the same steps but on your client machine. Always double-check that `.env` is set correctly, especially `ROOT_DIR`. +You don't have to do this on your server first but it's recommended. If you are running this script on the client **make sure that you temporarily enable -no-root-squash on your NFS server**, +as the script needs superuser privileges to run and by default on NFS the root user is mapped to nowhere to prevent abuse. ### SABnzbd External internet access denied message When you're trying to access SABnzbd the first time you'll come across the message `External @@ -92,7 +131,10 @@ official SABnzbd website. ## FAQ ### How to update containers -If you'd like to update containers, you can move to the directory of your `docker-compose.yml` file +There is an `update_containers.sh` script that takes care of this. Simply run it and it updates +all containers and removes old images. If you want to keep them, simply comment out the last line of the script. +It's essentially the following steps but automated: +If you'd like to it manually, go to the directory of your `docker-compose.yml` file and run `(sudo) docker compose pull`. This pulls the newest versions of all images (blueprints for containers) listed in the `docker-compose.yml` file. Then, you can run `(sudo) docker compose up -d`. This will deploy the new versions without losing uptime. Afterwards, you can run `(sudo) From 20317a93a027bdca5ab66332db6973b245ab13d5 Mon Sep 17 00:00:00 2001 From: Pavlogal Date: Tue, 2 Jul 2024 21:34:10 +0200 Subject: [PATCH 13/14] address nitpicks --- .env.sample | 4 ++-- README.md | 7 +++++-- main.py | 8 ++++---- setup.sh | 4 ++-- update_containers.sh | 1 - 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.env.sample b/.env.sample index 3462765..30d0918 100644 --- a/.env.sample +++ b/.env.sample @@ -1,7 +1,7 @@ # If you're not sure what timezone you should fill in, you can look at the following list: # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones # Use the column that says "TZ database name". -# to find your system's preconfigured timezone run: cat /etc/timezone +# To find your system's preconfigured timezone run: cat /etc/timezone TIMEZONE=Europe/Amsterdam # The PleX claim token is used to connect your server to your account. It can be obtained at @@ -31,4 +31,4 @@ SABNZBD_UID=13011 JELLYSEERR_UID=13012 # The user used to run docker-compose. To find this run: id -u -UID=1000 \ No newline at end of file +UID=1000 diff --git a/README.md b/README.md index cb7629c..7b1506f 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,10 @@ It's set up to follow the [TRaSH guidelines](https://trash-guides.info/Hardlinks - [Jellyseerr](https://github.com/Fallenbagel/jellyseerr) is like Overseerr, but for Jellyfin. ## Requirements -Currently this script only works on Linux. The only requirements other than that are **Python 3** and **docker** with **docker-compose-v2**. +Currently this script only works on Linux. There is a chance that the sample docker compose file will work on Windows, although untested. +The only requirements other than that are **Python 3** and **docker** with **docker-compose-v2**. While this script _may_ work on docker-compose-v1 it's made to be and highly recommended to be run using v2. -The easiest way to install these dependencies on Ubuntu is by running: +The easiest way to install these dependencies on Ubuntu and other Debian-based distors is by running: ``` sudo apt-get install python3 docker.io docker-compose-v2 ``` @@ -85,6 +86,8 @@ That's it! Your containers are now up and you can continue to set up the setting take a look at [important notes](#important-notes) before you continue. ## Important notes +- You probably shouldn't run the python script as root. Ideally you should create a brand new user that's just for these services, but any regular user will do. + It will need your password for `sudo` to set up the permissions and folder structures, but you shouldn't run it *as* root. - If you already used this script previously and want to clean up old users, run `remove_old_users.sh`. This is also recommended if you are updating from an earlier version of this script, since there were previously some conflicts in user IDs. - It is recommended to restart your system after script completion, so that newly created users and groups can be loaded properly. diff --git a/main.py b/main.py index a010a8c..12a1c27 100644 --- a/main.py +++ b/main.py @@ -20,7 +20,7 @@ def take_input(service_name, service_type): if choice: services_classed[service_type].append(service_name) else: - print('Invalid input, please enter Y or N. Not adding ' + service_name + ".") + print('Not adding ' + service_name + ".") def take_directory_input(): while True: @@ -111,7 +111,7 @@ def take_directory_input(): print('\n===CONFIGURATION===') -print('Please enter your timezone (like "Europe/Amsterdam") or press enter to use your PCs configured timezone:', end=' ') +print('Please enter your timezone (like "Europe/Amsterdam") or press enter to use your system\'s configured timezone:', end=' ') timezone = input() if (timezone == ''): timezone = open("/etc/timezone", "r").readline() @@ -140,7 +140,7 @@ def take_directory_input(): compose.close() print("Docker compose file generated successfully.") -print("Do you want to also generate the required folder structure and permissions? (this is required for first time setup) [Y/N]: ") +print("Do you want to also generate the required folder structure and permissions? (this is required for first time setup) [Y/n]: ") generate_permissions = take_boolean_input() if generate_permissions: permission_setup = UserGroupSetup(root_dir=root_dir) @@ -150,7 +150,7 @@ def take_directory_input(): except AttributeError: pass else: - print("Aborted.") + print("Permission and folder structure generation skipped by user.") print('Process complete. You can now run "docker compose up -d" to start your containers.') diff --git a/setup.sh b/setup.sh index fcef1f5..b38c800 100755 --- a/setup.sh +++ b/setup.sh @@ -29,7 +29,7 @@ sudo groupadd mediacenter -g $MEDIACENTER_GID # Adds current user to the mediacenter group. This is recommended so that you can still have access to files inside the ezarr folder structure for manual control. # This is way better than just doing everything as root, especially on NFS shares. Also some services run as the default user anyway (Jellyfin, Tautulli). sudo usermod -a -G mediacenter $USER -# When you add the user to the group the cahanges don't take effect immediately. +# When you add the user to the group the changes don't take effect immediately. # You can force them by running "sudo newgrp mediacenter" but that won't always work and it's better to just reboot after the script finishes running. # adds all the service users to the group @@ -75,4 +75,4 @@ sudo chown -R jellyseerr:mediacenter config/jellyseerr-config sudo chown -R bazarr:mediacenter config/bazarr-config sudo chown -R audiobookshelf:mediacenter config/audiobookshelf-config -echo "Done! It is recommended to reboot now." \ No newline at end of file +echo "Done! It is recommended to reboot now." diff --git a/update_containers.sh b/update_containers.sh index 463709b..ede8656 100755 --- a/update_containers.sh +++ b/update_containers.sh @@ -10,6 +10,5 @@ # if that isnt enough then reboot docker compose pull -docker compose down docker compose up -d docker image prune -f From a1f0c6b871e560af0a7bdda6364c0b8253a8966e Mon Sep 17 00:00:00 2001 From: Pavlogal <69644438+Pavlogal@users.noreply.github.com> Date: Sun, 5 May 2024 12:38:20 +0200 Subject: [PATCH 14/14] Update check_running.yml Updated auto-check workflow to also copy docker-compose sample file, updated syntax to docker compose without "-" --- .github/workflows/check_running.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check_running.yml b/.github/workflows/check_running.yml index a4a1c1e..bf4c1e5 100644 --- a/.github/workflows/check_running.yml +++ b/.github/workflows/check_running.yml @@ -18,9 +18,12 @@ jobs: - name: Copy environment file run: cp .env.sample .env + + - name: Copy docker-compose file + run: cp docker-compose.yml.sample docker-compose.yml - name: Run setup.sh run: ./setup.sh - - name: Run docker-compose - run: docker-compose up -d + - name: Run docker compose + run: docker compose up -d