diff --git a/ansible/roles/arr/defaults/main.yml b/ansible/roles/arr/defaults/main.yml index 5506ed5..47ea10a 100644 --- a/ansible/roles/arr/defaults/main.yml +++ b/ansible/roles/arr/defaults/main.yml @@ -4,6 +4,11 @@ arrstack_env_dir: /opt/arrstack arrstack_data_dir: /srv arrstack_data_dir_create: true -arrstack_data_dir_owner: 1000 -arrstack_data_dir_group: 1000 +arrstack_puid: 1000 +arrstack_pgid: 100 +arrstack_tz: Europe/Berlin +arrstack_umask_set: 022 + +# arrstack_mb_user: Musicbrainz-user +# arrstack_mb_pass: Musicbrainz-password diff --git a/ansible/roles/arr/tasks/main.yml b/ansible/roles/arr/tasks/main.yml index f446a30..f2710ef 100644 --- a/ansible/roles/arr/tasks/main.yml +++ b/ansible/roles/arr/tasks/main.yml @@ -11,8 +11,8 @@ ansible.builtin.file: state: directory path: "{{ arrstack_data_dir }}/{{ item }}" - owner: "{{ arrstack_data_dir_owner }}" - group: "{{ arrstack_data_dir_group }}" + owner: "{{ arrstack_puid }}" + group: "{{ arrstack_pgid }}" mode: 0770 when: arrstack_data_dir_create loop: @@ -26,14 +26,6 @@ - media/music - media/audiobooks -# - name: Create Docker Compose environment file -# ansible.builtin.template: -# src: docker-compose.yml.j2 -# dest: "{{ arrstack_env_dir }}/docker-compose.yml" -# owner: root -# group: root -# mode: 0600 - - name: Start the compose stack community.docker.docker_compose_v2: project_name: arrstack diff --git a/ansible/roles/arr/templates/docker-compose.yaml.j2 b/ansible/roles/arr/templates/docker-compose.yaml.j2 index ec65b35..00f0252 100644 --- a/ansible/roles/arr/templates/docker-compose.yaml.j2 +++ b/ansible/roles/arr/templates/docker-compose.yaml.j2 @@ -1,117 +1,191 @@ services: - whoami: - container_name: whoami - image: traefik/whoami - ports: - - 80:80 - sonarr: container_name: sonarr image: lscr.io/linuxserver/sonarr:latest - ports: - - 8989:8989 - env_file: - - arr.env + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} volumes: - - "./config/sonarr:/config" + - "{{ arrstack_env_dir }}/config/sonarr:/config" - "{{ arrstack_data_dir }}/media/tv:/data/media/tv" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet" - "{{ arrstack_data_dir }}/files/torrent:/data/torrent" restart: unless-stopped + labels: + caddy: "http://sonarr.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 8989{{ '}}'}}" + radarr: container_name: radarr image: lscr.io/linuxserver/radarr:latest - ports: - - 7878:7878 - env_file: - - arr.env + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} volumes: - - "./config/radarr:/config" + - "{{ arrstack_env_dir }}/config/radarr:/config" - "/mnt/ext/data/media/movies:/data/media/movies" # FIXME: Find solution - "{{ arrstack_data_dir }}/files/usenet:/data/usenet" - "{{ arrstack_data_dir }}/files/torrent:/data/torrent" restart: unless-stopped + labels: + caddy: "http://radarr.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 7878{{ '}}'}}" + lidarr: container_name: lidarr image: lscr.io/linuxserver/lidarr:latest - ports: - - 8686:8686 - env_file: - - arr.env - - mb.env + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} + - MB_USER={{ arrstack_mb_user }} + - MB_PASS={{ arrstack_mb_pass }} environment: - DOCKER_MODS=linuxserver/mods:universal-docker volumes: - - "./config/lidarr:/config" + - "{{ arrstack_env_dir }}/config/lidarr:/config" - "/var/run/docker.sock:/var/run/docker.sock:ro" - "{{ arrstack_data_dir }}/media/music:/data/media/music" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet" - "{{ arrstack_data_dir }}/files/torrent:/data/torrent" restart: unless-stopped + labels: + caddy: "http://lidarr.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 8686{{ '}}'}}" + readarr: container_name: readarr image: lscr.io/linuxserver/readarr:develop - ports: - - 8787:8787 - env_file: - - arr.env + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} volumes: - - "./config/readarr:/config" + - "{{ arrstack_env_dir }}/config/readarr:/config" - "{{ arrstack_data_dir }}/media/audiobooks:/data/media/audiobooks" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet" - "{{ arrstack_data_dir }}/files/torrent:/data/torrent" restart: unless-stopped + labels: + caddy: "http://readarr.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 8787{{ '}}'}}" + prowlarr: container_name: prowlarr image: lscr.io/linuxserver/prowlarr:develop - env_file: - - arr.env + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} volumes: - - "./config/prowlarr:/config" - ports: - - 9696:9696 + - "{{ arrstack_env_dir }}/config/prowlarr:/config" restart: unless-stopped + labels: + caddy: "http://prowlarr.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 9696{{ '}}'}}" + + beets: + image: lscr.io/linuxserver/beets:latest + container_name: beets + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} + - MB_USER={{ arrstack_mb_user }} + - MB_PASS={{ arrstack_mb_pass }} + volumes: + - "{{ arrstack_env_dir }}/config/beets:/config" + - "{{ arrstack_data_dir }}/media/music:/music" + - "{{ arrstack_data_dir }}/files/music-unsorted:/downloads" + restart: unless-stopped + labels: + caddy: "http://prowlarr.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 8337{{ '}}'}}" + sabnzbd: container_name: sabnzbd image: lscr.io/linuxserver/sabnzbd:latest - env_file: - - arr.env + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} volumes: - - "./config/sabnzbd:/config" + - "{{ arrstack_env_dir }}/config/sabnzbd:/config" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet:rw" - ports: - - 8080:8080 restart: unless-stopped + labels: + caddy: "http://usenet.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 8080{{ '}}'}}" + vpn: - image: qmcgaw/gluetun:v3 container_name: vpn + image: qmcgaw/gluetun:v3 + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} + - VPN_PORT_FORWARDING_STATUS_FILE=/gluetun/forwarded_port + - FIREWALL_OUTBOUND_SUBNETS=172.18.0.0/24 + - BLOCK_SURVEILLANCE=on + - VPN_SERVICE_PROVIDER={{ arrstack_vpn_provider }} + - OPENVPN_USER={{ arrstack_vpn_user }} + - OPENVPN_PASSWORD={{ arrstack_vpn_pass }} + - SERVER_REGIONS={{ arrstack_vpn_regions }} + - PORT_FORWARD_ONLY=true + - VPN_PORT_FORWARDING=on + - VPN_PORT_FORWARDING_PROVIDER={{ arrstack_vpn_provider }} + - QBITTORRENT_USER={{ arrstack_qbit_user }} + - QBITTORRENT_PASS={{ arrstack_qbit_pass }} cap_add: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun - env_file: - - arr.env - - pia.env - environment: - - VPN_PORT_FORWARDING_STATUS_FILE=/gluetun/forwarded_port - - FIREWALL_OUTBOUND_SUBNETS=172.18.0.0/24 - - BLOCK_SURVEILLANCE=on volumes: - - "./config/gluetun:/gluetun" - ports: - - 8000:8000 # gluetun http control - - 8888:8888 # qBittorrent WebUI + - "{{ arrstack_env_dir }}/config/gluetun:/gluetun" + #ports: # TODO: should this be exposed? + # - 8000:8000 # gluetun http control restart: unless-stopped + labels: + caddy: "http://torrent.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 8888{{ '}}'}}" qbittorrent: image: linuxserver/qbittorrent container_name: qbittorrent - env_file: - - arr.env environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} - WEBUI_PORT=8888 volumes: - - "./config/piaqbit:/config" - - "./config/gluetun:/gluetun" + - "{{ arrstack_env_dir }}/config/piaqbit:/config" + - "{{ arrstack_env_dir }}/config/gluetun:/gluetun" - "{{ arrstack_data_dir }}/files/torrent:/downloads" depends_on: - vpn @@ -120,19 +194,30 @@ services: gluetun-qbittorrent-port-manager: image: patrickaclark/gluetun-qbittorrent-port-manager:latest container_name: qbit-port-manager - env_file: - - arr.env - - pia.env environment: - - QBITTORRENT_SERVER=localhost # IP Address of qbittorrent + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} + - WEBUI_PORT=8888 + - QBITTORRENT_SERVER=qbittorrent # IP Address of qbittorrent - QBITTORRENT_PORT=8888 - PORT_FORWARDED=/gluetun/forwarded_port - HTTP_S=http # Select 'http' or 'https' depending on if you use certificates. - - GLUETUN_HOST=localhost # IP or FQDN of gluetun control server + - GLUETUN_HOST=vpn # IP or FQDN of gluetun control server - GLUETUN_PORT=8000 # port of gluetun control server - RECHECK_TIME=60 # number of seconds between checks to gluetun server for port + - VPN_SERVICE_PROVIDER={{ arrstack_vpn_provider }} + - OPENVPN_USER={{ arrstack_vpn_user }} + - OPENVPN_PASSWORD={{ arrstack_vpn_pass }} + - SERVER_REGIONS={{ arrstack_vpn_regions }} + - PORT_FORWARD_ONLY=true + - VPN_PORT_FORWARDING=on + - VPN_PORT_FORWARDING_PROVIDER={{ arrstack_vpn_provider }} + - QBITTORRENT_USER={{ arrstack_qbit_user }} + - QBITTORRENT_PASS={{ arrstack_qbit_pass }} volumes: - - "./config/gluetun:/gluetun" + - "{{ arrstack_env_dir }}/config/gluetun:/gluetun" depends_on: - vpn network_mode: "service:vpn" @@ -143,67 +228,110 @@ services: timeout: 10s start_period: 60s retries: 3 - jellyfin: - image: lscr.io/linuxserver/jellyfin:latest - container_name: jellyfin - env_file: - - arr.env - #environment: - #- JELLYFIN_PublishedServerUrl=192.168.0.5 #optional - volumes: - - ".config/jellyfin:/config" - - "/mnt/ext/data/media/movies:/media/movies" # FIXME: To be changed? - - "{{ arrstack_data_dir }}/media/tv:/media/tv" - - "{{ arrstack_data_dir }}/media/music:/media/music" - ports: - - 8096:8096 - - 7359:7359/udp #optional - network discovery - - 1900:1900/udp #optional - dlna discovery - restart: unless-stopped - audiobookshelf: - container_name: audiobookshelf - image: ghcr.io/advplyr/audiobookshelf:latest - env_file: - - arr.env - ports: - - 13378:80 - volumes: - - "{{ arrstack_data_dir }}/media/audiobooks:/audiobooks" - # - "{{ arrstack_data_dir }}/media/podcasts:/podcasts" # TODO: If integrating podcasts - - ".config/audiobookshelf:/config" - - ".metadata/audiobookshelf:/metadata" - restart: unless-stopped - jellyseerr: - image: fallenbagel/jellyseerr:latest - container_name: jellyseerr - env_file: - - arr.env - ports: - - 5055:5055 - volumes: - - "./config/jellyseerr:/app/config" - restart: unless-stopped - beets: - image: lscr.io/linuxserver/beets:latest - container_name: beets - env_file: - - arr.env - - mb.env - volumes: - - "./config/beets:/config" - - "{{ arrstack_data_dir }}/media/music:/music" - - "{{ arrstack_data_dir }}/files/music-unsorted:/downloads" - ports: - - 8337:8337 - restart: unless-stopped + homarr: image: ghcr.io/ajnart/homarr:latest container_name: homarr + networks: + - caddy volumes: + - {{ arrstack_env_dir }}/config/homarr/configs:/app/data/configs + - {{ arrstack_env_dir }}/config/homarr/icons:/app/public/icons + - {{ arrstack_env_dir }}/config/homarr/data:/data - /var/run/docker.sock:/var/run/docker.sock # Optional, only if you want docker integration - - ./config/homarr/configs:/app/data/configs - - ./config/homarr/icons:/app/public/icons - - ./config/homarr/data:/data - ports: - - '80:7575' restart: unless-stopped + labels: + caddy: "http://pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 7575{{ '}}'}}" + + jellyseerr: + image: fallenbagel/jellyseerr:latest + container_name: jellyseerr + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} + volumes: + - "{{ arrstack_env_dir }}/config/jellyseerr:/app/config" + restart: unless-stopped + labels: + caddy: "http://get.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 5055{{ '}}'}}" + + audiobookshelf: + container_name: audiobookshelf + image: ghcr.io/advplyr/audiobookshelf:latest + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} + volumes: + - "{{ arrstack_env_dir }}/config/audiobookshelf:/config" + - "{{ arrstack_env_dir }}/data/audiobookshelf:/metadata" + - "{{ arrstack_data_dir }}/media/audiobooks:/audiobooks" + # - "{{ arrstack_data_dir }}/media/podcasts:/podcasts" # TODO: If integrating podcasts + restart: unless-stopped + labels: + caddy: "http://books.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 80{{ '}}'}}" + + jellyfin: + image: lscr.io/linuxserver/jellyfin:latest + container_name: jellyfin + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} + devices: + - /dev/dri:/dev/dri + #environment: + #- JELLYFIN_PublishedServerUrl=192.168.0.5 #optional + volumes: + - "{{ arrstack_env_dir }}/config/jellyfin:/config" + - "{{ arrstack_env_dir }}/data/jellyfin:/config/data" + - "/mnt/ext/data/media/movies:/media/movies" # FIXME: To be changed? + - "{{ arrstack_data_dir }}/media/tv:/media/tv" + - "{{ arrstack_data_dir }}/media/music:/media/music" + ports: # FIXME: how to enable discovery behind proxies? + - 7359:7359/udp #optional - network discovery + - 1900:1900/udp #optional - dlna discovery + restart: unless-stopped + labels: + caddy: "http://media.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 8096{{ '}}'}}" + + gonic: + image: sentriz/gonic:latest + networks: + - caddy + environment: + - PUID={{ arrstack_puid }} + - PGID={{ arrstack_pgid }} + - TZ={{ arrstack_tz }} + - UMASK_SET={{ arrstack_umask_set }} + volumes: + - "{{ arrstack_env_dir }}/data/gonic:/data" + - "{{ arrstack_env_dir }}/data/gonic_playlists:/playlists" + - "/srv/media/music:/music:ro" + - "/srv/media/podcasts:/podcasts" + #- /path/to/cache:/cache # transcode / covers / etc cache dir + labels: + caddy: "http://music.pichi.berlin" + caddy.reverse_proxy: "{{ '{{' }}upstreams 80{{ '}}'}}" + + +networks: + caddy: + external: true + +volumes: + caddy_data: {}