infrastructure/nixos/access/proxmox.nix

126 lines
3.6 KiB
Nix

{
config,
lib,
...
}: let
inherit (lib.options) mkOption;
inherit (lib.modules) mkIf mkMerge mkDefault;
inherit (lib.strings) escapeRegex;
inherit (lib.lists) singleton optional;
inherit (config.lib.access) mkSnakeOil;
inherit (config.services) nginx tailscale;
inherit (nginx) virtualHosts;
access = config.services.nginx.access.proxmox;
proxyPass = "https://reisen.local.${config.networking.domain}:8006/";
unencrypted = mkSnakeOil {
name = "prox-local-cert";
domain =
singleton "prox.local.${config.networking.domain}"
++ optional tailscale.enable "prox.tail.${config.networking.domain}";
};
sslHost = {config, ...}: {
sslCertificate = mkIf (!config.enableACME && config.useACMEHost == null) unencrypted.fullchain;
sslCertificateKey = mkIf (!config.enableACME && config.useACMEHost == null) unencrypted.key;
};
in {
options.services.nginx.access.proxmox = with lib.types; {
domain = mkOption {
type = str;
default = "prox.${config.networking.domain}";
};
localDomain = mkOption {
type = str;
default = "prox.local.${config.networking.domain}";
};
tailDomain = mkOption {
type = str;
default = "prox.tail.${config.networking.domain}";
};
};
config.services.nginx.virtualHosts = let
locations."/" = {
extraConfig = ''
if ($http_x_forwarded_proto = http) {
return 302 https://$host$request_uri;
}
set $prox_prefix ''';
include ${config.sops.secrets.access-proxmox.path};
if ($request_uri ~ "^/([^/]+).*") {
set $prox_prefix $1;
}
if ($request_uri ~ "^/(pve2/.*|pwt/.*|api2/.*|xtermjs/.*|[^/]+\.js.*)") {
rewrite /(.*) /prox/$1 last;
}
if ($http_referer ~ "^https://prox\.${escapeRegex config.networking.domain}/([^/]+)/$") {
set $prox_prefix $1;
}
if ($prox_prefix != $prox_expected) {
return 501;
}
set $prox_plain ''';
if ($request_uri ~ "^/([^/]+)$") {
set $prox_plain $1;
}
if ($prox_plain = $prox_expected) {
return 302 https://$host/$prox_plain/;
}
if ($prox_plain != ''') {
rewrite /(.*) /prox/$1 last;
}
rewrite /[^/]+/(.*) /prox/$1;
rewrite /[^/]+$ /prox/;
'';
};
locations."/prox/" = {
inherit proxyPass;
extraConfig = ''
internal;
'';
};
locations."/prox/api2/" = {
proxy.websocket.enable = true;
proxyPass = "${proxyPass}api2/";
extraConfig = ''
internal;
'';
};
extraConfig = ''
client_max_body_size 16384M;
'';
in {
${access.domain} = {
inherit locations extraConfig;
};
${access.localDomain} = mkMerge [
{
inherit (virtualHosts.${access.domain}) useACMEHost;
local.enable = mkDefault true;
forceSSL = mkDefault true;
locations."/" = {
proxy.websocket.enable = true;
inherit proxyPass extraConfig;
};
}
sslHost
];
${access.tailDomain} = mkIf tailscale.enable (mkMerge [
{
inherit (virtualHosts.${access.domain}) useACMEHost;
addSSL = mkDefault true;
local.enable = mkDefault true;
locations."/" = {
proxy.websocket.enable = true;
inherit proxyPass extraConfig;
};
}
sslHost
]);
};
config.sops.secrets.access-proxmox = {
sopsFile = mkDefault ../secrets/access-proxmox.yaml;
owner = config.services.nginx.user;
inherit (nginx) group;
};
}