homelab-apps/services.jsonnet

183 lines
5.2 KiB
Plaintext

local optional(object, field) = std.get(object, field, {});
local dockerSocket = '/var/run/docker.sock:/var/run/docker.sock';
local tz = 'America/New_York';
local mediaEnv = {
PUID: 1000,
PGID: 1000,
TZ: tz,
};
local formatHelper(fmt) = function(name, option) fmt % [name, option];
local toList(fmt) = function(object) std.objectValues(std.mapWithKey(formatHelper(fmt), object));
local toLabels = toList('%s=%s');
local toVolumes = toList('%s:%s');
local toCommand = toList('--%s=%s');
local traefikLabels(name, host, port, extras) = toLabels({
'traefik.enable': 'true',
['traefik.http.routers.%s.rule' % name]: 'Host(`%s.mat`)' % host,
['traefik.http.routers.%s.entrypoints' % name]: 'web',
['traefik.http.services.%s.loadbalancer.server.port' % name]: port,
['traefik.http.routers.%s.service' % name]: '%s' % name,
'traefik.docker.network': 'traefik',
} + extras);
local mkService(name, svc) = svc {
container_name: name,
networks: ['traefik'],
volumes: toVolumes(optional(svc, 'volumes'))
+ toVolumes(optional(svc, 'mounts'))
+ if std.get(svc, 'docker', false)
then [dockerSocket]
else [],
labels: traefikLabels(name, std.get(svc, 'host', name), svc.webPort, optional(svc, 'traefik')),
restart: 'always',
};
local extractVolumes(cfg) = {
[name]: { external: true }
for name in std.flattenArrays([
std.objectFields(optional(svc, 'volumes'))
for svc in std.objectValues(cfg)
])
};
local Compose(cfg) = {
services: std.mapWithKey(mkService, cfg),
volumes: extractVolumes(cfg),
networks: { traefik: { external: true } },
};
local Port(port, src=port, kind='tcp') =
local mapped = '%d:%d' % [port, src];
'%s/%s' % [mapped, kind];
local MediaMounts(mounts) = {
['/media/mat/%s' % path]: mounts[path]
for path in std.objectFields(mounts)
};
local MediaService(name, tag='latest', env={}, mounts={}, webPort, ports=[]) = {
image: 'lscr.io/linuxserver/%s:%s' % [name, tag],
environment: mediaEnv + env,
volumes: { ['%s_config' % name]: '/config' },
mounts:: MediaMounts(mounts),
webPort:: webPort,
ports: ports,
};
function(secrets={})
Compose({
traefik: {
image: 'traefik:latest',
command: toCommand({
'log.level': 'ERROR',
'api.insecure': 'true',
'providers.docker': 'true',
'providers.docker.exposedbydefault': 'false',
'entrypoints.web.address': ':80',
// 'entrypoints.websecure.address': ':443',
}),
docker:: true,
webPort:: 80,
ports: [Port(80), /* Port(443), */ Port(8080)],
traefik:: {
// 'traefik.http.routers.http-catchall.rule': 'hostregexp(`{host:.+}`)'
// 'traefik.http.routers.http-catchall.entrypoints': 'web'
// 'traefik.http.routers.http-catchall.middlewares': 'redirect-to-https'
// 'traefik.http.middlewares.redirect-to-https.redirectscheme.scheme': 'https'
},
},
portainer: {
image: 'portainer/portainer-ce:latest',
docker:: true,
volumes: { portainer_data: '/data' },
webPort:: 9000,
ports: [Port(9443)],
},
deluge: MediaService(
name='deluge',
env={ DELUGE_LOGLEVEL: 'error' },
mounts={ torrents: '/downloads' },
webPort=8112,
ports=[Port(54979), Port(54979, kind='udp')],
),
prowlarr: MediaService(
name='prowlarr',
tag='develop',
webPort=9696,
mounts={
torrents: '/downloads',
'passport-5tb': '/passport-5tb',
'passport-1tb': '/passport-1tb',
},
),
bazarr: MediaService(
name='bazarr',
webPort=6767,
mounts={
'passport-5tb': '/passport-5tb',
'passport-1tb': '/passport-1tb',
},
),
radarr: MediaService(
name='radarr',
webPort=7878,
mounts={
'passport-5tb/movies': '/passport-5tb',
'passport-1tb/movies': '/passport-1tb',
torrents: '/downloads',
},
),
sonarr: MediaService(
name='sonarr',
webPort=8989,
mounts={
'passport-5tb/tv': '/passport-5tb',
'passport-1tb/tv': '/passport-1tb',
torrents: '/downloads',
}
),
plex: {
image: 'plexinc/pms-docker',
environment: {
TZ: tz,
PLEX_CLAIM: std.get(secrets, 'PLEX_CLAIM'),
ADVERTISE_IP: std.get(secrets, 'ADVERTISE_IP'),
},
volumes: { plex_config: '/config' },
mounts:: MediaMounts({
'torrents/plex-transcode': '/transcode',
'passport-5tb': '/passport-5tb',
'passport-1tb': '/passport-1tb',
}),
devices: ['/dev/dri:/dev/dri'],
webPort:: 32400,
ports: [
Port(56463, src=32400),
Port(3005),
Port(8324),
Port(32469),
Port(1900, kind='udp'),
Port(32410, kind='udp'),
Port(32412, kind='udp'),
Port(32413, kind='udp'),
Port(32414, kind='udp'),
],
},
archivebox: {
image: 'archivebox/archivebox:dev',
command: 'server --quick-init 0.0.0.0:8000',
environment: {
ALLOWED_HOSTS: '*',
MEDIA_MAX_SIZE: '750m',
RESOLUTION: '1024,768',
},
mounts:: MediaMounts({ 'passport-5tb/archivebox': '/data' }),
webPort:: 8000,
host:: 'archive',
},
})