blob: 1fce41b2c29c0e372aef8dbe4f8f996ad070cbe9 [file] [log] [blame]
{ pkgs, ... }: let
lib = pkgs.lib;
in {
Host = host: service: {
inherit host service;
extraHosts = [];
secure = true;
type = "hosts";
};
Hosts = hosts: service: {
inherit service;
host = elemAt hosts 0;
extraHosts = tail hosts;
secure = true;
type = "hosts";
};
InsecureHost = host: service: {
inherit host service;
extraHosts = [];
secure = false;
type = "hosts";
};
InsecureHosts = hosts: service: {
inherit service;
host = elemAt hosts 0;
extraHosts = tail hosts;
secure = false;
type = "hosts";
};
ReverseProxy = to: {
inherit to;
type = "reverseproxy";
};
PHP = root: socket: {
inherit root socket;
type = "php";
};
Redirect = to: permanent: {
inherit to permanent;
type = "redirect";
};
Directory = root: {
inherit root;
private = false;
type = "directory";
};
PrivateDirectory = root: {
inherit root;
private = true;
type = "directory";
};
File = path: {
inherit path;
type = "file";
};
Compose = services: {
inherit services;
type = "compose";
};
Path = path: service: {
inherit path service;
type = "path";
};
Merge = let
# builtins.length and count up
_iterateCompose = services: currentConfig: currentPath: secure: priority: i:
if i > length services
then currentConfig
else _iterateCompose services (_merge (elemAt services i) currentConfig currentPath secure priority+i) currentPath secure priority (i+1);
_iterateMerge = i: current: services:
if i > length services
then current
else _iterateMerge (i+1) (current++[_merge (elemAt services i) {} "/" true 1000]) services;
_merge = service: currentConfig: currentPath: secure: priority:
if service.type == "hosts"
then _merge service.service (lib.mkMerge currentConfig {
name = service.host;
value = {
serverAliases = service.extraHosts;
enableACME = service.secure;
forceSSL = service.secure;
listen = [
{
addr = "0.0.0.0";
port = if service.secure then 443 else 80;
ssl = service.secure;
}
];
};
}) currentPath service.secure priority
else if service.type == "reverseproxy"
then (lib.mkMerge currentConfig {
value.locations.${currentPath} = {
proxyPass = service.to;
proxyWebsockets = true;
recommendedProxySettings = true;
};
})
else if service.type == "php"
then (lib.mkMerge currentConfig {
value.locations.${currentPath} = {
root = service.root;
index = "index.php index.html index.htm";
tryFiles = "$uri $uri/ ${currentPath}index.php?$query_string =404";
};
value.locations."~ ^${currentPath}.*\.php$" = {
tryFiles = "$uri $uri/ ${currentPath}index.php?$query_string =404";
extraConfig = ''
include ${pkgs.nginx}/conf/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param REDIRECT_STATUS 200;
fastcgi_pass unix:${service.socket};
fastcgi_intercept_errors on;
${lib.optionalString secure "fastcgi_param HTTPS on;"}
'';
};
})
else if service.type == "redirect"
then (lib.mkMerge currentConfig {
value.locations.${currentPath}.return =
if service.permanent
then "308 ${service.to}"
else "307 ${service.to}";
})
else if service.type == "directory"
then (lib.mkMerge currentConfig {
value.locations.${currentPath} = {
root = service.root;
index = "index.html index.htm";
tryFiles = "$uri $uri/ =404";
extraConfig = lib.optionalString !service.private "autoindex on;";
};
})
else if service.type == "file"
then (lib.mkMerge currentConfig {
value.locations.${currentPath} = {
tryFiles = "${service.path} =404";
};
})
else if service.type == "path"
then _merge service.service currentConfig service.path service.secure
else if service.type == "compose"
then (_iterateCompose service.services currentConfig currentPath secure priority 0)
else throw "Unknown service type: ${service.type}";
in (services: lib.pipe services [
(_iterateMerge 0 [])
builtins.listToAttrs
]);
# https://www.nginx.com/resources/wiki/start/topics/examples/full/
/**
Internal needs to be a string that is both a host and a port, e.g. generic:1000
External should only be a port
Protocol should be TCP or UDP
*/
Stream = external: internal: protocol: ''
server {
listen ${builtins.toString external} ${protocol};
proxy_pass ${internal};
}
'';
Alias = host: alias: {
inherit host;
aliases = [ alias ];
type = "aliases";
};
Aliases = host: aliases: {
inherit host aliases;
type = "aliases";
};
}