[timetagger,traefik] Adds timetagger back, and attempts to put it behind an oauth proxy, but the traefik config isn't quite right.
This commit is contained in:
@@ -21,41 +21,62 @@ in
|
||||
havenisms
|
||||
blazestar
|
||||
terakoda
|
||||
terakoda_net;
|
||||
terakoda_net
|
||||
;
|
||||
|
||||
mkContainer = {
|
||||
image,
|
||||
hostName,
|
||||
port,
|
||||
homepageOpts ? {},
|
||||
dependsOn ? [],
|
||||
domain ? havenisms,
|
||||
ports ? [],
|
||||
volumes ? [],
|
||||
environment ? {},
|
||||
environmentFiles ? [],
|
||||
public ? false,
|
||||
user ? null,
|
||||
extraOptions ? [],
|
||||
}:
|
||||
mkContainer =
|
||||
{
|
||||
image,
|
||||
hostName,
|
||||
port,
|
||||
homepageOpts ? { },
|
||||
dependsOn ? [ ],
|
||||
domain ? havenisms,
|
||||
ports ? [ ],
|
||||
volumes ? [ ],
|
||||
environment ? { },
|
||||
environmentFiles ? [ ],
|
||||
public ? false,
|
||||
user ? null,
|
||||
extraOptions ? [ ],
|
||||
oauthProxy ? false,
|
||||
}:
|
||||
let
|
||||
routerRule = if public then hostRule hostName domain else localHostRule hostName domain;
|
||||
homepageLabels = if homepageOpts == {} then {} else {
|
||||
"homepage.group" = "${homepageOpts.group}";
|
||||
"homepage.name" = "${homepageOpts.name}";
|
||||
"homepage.icon" = "${homepageOpts.icon}";
|
||||
"homepage.href" = "https://${hostName}.${domain}";
|
||||
"homepage.description" = "${homepageOpts.description}";
|
||||
};
|
||||
homepageLabels =
|
||||
if homepageOpts == { } then
|
||||
{ }
|
||||
else
|
||||
{
|
||||
"homepage.group" = "${homepageOpts.group}";
|
||||
"homepage.name" = "${homepageOpts.name}";
|
||||
"homepage.icon" = "${homepageOpts.icon}";
|
||||
"homepage.href" = "https://${hostName}.${domain}";
|
||||
"homepage.description" = "${homepageOpts.description}";
|
||||
};
|
||||
oauthLabels =
|
||||
if oauthProxy then { "traefik.http.routers.${hostName}.middlewares" = "oidc-auth@file"; } else { };
|
||||
in
|
||||
{
|
||||
inherit image dependsOn volumes environment environmentFiles ports user extraOptions;
|
||||
inherit
|
||||
image
|
||||
dependsOn
|
||||
volumes
|
||||
environment
|
||||
environmentFiles
|
||||
ports
|
||||
user
|
||||
extraOptions
|
||||
;
|
||||
autoStart = true;
|
||||
labels = {
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.${hostName}.rule" = "${routerRule}";
|
||||
"traefik.http.services.${hostName}.loadbalancer.server.port" = "${toString port}";
|
||||
} // homepageLabels;
|
||||
labels =
|
||||
{
|
||||
"traefik.enable" = "true";
|
||||
"traefik.http.routers.${hostName}.rule" = "${routerRule}";
|
||||
"traefik.http.services.${hostName}.loadbalancer.server.port" = "${toString port}";
|
||||
}
|
||||
// oauthLabels
|
||||
// homepageLabels;
|
||||
};
|
||||
|
||||
# Creates a MariaDB container for a specific app. It should be safe to give
|
||||
@@ -64,60 +85,64 @@ in
|
||||
# user.
|
||||
#
|
||||
# Note that this returns a _module_ so that it can be imported and provide many different config values.
|
||||
mkMariaDbContainer = {
|
||||
name,
|
||||
uid,
|
||||
gid,
|
||||
passwordSecret,
|
||||
directory,
|
||||
}:
|
||||
{ config, ... }:
|
||||
{
|
||||
virtualisation.oci-containers.containers."${name}-mariadb" = {
|
||||
image = "lscr.io/linuxserver/mariadb:latest";
|
||||
autoStart = true;
|
||||
ports = [ "3306:3306" ];
|
||||
volumes = [
|
||||
"${directory}:/config"
|
||||
"${config.sops.secrets.mariadb_root_password.path}:/run/secrets/mariadb_root_password"
|
||||
"${config.sops.secrets."${passwordSecret}".path}:/run/secrets/mariadb_password"
|
||||
];
|
||||
environment = {
|
||||
PUID = "${toString uid}";
|
||||
PGID = "${toString gid}";
|
||||
MYSQL_USER = name;
|
||||
MYSQL_DATABASE = name;
|
||||
FILE__MYSQL_ROOT_PASSWORD = "/run/secrets/mariadb_root_password";
|
||||
FILE__MYSQL_PASSWORD = "/run/secrets/mariadb_password";
|
||||
mkMariaDbContainer =
|
||||
{
|
||||
name,
|
||||
uid,
|
||||
gid,
|
||||
passwordSecret,
|
||||
directory,
|
||||
}:
|
||||
{ config, ... }:
|
||||
{
|
||||
virtualisation.oci-containers.containers."${name}-mariadb" = {
|
||||
image = "lscr.io/linuxserver/mariadb:latest";
|
||||
autoStart = true;
|
||||
ports = [ "3306:3306" ];
|
||||
volumes = [
|
||||
"${directory}:/config"
|
||||
"${config.sops.secrets.mariadb_root_password.path}:/run/secrets/mariadb_root_password"
|
||||
"${config.sops.secrets."${passwordSecret}".path}:/run/secrets/mariadb_password"
|
||||
];
|
||||
environment = {
|
||||
PUID = "${toString uid}";
|
||||
PGID = "${toString gid}";
|
||||
MYSQL_USER = name;
|
||||
MYSQL_DATABASE = name;
|
||||
FILE__MYSQL_ROOT_PASSWORD = "/run/secrets/mariadb_root_password";
|
||||
FILE__MYSQL_PASSWORD = "/run/secrets/mariadb_password";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkPostgresContainer = {
|
||||
name,
|
||||
uid,
|
||||
gid,
|
||||
passwordSecret,
|
||||
directory,
|
||||
containerName ? "${name}-postgres",
|
||||
databaseName ? name,
|
||||
username ? name,
|
||||
}: { config, ... }: {
|
||||
virtualisation.oci-containers.containers."${containerName}" = {
|
||||
image = "postgres";
|
||||
autoStart = true;
|
||||
volumes = [
|
||||
# Note that data must be mounted at this location to persist.
|
||||
# See https://github.com/docker-library/docs/blob/master/postgres/README.md#pgdata
|
||||
"${directory}:/var/lib/postgresql/data"
|
||||
"${config.sops.secrets."${passwordSecret}".path}:/run/secrets/postgres_password"
|
||||
];
|
||||
user = "${toString uid}:${toString gid}";
|
||||
environment = {
|
||||
POSTGRES_USER = username;
|
||||
POSTGRES_DB = databaseName;
|
||||
POSTGRES_PASSWORD_FILE = "/run/secrets/postgres_password";
|
||||
mkPostgresContainer =
|
||||
{
|
||||
name,
|
||||
uid,
|
||||
gid,
|
||||
passwordSecret,
|
||||
directory,
|
||||
containerName ? "${name}-postgres",
|
||||
databaseName ? name,
|
||||
username ? name,
|
||||
}:
|
||||
{ config, ... }:
|
||||
{
|
||||
virtualisation.oci-containers.containers."${containerName}" = {
|
||||
image = "postgres";
|
||||
autoStart = true;
|
||||
volumes = [
|
||||
# Note that data must be mounted at this location to persist.
|
||||
# See https://github.com/docker-library/docs/blob/master/postgres/README.md#pgdata
|
||||
"${directory}:/var/lib/postgresql/data"
|
||||
"${config.sops.secrets."${passwordSecret}".path}:/run/secrets/postgres_password"
|
||||
];
|
||||
user = "${toString uid}:${toString gid}";
|
||||
environment = {
|
||||
POSTGRES_USER = username;
|
||||
POSTGRES_DB = databaseName;
|
||||
POSTGRES_PASSWORD_FILE = "/run/secrets/postgres_password";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
50
system/hosts/mcp/containers/oauth2proxy.nix
Normal file
50
system/hosts/mcp/containers/oauth2proxy.nix
Normal file
@@ -0,0 +1,50 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
inherit (import ./lib.nix config) mkContainer blazestar havenisms;
|
||||
in
|
||||
{
|
||||
sops.secrets = {
|
||||
"oauth2-proxy/cookie-secret" = {
|
||||
restartUnits = [ "podman-oauth2-proxy.service" ];
|
||||
mode = "0400";
|
||||
};
|
||||
"oauth2-proxy/client-secret" = {
|
||||
restartUnits = [ "podman-oauth2-proxy.service" ];
|
||||
mode = "0400";
|
||||
};
|
||||
};
|
||||
|
||||
sops.templates."oauth2-proxy.env".content = ''
|
||||
OAUTH2_PROXY_HTTP_ADDRESS='0.0.0.0:4180'
|
||||
OAUTH2_PROXY_COOKIE_SECRET='${config.sops.placehoder."oauth2-proxy/cookie-secret"}'
|
||||
OAUTH2_PROXY_COOKIE_DOMAINS='.${blazestar} .${havenisms}'
|
||||
OAUTH2_PROXY_WHITELIST_DOMAINS='.${blazestar} .${havenisms}'
|
||||
OAUTH2_PROXY_PROVIDER='oidc'
|
||||
OAUTH2_PROXY_CLIENT_ID='oauth2-proxy'
|
||||
OAUTH2_PROXY_CLIENT_SECRET='${config.sops.placehoder."oauth2-proxy/client-secret"}'
|
||||
OAUTH2_PROXY_EMAIL_DOMAINS='*'
|
||||
OAUTH2_PROXY_OIDC_ISSUER_URL='https://auth.${blazestar}/realms/master'
|
||||
OAUTH2_PROXY_REDIRECT_URL='https://auth.${blazestar}/oauth2/callback'
|
||||
OAUTH2_PROXY_COOKIE_CSRF_PER_REQUEST=true
|
||||
OAUTH2_PROXY_COOKIE_CSRF_EXPIRE='5m'
|
||||
OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR="/templates"
|
||||
OAUTH2_PROXY_REVERSE_PROXY=true
|
||||
'';
|
||||
|
||||
virtualisation.oci-containers.containers.oauth2-proxy = mkContainer {
|
||||
image = "quay.io/oauth2-proxy/oauth2-proxy";
|
||||
hostName = "oauth";
|
||||
domain = blazestar;
|
||||
port = "4180";
|
||||
homepageOpts = {
|
||||
group = "Infra";
|
||||
name = "OAuth2-Proxy";
|
||||
icon = "oauth2-proxy.png";
|
||||
description = "An OAuth2 Reverse Proxy";
|
||||
};
|
||||
volumes = [
|
||||
];
|
||||
environment = {
|
||||
};
|
||||
};
|
||||
}
|
||||
31
system/hosts/mcp/containers/timetagger.nix
Normal file
31
system/hosts/mcp/containers/timetagger.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
inherit (import ./lib.nix config) mkContainer terakoda_net;
|
||||
in
|
||||
{
|
||||
virtualisation.oci-containers.containers.timetagger = mkContainer {
|
||||
image = "ghcr.io/almarklein/timetagger:v24.12.2";
|
||||
hostName = "time";
|
||||
domain = terakoda_net;
|
||||
port = "80";
|
||||
oauthProxy = true;
|
||||
homepageOpts = {
|
||||
group = "Apps";
|
||||
name = "TimeTagger";
|
||||
icon = "timetagger.png";
|
||||
description = "Time tracker";
|
||||
|
||||
};
|
||||
volumes = [
|
||||
"/tank/config/timetagger:/data"
|
||||
];
|
||||
environment = {
|
||||
TIMETAGGER_BIND = "0.0.0.0:80";
|
||||
TIMETAGGER_DATADIR = "/data";
|
||||
TIMETAGGER_LOG_LEVEL = "debug";
|
||||
TIMETAGGER_PROXY_AUTH_ENABLED = "True";
|
||||
TIMETAGGER_PROXY_AUTH_TRUSTED = "10.88.0.0/16";
|
||||
TIMETAGGER_PROXY_AUTH_HEADER = "X-Remote-User";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -5,28 +5,62 @@ let
|
||||
name = "traefik-config";
|
||||
path = ./traefik;
|
||||
};
|
||||
in {
|
||||
virtualisation.oci-containers.containers.traefik = mkContainer {
|
||||
image = "traefik";
|
||||
hostName = "proxy";
|
||||
port = 8080;
|
||||
domain = blazestar;
|
||||
public = false;
|
||||
ports = [
|
||||
"80:80"
|
||||
"443:443"
|
||||
];
|
||||
volumes =
|
||||
[
|
||||
"/var/run/podman/podman.sock:/var/run/docker.sock:ro"
|
||||
"${traefikConfigDir}:/etc/traefik"
|
||||
"/tank/config/traefik/acme:/etc/traefik/acme"
|
||||
];
|
||||
homepageOpts = {
|
||||
name = "Traefik";
|
||||
icon = "traefik.svg";
|
||||
group = "Infra";
|
||||
description = "Reverse Proxy";
|
||||
};
|
||||
in
|
||||
{
|
||||
|
||||
sops.secrets = {
|
||||
"traefik/oauth2-client-secret" = {
|
||||
restartUnits = [ "podman-traefik.service" ];
|
||||
mode = "0400";
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
sops.templates."traefik/oauth2-config.yaml".content = ''
|
||||
experimental:
|
||||
plugins:
|
||||
traefik-oidc-auth:
|
||||
moduleName: "github.com/sevensolutions/traefik-oidc-auth"
|
||||
version: "v0.11.0"
|
||||
|
||||
http:
|
||||
middlewares:
|
||||
oidc-auth:
|
||||
plugin:
|
||||
traefik-oidc-auth:
|
||||
Provider:
|
||||
Url: "https://auth.blazestar.net/"
|
||||
ClientId: "3e3f7d9a-a684-4412-866c-ea7281954a9f"
|
||||
ClientSecret: "${config.sops.placeholder."traefik/oauth2-client-secret"}"
|
||||
TokenValidation: "IdToken"
|
||||
Scopes: ["openid", "profile", "email"]
|
||||
'';
|
||||
|
||||
virtualisation.oci-containers.containers.traefik = mkContainer {
|
||||
image = "traefik";
|
||||
hostName = "proxy";
|
||||
port = 8080;
|
||||
domain = blazestar;
|
||||
public = false;
|
||||
ports = [
|
||||
"80:80"
|
||||
"443:443"
|
||||
];
|
||||
volumes = [
|
||||
"/var/run/podman/podman.sock:/var/run/docker.sock:ro"
|
||||
# All the configs from the config directory
|
||||
"${traefikConfigDir}:/etc/traefik"
|
||||
# Oauth2 config containing secrets
|
||||
"${config.sops.templates."traefik/oauth2-config.yaml".path}:/etc/traefik/dynamic/oauth2-config.yaml"
|
||||
# Persistent storage for acme certificates
|
||||
# TODO: It may be possible to just use docker storage because persistence
|
||||
# is not critical when the cert can just be renewed.
|
||||
"/tank/config/traefik/acme:/etc/traefik/acme"
|
||||
];
|
||||
homepageOpts = {
|
||||
name = "Traefik";
|
||||
icon = "traefik.svg";
|
||||
group = "Infra";
|
||||
description = "Reverse Proxy";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ providers:
|
||||
docker:
|
||||
exposedByDefault: false
|
||||
file:
|
||||
directory: /etc/traefik/static
|
||||
directory: /etc/traefik/dynamic
|
||||
watch: true
|
||||
|
||||
certificatesResolvers:
|
||||
|
||||
Reference in New Issue
Block a user