feat: add media server
This commit is contained in:
33
modules/20-services-apps/gluetun/.env.example
Normal file
33
modules/20-services-apps/gluetun/.env.example
Normal file
@@ -0,0 +1,33 @@
|
||||
# Gluetun VPN (.env example)
|
||||
# Copy to modules/20-services-apps/gluetun/.env and fill in values
|
||||
|
||||
# Provider and VPN type
|
||||
VPN_SERVICE_PROVIDER=mullvad
|
||||
VPN_TYPE=wireguard
|
||||
|
||||
# Wireguard credentials (required)
|
||||
# Generate from Mullvad account: private key and tunnel IP address
|
||||
WIREGUARD_PRIVATE_KEY=
|
||||
# Example: 10.64.0.2/32
|
||||
WIREGUARD_ADDRESSES=
|
||||
|
||||
# Server selection (one of the following is recommended)
|
||||
#SERVER_CITIES="Los Angeles"
|
||||
#SERVER_COUNTRIES="United States"
|
||||
|
||||
# Exact server pinning (optional; supports comma-separated list)
|
||||
# For Jakarta example:
|
||||
#SERVER_HOSTNAMES=id-jpu-wg-001
|
||||
#SERVER_HOSTNAME=id-jpu-wg-001
|
||||
|
||||
# Updater period (optional)
|
||||
#UPDATER_PERIOD=24h
|
||||
|
||||
# Firewall rules (optional)
|
||||
# Allow outbound traffic to RFC1918 subnets so LAN services can be reached
|
||||
# Example: 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||
#FIREWALL_OUTBOUND_SUBNETS=
|
||||
|
||||
# If you need to accept inbound connections through Gluetun (e.g., expose qBittorrent UI),
|
||||
# publish the port in Terraform and optionally set FIREWALL_INPUT_PORTS as well
|
||||
#FIREWALL_INPUT_PORTS=8080
|
||||
65
modules/20-services-apps/gluetun/README.md
Normal file
65
modules/20-services-apps/gluetun/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Gluetun (Mullvad Wireguard)
|
||||
|
||||
This module runs Gluetun to provide a VPN network stack for other containers.
|
||||
You can route qBittorrent through Gluetun by setting its `network_mode` to `container:gluetun` using the provided toggle in the qBittorrent module.
|
||||
|
||||
- Image: `qmcgaw/gluetun:v3.39.0`
|
||||
- Requires: NET_ADMIN capability and `/dev/net/tun` device
|
||||
- Default: No ports exposed on host. Publish only if you need host access.
|
||||
- Attach Gluetun to the same Docker network as services that should reach apps running through it (e.g., `media-network`).
|
||||
|
||||
## Usage
|
||||
|
||||
Example in `services/main.tf`:
|
||||
|
||||
```hcl
|
||||
module "gluetun" {
|
||||
source = "${local.module_dir}/20-services-apps/gluetun"
|
||||
volume_path = "${local.volume_host}/gluetun"
|
||||
networks = [module.media_docker_network.name]
|
||||
# Optionally expose qBittorrent's Web UI to the host via Gluetun:
|
||||
# ports = [{ internal = 8080, external = 8080, protocol = "tcp" }]
|
||||
}
|
||||
|
||||
module "qbittorrent" {
|
||||
source = "${local.module_dir}/20-services-apps/qbittorrent"
|
||||
volume_path = "${local.volume_host}/qbittorrent"
|
||||
downloads_path = "${local.data_host}/torrents"
|
||||
networks = [module.media_docker_network.name]
|
||||
connect_via_gluetun = true
|
||||
gluetun_container_name = "gluetun"
|
||||
}
|
||||
|
||||
module "arr" {
|
||||
source = "${local.module_dir}/20-services-apps/arr"
|
||||
volume_path = "${local.volume_host}/arr"
|
||||
data_path = local.data_host
|
||||
downloads_path = "${local.data_host}/torrents"
|
||||
networks = [module.media_docker_network.name]
|
||||
proxy_networks = [module.homelab_docker_network.name]
|
||||
qbittorrent_host = "gluetun" # arr containers will reach qBt at http://gluetun:8080
|
||||
}
|
||||
```
|
||||
|
||||
## Environment variables
|
||||
|
||||
Place a `.env` file in this module directory (`modules/20-services-apps/gluetun/.env`). See `.env.example` for all options. Key variables:
|
||||
|
||||
- VPN_SERVICE_PROVIDER=mullvad
|
||||
- VPN_TYPE=wireguard
|
||||
- WIREGUARD_PRIVATE_KEY=... (required)
|
||||
- WIREGUARD_ADDRESSES=10.64.0.2/32 (example)
|
||||
- SERVER_CITIES=... or SERVER_COUNTRIES=...
|
||||
- SERVER_HOSTNAMES=id-jpu-wg-001 (optional exact server pin; supports comma-separated list)
|
||||
- UPDATER_PERIOD=24h (optional)
|
||||
- FIREWALL_OUTBOUND_SUBNETS=10.0.0.0/8,192.168.0.0/16 (optional; allow containers to reach LAN subnets)
|
||||
- Optional: `FIREWALL_INPUT_PORTS=8080` if you need other containers/LAN to initiate connections to services through Gluetun.
|
||||
|
||||
Notes:
|
||||
- When qBittorrent shares Gluetun's network, other containers should use `http://gluetun:8080`.
|
||||
- To access qBittorrent UI from the host, publish `8080/tcp` on Gluetun via this module's `ports` input or set `FIREWALL_INPUT_PORTS` accordingly.
|
||||
- Do not publish ports on qBittorrent when using Gluetun network mode; publish on Gluetun instead.
|
||||
|
||||
Pinning a specific server:
|
||||
- Set `SERVER_HOSTNAMES=id-jpu-wg-001` to pin to Mullvad Jakarta `id-jpu-wg-001`.
|
||||
- The module also accepts `SERVER_HOSTNAME` for compatibility (falls back to it if `SERVER_HOSTNAMES` is not set).
|
||||
88
modules/20-services-apps/gluetun/main.tf
Normal file
88
modules/20-services-apps/gluetun/main.tf
Normal file
@@ -0,0 +1,88 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
dotenv = { source = "germanbrew/dotenv" }
|
||||
}
|
||||
}
|
||||
|
||||
variable "volume_path" {
|
||||
description = "Base directory for Gluetun state/config mounted at /gluetun"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "networks" {
|
||||
description = "Networks to attach Gluetun to"
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "ports" {
|
||||
description = "Ports to publish on the Gluetun container (used to reach services connected via network_mode: container:gluetun)"
|
||||
type = list(object({
|
||||
internal = number
|
||||
external = number
|
||||
protocol = string
|
||||
}))
|
||||
// Default to no published ports. Publish only if you need host access.
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "image_tag" {
|
||||
description = "Gluetun image tag"
|
||||
type = string
|
||||
default = "v3.39.0"
|
||||
}
|
||||
|
||||
locals {
|
||||
env_file = "${path.module}/.env"
|
||||
container_name = "gluetun"
|
||||
image = "qmcgaw/gluetun"
|
||||
tag = var.image_tag
|
||||
monitoring = true
|
||||
|
||||
// Gluetun environment
|
||||
env_vars = {
|
||||
VPN_SERVICE_PROVIDER = try(provider::dotenv::get_by_key("VPN_SERVICE_PROVIDER", local.env_file), "mullvad")
|
||||
VPN_TYPE = try(provider::dotenv::get_by_key("VPN_TYPE", local.env_file), "wireguard")
|
||||
WIREGUARD_PRIVATE_KEY = provider::dotenv::get_by_key("WIREGUARD_PRIVATE_KEY", local.env_file)
|
||||
WIREGUARD_ADDRESSES = provider::dotenv::get_by_key("WIREGUARD_ADDRESSES", local.env_file)
|
||||
SERVER_CITIES = try(provider::dotenv::get_by_key("SERVER_CITIES", local.env_file), "")
|
||||
SERVER_COUNTRIES = try(provider::dotenv::get_by_key("SERVER_COUNTRIES", local.env_file), "")
|
||||
SERVER_HOSTNAMES = try(
|
||||
provider::dotenv::get_by_key("SERVER_HOSTNAMES", local.env_file),
|
||||
try(provider::dotenv::get_by_key("SERVER_HOSTNAME", local.env_file), "")
|
||||
)
|
||||
UPDATER_PERIOD = try(provider::dotenv::get_by_key("UPDATER_PERIOD", local.env_file), "")
|
||||
FIREWALL_OUTBOUND_SUBNETS = try(provider::dotenv::get_by_key("FIREWALL_OUTBOUND_SUBNETS", local.env_file), "")
|
||||
}
|
||||
|
||||
volumes = [
|
||||
{
|
||||
host_path = var.volume_path,
|
||||
container_path = "/gluetun",
|
||||
read_only = false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
module "gluetun" {
|
||||
source = "../../10-services-generic/docker-service"
|
||||
container_name = local.container_name
|
||||
image = local.image
|
||||
tag = local.tag
|
||||
env_vars = local.env_vars
|
||||
volumes = local.volumes
|
||||
networks = var.networks
|
||||
monitoring = local.monitoring
|
||||
|
||||
// Grant minimal privileges required by Gluetun
|
||||
capabilities_add = ["NET_ADMIN"]
|
||||
devices = [
|
||||
{
|
||||
host_path = "/dev/net/tun"
|
||||
container_path = "/dev/net/tun"
|
||||
permissions = "rwm"
|
||||
}
|
||||
]
|
||||
|
||||
ports = var.ports
|
||||
}
|
||||
Reference in New Issue
Block a user