Files
server-config/containers/server-n0/nginx.nix
T
d9b4bab1f8
diff-tag / dix (push) Successful in 6m33s
flake-check / flake-check (push) Successful in 59s
lint / lint (push) Successful in 1m47s
Fix flake update (#11)
Co-authored-by: flowey <floweydev@gmail.com>
Co-authored-by: gitea-actions[bot] <gitea-actions@noreply.local>
Reviewed-on: #11
2026-09-22 21:44:25 +00:00

211 lines
5.9 KiB
Nix

{
name,
hostInfo,
dsl,
lib,
containers,
...
}:
let
inherit (dsl) mkContainer collectContainers;
inherit (hostInfo.paths) data;
mkNginxConfig =
{
email,
vhosts,
resolver,
}:
let
mkVhostEntries =
{
domain,
upstream ? null,
websockets ? true,
redirect ? true,
listenHttp ? false,
extraLocations ? { },
}:
let
httpsListen = {
addr = "0.0.0.0";
port = 443;
ssl = true;
};
httpListen = {
addr = "0.0.0.0";
port = 80;
ssl = false;
};
defaultLoc = lib.optionalAttrs (upstream != null) {
"/" = {
proxyWebsockets = websockets;
extraConfig = ''
set $backend "${upstream.container.name}:${toString upstream.port}";
proxy_pass http://$backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $hostname;
'';
};
};
acmePrimaryOnMain = !redirect && listenHttp;
mainVhost = lib.nameValuePair domain (
{
listen = [ httpsListen ] ++ lib.optional listenHttp httpListen;
locations = defaultLoc // extraLocations;
}
// (
if acmePrimaryOnMain then
{
addSSL = true;
enableACME = true;
}
else
{
onlySSL = true;
useACMEHost = domain;
}
)
);
redirectVhost = lib.nameValuePair "${domain}-redirect" {
serverName = domain;
enableACME = true;
listen = [ httpListen ];
locations = {
"/" = {
return = "301 https://$host$request_uri";
};
};
};
in
[ mainVhost ] ++ lib.optional redirect redirectVhost;
in
{
access = map (v: {
to = v.upstream.container.name;
tcp = [ v.upstream.port ];
}) (lib.filter (v: v.upstream or null != null) vhosts);
containerConfig =
{
lib,
config,
...
}:
{
services.nginx = {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
clientMaxBodySize = "100M";
appendHttpConfig = ''
access_log syslog:server=unix:/dev/log,tag=nginx combined;
'';
resolver = {
addresses = [ resolver ];
ipv6 = false;
valid = "30s";
};
virtualHosts = lib.listToAttrs (lib.concatLists (map mkVhostEntries vhosts)) // {
"_" = {
listen = [
{
addr = "0.0.0.0";
port = 443;
extraParameters = [
"ssl"
"default_server"
];
}
{
addr = "0.0.0.0";
port = 80;
extraParameters = [ "default_server" ];
}
];
extraConfig = "ssl_reject_handshake on;";
locations."/".return = "404";
};
};
};
security.acme = {
acceptTerms = true;
defaults.email = email;
};
systemd.services =
lib.mapAttrs' (
cert: _:
lib.nameValuePair "acme-${cert}" {
after = [ "container-ready.target" ];
wants = [ "container-ready.target" ];
}
) config.security.acme.certs
// {
nginx.serviceConfig.FailureAction = "exit-force";
};
};
};
up = container: port: { inherit container port; };
discovered = collectContainers "nginx" containers;
discoveredVhosts = map (
{ container, data }:
{
inherit (data) domain;
}
// lib.optionalAttrs (data ? port) { upstream = up container data.port; }
// lib.optionalAttrs (data ? websockets) { inherit (data) websockets; }
// lib.optionalAttrs (data ? redirect) { inherit (data) redirect; }
// lib.optionalAttrs (data ? listenHttp) { inherit (data) listenHttp; }
// lib.optionalAttrs (data ? extraLocations) { inherit (data) extraLocations; }
) discovered;
extraVhosts = [
{
domain = "utils.floweytf.com";
redirect = false;
listenHttp = true;
extraLocations = {
"/static/" = {
alias = "/usr/share/nginx/static/";
extraConfig = "autoindex on;";
};
};
}
];
upstreamContainers = map (e: e.container) (lib.filter ({ data, ... }: data ? port) discovered);
setup = mkNginxConfig {
email = "floweydev@gmail.com";
resolver = hostAddr;
vhosts = discoveredVhosts ++ extraVhosts;
};
c = mkContainer {
inherit name;
net.access = setup.access ++ [ { to = "@internet"; } ];
svc.autoStart = true;
svc.depends = upstreamContainers;
net.forward.tcp = [
80
443
];
resources.fs."/var/lib/acme" = {
hostPath = "${data}/core/nginx/acme";
isReadOnly = false;
};
miscProperties.acmeDomains = map (v: v.domain) (discoveredVhosts ++ extraVhosts);
inherit (setup) containerConfig;
};
inherit (c) hostAddr;
in
c