1 Commits

Author SHA1 Message Date
Yuris Cakranegara
c07f59d021 feat: add media server 2025-06-27 21:34:55 +10:00
15 changed files with 1343 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
# Media Server Module
This module deploys a complete media server stack using Docker containers in the homelab environment. It includes content management services (Sonarr, Radarr, Readarr), content discovery (Prowlarr, Jellyseerr), download clients (Qbittorrent, Sabnzbd), and media playback (Jellyfin).
## Overview
The Media Server module:
- Deploys multiple Docker containers:
- `sonarr`: Series/TV management system
- `radarr`: Movie management system
- `readarr`: Book management system
- `jellyseerr`: Content request and discovery system
- `prowlarr`: Indexer management system
- `qbittorrent`: Torrent download client with VueTorrent UI
- `unpackerr`: Automatic extraction utility
- `jellyfin`: Media server for streaming content
- `sabnzbd`: Usenet download client
- `flaresolverr`: Proxy service to bypass Cloudflare and other protection
- `autoheal`: Service for automatic container health restarts
- Creates a dedicated Docker network (`media-server`) for container communication
- Persists data to volumes on the host
- Provides service definitions for integration with networking modules
- Exposes Jellyfin, Jellyseerr, and Sabnzbd via reverse proxy
## Usage
```hcl
module "media_server" {
source = "./modules/20-services-apps/media-server"
volume_path = "/path/to/app/data"
data_root = "/path/to/media/data"
download_root = "/path/to/download/data"
user_id = "1000"
group_id = "1000"
timezone = "UTC"
hostname = "example.com"
sonarr_api_key = "your-sonarr-api-key"
radarr_api_key = "your-radarr-api-key"
networks = ["homelab-network"]
}
```
## Variables
| Variable | Description | Type | Default |
| ---------------- | ------------------------------------------------- | -------------- | -------- |
| `volume_path` | Base directory for application data | `string` | - |
| `data_root` | Root directory for media data | `string` | - |
| `download_root` | Directory for downloads | `string` | - |
| `user_id` | User ID for container permissions | `string` | `"1000"` |
| `group_id` | Group ID for container permissions | `string` | `"1000"` |
| `timezone` | Timezone for the containers | `string` | `"UTC"` |
| `hostname` | Hostname for the Jellyfin PublishedServerUrl | `string` | - |
| `sonarr_api_key` | API key for Sonarr | `string` | - |
| `radarr_api_key` | API key for Radarr | `string` | - |
| `networks` | List of networks to which containers are attached | `list(string)` | `[]` |
## Outputs
| Output | Description |
| --------------------- | ------------------------------------------------------------------ |
| `service_definitions` | Service definitions for Jellyfin, Jellyseerr, and Sabnzbd services |
| `network_name` | Name of the media server network |
## Services
### Sonarr
TV series management tool that integrates with various download clients and indexers to automate obtaining TV episodes.
- Port: 8989
- Volumes:
- Config: `/config``${volume_path}/sonarr`
- Data: `/data``${data_root}`
### Radarr
Movie management tool that integrates with various download clients and indexers to automate obtaining movies.
- Port: 7878
- Volumes:
- Config: `/config``${volume_path}/radarr`
- Data: `/data``${data_root}`
### Readarr
Book management tool that integrates with various download clients and indexers to automate obtaining books.
- Port: 8787
- Volumes:
- Config: `/config``${volume_path}/readarr`
- Books: `/books``${data_root}`
### Jellyseerr
Media request system that integrates with Jellyfin to allow users to request new content.
- Port: 5055
- Volumes:
- Config: `/app/config``${volume_path}/jellyseerr`
### Prowlarr
Indexer manager/proxy that integrates with various PVR apps and download clients.
- Port: 9696
- Volumes:
- Config: `/config``${volume_path}/prowlarr`
### FlareSolverr
Proxy server to bypass Cloudflare and other protection methods.
- Port: 8191
### QBittorrent
Torrent client with VueTorrent web interface.
- Port: 8080
- Volumes:
- Config: `/config``${volume_path}/qbittorrent`
- Downloads: `/data/torrents``${download_root}`
### Unpackerr
Extracts completed downloads automatically for Sonarr, Radarr, and others.
- Volumes:
- Downloads: `/data/torrents``${download_root}`
### Jellyfin
Media server for streaming content to various devices.
- Ports:
- 8096 (HTTP)
- 7359 (UDP)
- 1900 (UDP)
- Volumes:
- Config: `/config``${volume_path}/jellyfin`
- Data: `/data``${data_root}`
- Devices:
- `/dev/dri/` for hardware acceleration
### Sabnzbd
Usenet download client.
- Port: 6789 (external) → 8080 (internal)
- Volumes:
- Config: `/config``${volume_path}/sabnzbd/config`
- Downloads: `/downloads``${data_root}/usenet/downloads`
### Autoheal
Service that automatically checks for container health and restarts unhealthy containers.
- Requires access to Docker socket
## Networking
The module creates a dedicated Docker network named `media-server` for communication between the components. Each service container is also attached to any additional networks specified in the `networks` variable, allowing it to communicate with other services in the homelab.
## Reverse Proxy Integration
Three services are configured to be exposed through a reverse proxy:
- **Jellyfin**: Exposed at subdomain `jellyfin`
- **Jellyseerr**: Exposed at subdomain `requests`
- **Sabnzbd**: Exposed at subdomain `sabnzbd`
These services have their `publish_via` property set to `"reverse_proxy"` in their service definitions.
## Example Integration in Main Configuration
```hcl
module "media_server" {
source = "./modules/20-services-apps/media-server"
volume_path = module.system_globals.volume_host
data_root = "${module.system_globals.data_root}/media"
download_root = "${module.system_globals.data_root}/downloads"
user_id = module.system_globals.user_id
group_id = module.system_globals.group_id
timezone = module.system_globals.timezone
hostname = "example.com"
sonarr_api_key = var.sonarr_api_key
radarr_api_key = var.radarr_api_key
networks = [module.services.homelab_docker_network_name]
}
# The service definitions are automatically included in the services output
module "services" {
source = "./modules/services"
# ...
service_definitions = concat(
module.media_server.service_definitions,
# Other service definitions
)
}
```

View File

@@ -0,0 +1,148 @@
terraform {
required_providers {
dotenv = {
source = "germanbrew/dotenv"
}
}
}
locals {
monitoring = true
# Define common healthcheck settings
healthcheck_interval = "30s"
healthcheck_retries = 10
}
# Create dedicated network for media server components
module "media_server_network" {
source = "../../01-networking/docker-network"
name = "media-server"
subnet = "11.102.0.0/16"
driver = "bridge"
}
# Import service modules
module "sonarr" {
source = "./services/sonarr"
user_id = var.user_id
group_id = var.group_id
timezone = var.timezone
volume_path = var.volume_path
data_root = var.data_root
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "radarr" {
source = "./services/radarr"
user_id = var.user_id
group_id = var.group_id
timezone = var.timezone
volume_path = var.volume_path
data_root = var.data_root
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "readarr" {
source = "./services/readarr"
user_id = var.user_id
group_id = var.group_id
timezone = var.timezone
volume_path = var.volume_path
data_root = var.data_root
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "jellyseerr" {
source = "./services/jellyseerr"
timezone = var.timezone
volume_path = var.volume_path
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "prowlarr" {
source = "./services/prowlarr"
user_id = var.user_id
group_id = var.group_id
timezone = var.timezone
volume_path = var.volume_path
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "qbittorrent" {
source = "./services/qbittorrent"
user_id = var.user_id
group_id = var.group_id
timezone = var.timezone
volume_path = var.volume_path
download_root = var.download_root
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "unpackerr" {
source = "./services/unpackerr"
user_id = var.user_id
group_id = var.group_id
timezone = var.timezone
download_root = var.download_root
sonarr_api_key = var.sonarr_api_key
radarr_api_key = var.radarr_api_key
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "jellyfin" {
source = "./services/jellyfin"
user_id = var.user_id
group_id = var.group_id
timezone = var.timezone
volume_path = var.volume_path
data_root = var.data_root
hostname = var.hostname
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "sabnzbd" {
source = "./services/sabnzbd"
user_id = var.user_id
group_id = var.group_id
timezone = var.timezone
volume_path = var.volume_path
data_root = var.data_root
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "flaresolverr" {
source = "./services/flaresolverr"
timezone = var.timezone
log_level = "info"
log_html = "false"
captcha_solver = "none"
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}
module "autoheal" {
source = "./services/autoheal"
networks = concat([module.media_server_network.name], var.networks)
monitoring = local.monitoring
}

View File

@@ -0,0 +1,13 @@
output "service_definitions" {
description = "Service definitions for integration with networking modules"
value = [
module.jellyfin.service_definition,
module.jellyseerr.service_definition,
module.sabnzbd.service_definition
]
}
output "network_name" {
description = "Name of the media server network"
value = module.media_server_network.name
}

View File

@@ -0,0 +1,48 @@
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "autoheal"
image = "willfarrell/autoheal"
tag = "latest"
autoheal_env_vars = {
AUTOHEAL_CONTAINER_LABEL = "all"
}
autoheal_volumes = [
{
host_path = "/var/run/docker.sock"
container_path = "/var/run/docker.sock"
read_only = false
}
]
}
module "autoheal" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.autoheal_volumes
env_vars = local.autoheal_env_vars
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for autoheal"
value = {
name = local.container_name
endpoint = "http://${local.container_name}"
}
}

View File

@@ -0,0 +1,71 @@
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
variable "log_level" {
description = "Log level for flaresolverr"
type = string
default = "info"
}
variable "log_html" {
description = "Whether to log HTML"
type = string
default = "false"
}
variable "captcha_solver" {
description = "Type of CAPTCHA solver to use"
type = string
default = "none"
}
locals {
container_name = "flaresolverr"
image = "ghcr.io/flaresolverr/flaresolverr"
tag = "latest"
flaresolverr_env_vars = {
LOG_LEVEL = var.log_level
LOG_HTML = var.log_html
CAPTCHA_SOLVER = var.captcha_solver
TZ = var.timezone
}
}
module "flaresolverr" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
env_vars = local.flaresolverr_env_vars
ports = [{
internal = 8191
external = 8191
protocol = "tcp"
}]
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for flaresolverr"
value = {
name = local.container_name
primary_port = 8191
endpoint = "http://${local.container_name}:8191"
}
}

View File

@@ -0,0 +1,114 @@
variable "user_id" {
description = "User ID for container permissions"
type = string
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
}
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "volume_path" {
description = "Base directory for volumes"
type = string
}
variable "data_root" {
description = "Root directory for media data"
type = string
}
variable "hostname" {
description = "Hostname for the Jellyfin PublishedServerUrl"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "jellyfin"
image = "jellyfin/jellyfin"
tag = "latest"
internal_ports = [
{
internal = 8096
external = 8096
protocol = "tcp"
},
{
internal = 7359
external = 7359
protocol = "udp"
},
{
internal = 1900
external = 1900
protocol = "udp"
}
]
jellyfin_volumes = [
{
host_path = "${var.volume_path}/jellyfin"
container_path = "/config"
read_only = false
},
{
host_path = "${var.data_root}"
container_path = "/data"
read_only = false
}
]
jellyfin_devices = [
"/dev/dri/:/dev/dri/"
]
jellyfin_env_vars = {
PUID = var.user_id
PGID = var.group_id
TZ = var.timezone
JELLYFIN_PublishedServerUrl = "${var.hostname}/jellyfin"
}
}
module "jellyfin" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.jellyfin_volumes
env_vars = local.jellyfin_env_vars
ports = local.internal_ports
devices = local.jellyfin_devices
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for integration with networking modules"
value = {
name = local.container_name
primary_port = 8096
endpoint = "http://${local.container_name}:8096"
subdomains = ["jellyfin"]
publish_via = "reverse_proxy"
proxied = false
}
}

View File

@@ -0,0 +1,77 @@
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "volume_path" {
description = "Base directory for volumes"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "jellyseerr"
image = "fallenbagel/jellyseerr"
tag = "latest"
jellyseerr_volumes = [
{
host_path = "${var.volume_path}/jellyseerr"
container_path = "/app/config"
read_only = false
}
]
jellyseerr_env_vars = {
LOG_LEVEL = "debug"
TZ = var.timezone
}
jellyseerr_healthcheck = {
test = ["CMD", "wget", "http://127.0.0.1:5055/api/v1/status", "-qO", "/dev/null"]
interval = "30s"
timeout = "5s"
retries = 10
start_period = "5s"
}
}
module "jellyseerr" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.jellyseerr_volumes
env_vars = local.jellyseerr_env_vars
healthcheck = local.jellyseerr_healthcheck
ports = [{
internal = 5055
external = 5055
protocol = "tcp"
}]
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for integration with networking modules"
value = {
name = local.container_name
primary_port = 5055
endpoint = "http://${local.container_name}:5055"
subdomains = ["requests"]
publish_via = "reverse_proxy"
proxied = false
}
}

View File

@@ -0,0 +1,85 @@
variable "user_id" {
description = "User ID for container permissions"
type = string
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
}
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "volume_path" {
description = "Base directory for volumes"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "prowlarr"
image = "lscr.io/linuxserver/prowlarr"
tag = "latest"
prowlarr_volumes = [
{
host_path = "${var.volume_path}/prowlarr"
container_path = "/config"
read_only = false
}
]
prowlarr_env_vars = {
PUID = var.user_id
PGID = var.group_id
TZ = var.timezone
}
prowlarr_healthcheck = {
test = ["CMD", "curl", "--fail", "http://127.0.0.1:9696/prowlarr/ping"]
interval = "30s"
timeout = "5s"
retries = 10
start_period = "5s"
}
}
module "prowlarr" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.prowlarr_volumes
env_vars = local.prowlarr_env_vars
healthcheck = local.prowlarr_healthcheck
ports = [{
internal = 9696
external = 9696
protocol = "tcp"
}]
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for prowlarr"
value = {
name = local.container_name
primary_port = 9696
endpoint = "http://${local.container_name}:9696"
}
}

View File

@@ -0,0 +1,97 @@
variable "user_id" {
description = "User ID for container permissions"
type = string
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
}
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "volume_path" {
description = "Base directory for volumes"
type = string
}
variable "download_root" {
description = "Directory for downloads"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "qbittorrent"
image = "lscr.io/linuxserver/qbittorrent"
tag = "libtorrentv1"
qbittorrent_volumes = [
{
host_path = "${var.volume_path}/qbittorrent"
container_path = "/config"
read_only = false
},
{
host_path = var.download_root
container_path = "/data/torrents"
read_only = false
}
]
qbittorrent_env_vars = {
PUID = var.user_id
PGID = var.group_id
TZ = var.timezone
WEBUI_PORT = "8080"
DOCKER_MODS = "ghcr.io/gabe565/linuxserver-mod-vuetorrent"
}
qbittorrent_healthcheck = {
test = ["CMD", "curl", "--fail", "http://127.0.0.1:8080", "https://google.com"]
interval = "30s"
timeout = "5s"
retries = 10
start_period = "5s"
}
}
module "qbittorrent" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.qbittorrent_volumes
env_vars = local.qbittorrent_env_vars
healthcheck = local.qbittorrent_healthcheck
ports = [{
internal = 8080
external = 8080
protocol = "tcp"
}]
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for qbittorrent"
value = {
name = local.container_name
primary_port = 8080
endpoint = "http://${local.container_name}:8080"
}
}

View File

@@ -0,0 +1,95 @@
variable "user_id" {
description = "User ID for container permissions"
type = string
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
}
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "volume_path" {
description = "Base directory for volumes"
type = string
}
variable "data_root" {
description = "Root directory for media data"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "radarr"
image = "lscr.io/linuxserver/radarr"
tag = "latest"
radarr_volumes = [
{
host_path = "${var.volume_path}/radarr"
container_path = "/config"
read_only = false
},
{
host_path = var.data_root
container_path = "/data"
read_only = false
}
]
radarr_env_vars = {
PUID = var.user_id
PGID = var.group_id
TZ = var.timezone
}
radarr_healthcheck = {
test = ["CMD", "curl", "--fail", "http://127.0.0.1:7878/radarr/ping"]
interval = "30s"
timeout = "5s"
retries = 10
start_period = "5s"
}
}
module "radarr" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.radarr_volumes
env_vars = local.radarr_env_vars
healthcheck = local.radarr_healthcheck
ports = [{
internal = 7878
external = 7878
protocol = "tcp"
}]
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for radarr"
value = {
name = local.container_name
primary_port = 7878
endpoint = "http://${local.container_name}:7878"
}
}

View File

@@ -0,0 +1,86 @@
variable "user_id" {
description = "User ID for container permissions"
type = string
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
}
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "volume_path" {
description = "Base directory for volumes"
type = string
}
variable "data_root" {
description = "Root directory for media data"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "readarr"
image = "lscr.io/linuxserver/readarr"
tag = "develop"
readarr_volumes = [
{
host_path = "${var.volume_path}/readarr"
container_path = "/config"
read_only = false
},
{
host_path = var.data_root
container_path = "/books"
read_only = false
}
]
readarr_env_vars = {
PUID = var.user_id
PGID = var.group_id
TZ = var.timezone
}
}
module "readarr" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.readarr_volumes
env_vars = local.readarr_env_vars
ports = [{
internal = 8787
external = 8787
protocol = "tcp"
}]
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for readarr"
value = {
name = local.container_name
primary_port = 8787
endpoint = "http://${local.container_name}:8787"
}
}

View File

@@ -0,0 +1,89 @@
variable "user_id" {
description = "User ID for container permissions"
type = string
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
}
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "volume_path" {
description = "Base directory for volumes"
type = string
}
variable "data_root" {
description = "Root directory for media data"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "sabnzbd"
image = "lscr.io/linuxserver/sabnzbd"
tag = "latest"
sabnzbd_volumes = [
{
host_path = "${var.volume_path}/sabnzbd/config"
container_path = "/config"
read_only = false
},
{
host_path = "${var.data_root}/usenet/downloads"
container_path = "/downloads"
read_only = false
}
]
sabnzbd_env_vars = {
PUID = var.user_id
PGID = var.group_id
TZ = var.timezone
}
}
module "sabnzbd" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.sabnzbd_volumes
env_vars = local.sabnzbd_env_vars
ports = [{
internal = 8080
external = 6789
protocol = "tcp"
}]
networks = var.networks
monitoring = var.monitoring
restart_policy = "unless-stopped"
}
output "service_definition" {
description = "Service definition for integration with networking modules"
value = {
name = local.container_name
primary_port = 8080
endpoint = "http://${local.container_name}:8080"
subdomains = ["sabnzbd"]
publish_via = "reverse_proxy"
proxied = false
}
}

View File

@@ -0,0 +1,95 @@
variable "user_id" {
description = "User ID for container permissions"
type = string
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
}
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "volume_path" {
description = "Base directory for volumes"
type = string
}
variable "data_root" {
description = "Root directory for media data"
type = string
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "sonarr"
image = "lscr.io/linuxserver/sonarr"
tag = "latest"
sonarr_volumes = [
{
host_path = "${var.volume_path}/sonarr"
container_path = "/config"
read_only = false
},
{
host_path = var.data_root
container_path = "/data"
read_only = false
}
]
sonarr_env_vars = {
PUID = var.user_id
PGID = var.group_id
TZ = var.timezone
}
sonarr_healthcheck = {
test = ["CMD", "curl", "--fail", "http://127.0.0.1:8989/sonarr/ping"]
interval = "30s"
timeout = "5s"
retries = 10
start_period = "5s"
}
}
module "sonarr" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.sonarr_volumes
env_vars = local.sonarr_env_vars
healthcheck = local.sonarr_healthcheck
ports = [{
internal = 8989
external = 8989
protocol = "tcp"
}]
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
}
output "service_definition" {
description = "Service definition for sonarr"
value = {
name = local.container_name
primary_port = 8989
endpoint = "http://${local.container_name}:8989"
}
}

View File

@@ -0,0 +1,90 @@
variable "user_id" {
description = "User ID for container permissions"
type = string
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
}
variable "timezone" {
description = "Timezone for the container"
type = string
}
variable "download_root" {
description = "Directory for downloads"
type = string
}
variable "sonarr_api_key" {
description = "API key for Sonarr"
type = string
sensitive = true
}
variable "radarr_api_key" {
description = "API key for Radarr"
type = string
sensitive = true
}
variable "networks" {
description = "List of networks to which the container should be attached"
type = list(string)
}
variable "monitoring" {
description = "Enable container monitoring"
type = bool
default = true
}
locals {
container_name = "unpackerr"
image = "golift/unpackerr"
tag = "latest"
unpackerr_volumes = [
{
host_path = var.download_root
container_path = "/data/torrents"
read_only = false
}
]
unpackerr_env_vars = {
TZ = var.timezone
UN_SONARR_0_URL = "http://sonarr:8989/sonarr"
UN_SONARR_0_API_KEY = var.sonarr_api_key
UN_RADARR_0_URL = "http://radarr:7878/radarr"
UN_RADARR_0_API_KEY = var.radarr_api_key
}
unpackerr_security_opts = [
"no-new-privileges:true"
]
}
module "unpackerr" {
source = "../../../../10-services-generic/docker-service"
container_name = local.container_name
image = local.image
tag = local.tag
volumes = local.unpackerr_volumes
env_vars = local.unpackerr_env_vars
security_opts = local.unpackerr_security_opts
networks = var.networks
monitoring = var.monitoring
restart_policy = "always"
user = "${var.user_id}:${var.group_id}"
}
output "service_definition" {
description = "Service definition for unpackerr"
value = {
name = local.container_name
endpoint = "http://${local.container_name}"
}
}

View File

@@ -0,0 +1,55 @@
variable "volume_path" {
description = "Base directory for volumes (APP_DATA)"
type = string
}
variable "data_root" {
description = "Root directory for media data (DATA_ROOT)"
type = string
}
variable "download_root" {
description = "Directory for downloads (DOWNLOAD_ROOT)"
type = string
}
variable "user_id" {
description = "User ID for container permissions"
type = string
default = "1000"
}
variable "group_id" {
description = "Group ID for container permissions"
type = string
default = "1000"
}
variable "timezone" {
description = "Timezone for the containers"
type = string
default = "UTC"
}
variable "hostname" {
description = "Hostname for the Jellyfin PublishedServerUrl"
type = string
}
variable "sonarr_api_key" {
description = "API key for Sonarr"
type = string
sensitive = true
}
variable "radarr_api_key" {
description = "API key for Radarr"
type = string
sensitive = true
}
variable "networks" {
description = "List of additional networks to which containers should be attached"
type = list(string)
default = []
}