Make arrstack docker compose ansible ready

Move sonarr to new system

Move sabnzbd to new system

Move radarr

Move lidarr

!unsafe directive makes ansible ignore potential template vars in the
string

https://github.com/ansible/ansible/issues/16443

Move readarr

Move prowlarr

Move homarr

Move beets

Move jellyseerr

Move audiobookshelf

Move jellyfin

Move gonic

Migrate torrent setup
This commit is contained in:
Marty Oehme 2025-07-14 10:01:19 +02:00
parent 93ae62dc93
commit 2045f4ae58
Signed by: Marty
GPG key ID: 4E535BC19C61886E
3 changed files with 254 additions and 129 deletions

View file

@ -4,6 +4,11 @@ arrstack_env_dir: /opt/arrstack
arrstack_data_dir: /srv arrstack_data_dir: /srv
arrstack_data_dir_create: true 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

View file

@ -11,8 +11,8 @@
ansible.builtin.file: ansible.builtin.file:
state: directory state: directory
path: "{{ arrstack_data_dir }}/{{ item }}" path: "{{ arrstack_data_dir }}/{{ item }}"
owner: "{{ arrstack_data_dir_owner }}" owner: "{{ arrstack_puid }}"
group: "{{ arrstack_data_dir_group }}" group: "{{ arrstack_pgid }}"
mode: 0770 mode: 0770
when: arrstack_data_dir_create when: arrstack_data_dir_create
loop: loop:
@ -26,14 +26,6 @@
- media/music - media/music
- media/audiobooks - 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 - name: Start the compose stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_name: arrstack project_name: arrstack

View file

@ -1,117 +1,191 @@
services: services:
whoami:
container_name: whoami
image: traefik/whoami
ports:
- 80:80
sonarr: sonarr:
container_name: sonarr container_name: sonarr
image: lscr.io/linuxserver/sonarr:latest image: lscr.io/linuxserver/sonarr:latest
ports: networks:
- 8989:8989 - caddy
env_file: environment:
- arr.env - PUID={{ arrstack_puid }}
- PGID={{ arrstack_pgid }}
- TZ={{ arrstack_tz }}
- UMASK_SET={{ arrstack_umask_set }}
volumes: volumes:
- "./config/sonarr:/config" - "{{ arrstack_env_dir }}/config/sonarr:/config"
- "{{ arrstack_data_dir }}/media/tv:/data/media/tv" - "{{ arrstack_data_dir }}/media/tv:/data/media/tv"
- "{{ arrstack_data_dir }}/files/usenet:/data/usenet" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet"
- "{{ arrstack_data_dir }}/files/torrent:/data/torrent" - "{{ arrstack_data_dir }}/files/torrent:/data/torrent"
restart: unless-stopped restart: unless-stopped
labels:
caddy: "http://sonarr.pichi.berlin"
caddy.reverse_proxy: "{{ '{{' }}upstreams 8989{{ '}}'}}"
radarr: radarr:
container_name: radarr container_name: radarr
image: lscr.io/linuxserver/radarr:latest image: lscr.io/linuxserver/radarr:latest
ports: networks:
- 7878:7878 - caddy
env_file: environment:
- arr.env - PUID={{ arrstack_puid }}
- PGID={{ arrstack_pgid }}
- TZ={{ arrstack_tz }}
- UMASK_SET={{ arrstack_umask_set }}
volumes: volumes:
- "./config/radarr:/config" - "{{ arrstack_env_dir }}/config/radarr:/config"
- "/mnt/ext/data/media/movies:/data/media/movies" # FIXME: Find solution - "/mnt/ext/data/media/movies:/data/media/movies" # FIXME: Find solution
- "{{ arrstack_data_dir }}/files/usenet:/data/usenet" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet"
- "{{ arrstack_data_dir }}/files/torrent:/data/torrent" - "{{ arrstack_data_dir }}/files/torrent:/data/torrent"
restart: unless-stopped restart: unless-stopped
labels:
caddy: "http://radarr.pichi.berlin"
caddy.reverse_proxy: "{{ '{{' }}upstreams 7878{{ '}}'}}"
lidarr: lidarr:
container_name: lidarr container_name: lidarr
image: lscr.io/linuxserver/lidarr:latest image: lscr.io/linuxserver/lidarr:latest
ports: networks:
- 8686:8686 - caddy
env_file: environment:
- arr.env - PUID={{ arrstack_puid }}
- mb.env - PGID={{ arrstack_pgid }}
- TZ={{ arrstack_tz }}
- UMASK_SET={{ arrstack_umask_set }}
- MB_USER={{ arrstack_mb_user }}
- MB_PASS={{ arrstack_mb_pass }}
environment: environment:
- DOCKER_MODS=linuxserver/mods:universal-docker - DOCKER_MODS=linuxserver/mods:universal-docker
volumes: volumes:
- "./config/lidarr:/config" - "{{ arrstack_env_dir }}/config/lidarr:/config"
- "/var/run/docker.sock:/var/run/docker.sock:ro" - "/var/run/docker.sock:/var/run/docker.sock:ro"
- "{{ arrstack_data_dir }}/media/music:/data/media/music" - "{{ arrstack_data_dir }}/media/music:/data/media/music"
- "{{ arrstack_data_dir }}/files/usenet:/data/usenet" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet"
- "{{ arrstack_data_dir }}/files/torrent:/data/torrent" - "{{ arrstack_data_dir }}/files/torrent:/data/torrent"
restart: unless-stopped restart: unless-stopped
labels:
caddy: "http://lidarr.pichi.berlin"
caddy.reverse_proxy: "{{ '{{' }}upstreams 8686{{ '}}'}}"
readarr: readarr:
container_name: readarr container_name: readarr
image: lscr.io/linuxserver/readarr:develop image: lscr.io/linuxserver/readarr:develop
ports: networks:
- 8787:8787 - caddy
env_file: environment:
- arr.env - PUID={{ arrstack_puid }}
- PGID={{ arrstack_pgid }}
- TZ={{ arrstack_tz }}
- UMASK_SET={{ arrstack_umask_set }}
volumes: volumes:
- "./config/readarr:/config" - "{{ arrstack_env_dir }}/config/readarr:/config"
- "{{ arrstack_data_dir }}/media/audiobooks:/data/media/audiobooks" - "{{ arrstack_data_dir }}/media/audiobooks:/data/media/audiobooks"
- "{{ arrstack_data_dir }}/files/usenet:/data/usenet" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet"
- "{{ arrstack_data_dir }}/files/torrent:/data/torrent" - "{{ arrstack_data_dir }}/files/torrent:/data/torrent"
restart: unless-stopped restart: unless-stopped
labels:
caddy: "http://readarr.pichi.berlin"
caddy.reverse_proxy: "{{ '{{' }}upstreams 8787{{ '}}'}}"
prowlarr: prowlarr:
container_name: prowlarr container_name: prowlarr
image: lscr.io/linuxserver/prowlarr:develop image: lscr.io/linuxserver/prowlarr:develop
env_file: networks:
- arr.env - caddy
environment:
- PUID={{ arrstack_puid }}
- PGID={{ arrstack_pgid }}
- TZ={{ arrstack_tz }}
- UMASK_SET={{ arrstack_umask_set }}
volumes: volumes:
- "./config/prowlarr:/config" - "{{ arrstack_env_dir }}/config/prowlarr:/config"
ports:
- 9696:9696
restart: unless-stopped 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: sabnzbd:
container_name: sabnzbd container_name: sabnzbd
image: lscr.io/linuxserver/sabnzbd:latest image: lscr.io/linuxserver/sabnzbd:latest
env_file: networks:
- arr.env - caddy
environment:
- PUID={{ arrstack_puid }}
- PGID={{ arrstack_pgid }}
- TZ={{ arrstack_tz }}
- UMASK_SET={{ arrstack_umask_set }}
volumes: volumes:
- "./config/sabnzbd:/config" - "{{ arrstack_env_dir }}/config/sabnzbd:/config"
- "{{ arrstack_data_dir }}/files/usenet:/data/usenet:rw" - "{{ arrstack_data_dir }}/files/usenet:/data/usenet:rw"
ports:
- 8080:8080
restart: unless-stopped restart: unless-stopped
labels:
caddy: "http://usenet.pichi.berlin"
caddy.reverse_proxy: "{{ '{{' }}upstreams 8080{{ '}}'}}"
vpn: vpn:
image: qmcgaw/gluetun:v3
container_name: vpn 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: cap_add:
- NET_ADMIN - NET_ADMIN
devices: devices:
- /dev/net/tun:/dev/net/tun - /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: volumes:
- "./config/gluetun:/gluetun" - "{{ arrstack_env_dir }}/config/gluetun:/gluetun"
ports: #ports: # TODO: should this be exposed?
- 8000:8000 # gluetun http control # - 8000:8000 # gluetun http control
- 8888:8888 # qBittorrent WebUI
restart: unless-stopped restart: unless-stopped
labels:
caddy: "http://torrent.pichi.berlin"
caddy.reverse_proxy: "{{ '{{' }}upstreams 8888{{ '}}'}}"
qbittorrent: qbittorrent:
image: linuxserver/qbittorrent image: linuxserver/qbittorrent
container_name: qbittorrent container_name: qbittorrent
env_file:
- arr.env
environment: environment:
- PUID={{ arrstack_puid }}
- PGID={{ arrstack_pgid }}
- TZ={{ arrstack_tz }}
- UMASK_SET={{ arrstack_umask_set }}
- WEBUI_PORT=8888 - WEBUI_PORT=8888
volumes: volumes:
- "./config/piaqbit:/config" - "{{ arrstack_env_dir }}/config/piaqbit:/config"
- "./config/gluetun:/gluetun" - "{{ arrstack_env_dir }}/config/gluetun:/gluetun"
- "{{ arrstack_data_dir }}/files/torrent:/downloads" - "{{ arrstack_data_dir }}/files/torrent:/downloads"
depends_on: depends_on:
- vpn - vpn
@ -120,19 +194,30 @@ services:
gluetun-qbittorrent-port-manager: gluetun-qbittorrent-port-manager:
image: patrickaclark/gluetun-qbittorrent-port-manager:latest image: patrickaclark/gluetun-qbittorrent-port-manager:latest
container_name: qbit-port-manager container_name: qbit-port-manager
env_file:
- arr.env
- pia.env
environment: 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 - QBITTORRENT_PORT=8888
- PORT_FORWARDED=/gluetun/forwarded_port - PORT_FORWARDED=/gluetun/forwarded_port
- HTTP_S=http # Select 'http' or 'https' depending on if you use certificates. - 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 - GLUETUN_PORT=8000 # port of gluetun control server
- RECHECK_TIME=60 # number of seconds between checks to gluetun server for port - 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: volumes:
- "./config/gluetun:/gluetun" - "{{ arrstack_env_dir }}/config/gluetun:/gluetun"
depends_on: depends_on:
- vpn - vpn
network_mode: "service:vpn" network_mode: "service:vpn"
@ -143,67 +228,110 @@ services:
timeout: 10s timeout: 10s
start_period: 60s start_period: 60s
retries: 3 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: homarr:
image: ghcr.io/ajnart/homarr:latest image: ghcr.io/ajnart/homarr:latest
container_name: homarr container_name: homarr
networks:
- caddy
volumes: 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 - /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 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: {}