nixos/modules/services/reverseproxy.nix

276 lines
7.9 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
pkgs,
lib,
config,
...
}:
let
cfg = config.crans.reverseProxy;
formatJSON = pkgs.formats.json { };
allowAll = formatJSON.generate "allow_all.json" {
bots = [
{
name = "allow_all";
path_regex = ".*";
action = "ALLOW";
}
];
};
open_graph = formatJSON.generate "opengraph.json" {
openGraph = [
{
enabled = true;
considerHost = true;
ttl = "24h";
}
];
};
mainTld = "org";
otherTld = [
"fr"
"eu"
];
inherit (lib)
literalExpression
mkEnableOption
mkIf
mkOption
types
;
in
{
options.crans.reverseProxy = {
enable = mkEnableOption "Configuration du reverseproxy.";
virtualHosts = mkOption {
type = types.attrsOf (
types.submodule {
options = {
serverAliases = mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"everything"
"voyager"
];
description = ''
Déclaration des alias.
'';
};
proxyPass = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Indique la destination à proxy.
'';
example = "172.16.10.128:8000";
};
serveLocalFiles = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Chemin vers un dossier à exposer statiquement.
'';
example = "/var/local/adopter-un-manchot";
};
globalRedirect = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Si définie, toutes les requêtes sont redirigées (via 301) sur cet hôte.
'';
example = "perso.crans.org/club";
};
anubisConfig = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Chemin du fichier de configuration
'';
example = "/var/www/anubis.conf";
};
anubisOpenGraph = mkOption {
type = types.bool;
default = true;
description = ''
Activer openGraph pour l'indexation et l'embedding
'';
};
httpOnly = mkOption {
type = types.bool;
default = false;
description = ''
Interdit les connexions en https
'';
example = "true";
};
proxyWebsockets = mkOption {
type = types.bool;
default = false;
description = ''
Activer les websockets
'';
example = "true";
};
};
}
);
default = { };
example = literalExpression ''
{
"framadate" = {
host = "176.16.10.128:8000";
serverAliases = [
"everything"
"voyager"
]
};
};
'';
description = "Déclaration des machines.";
};
};
config = {
systemd.services = lib.mapAttrs (vhostName: vhostConfig: {
wantedBy = [ "multi-user.target" ];
}) cfg.virtualHosts;
services = mkIf cfg.enable {
anubis = {
defaultOptions.group = "nginx";
instances = lib.mapAttrs (
vhostName: vhostConfig:
mkIf (vhostConfig.anubisConfig != null) {
enable = true;
settings = {
BIND = "/run/anubis/anubis-${vhostName}/socket.sock";
BIND_NETWORK = "unix";
METRICS_BIND = "/run/anubis/anubis-${vhostName}/anubis-${vhostName}-metrics.sock";
TARGET = "unix:///run/nginx/nginx-${vhostName}.sock";
COOKIE_DOMAIN = "crans.org";
REDIRECT_DOMAINS = "${vhostName}.crans.org";
SOCKET_MODE = "0660";
# OpenGraph config
OG_PASSTHROUGH = vhostConfig.anubisOpenGraph;
OG_EXPIRY_TIME = "24h";
OG_CACHE_CONSIDER_HOST = true;
# Policy config
POLICY_FNAME = vhostConfig.anubisConfig;
};
}
) cfg.virtualHosts;
};
nginx =
let
configVhost =
vhostName: vhostConfig:
let
sslConf = {
enableACME = !vhostConfig.httpOnly;
forceSSL = !vhostConfig.httpOnly;
rejectSSL = vhostConfig.httpOnly;
};
# Conf pour lhost en entrès
entryExtraConf = {
extraConfig = ''
set_real_ip_from 172.16.0.0/16;
set_real_ip_from fd00::/56;
real_ip_header X-Real-Ip;
'';
}
// sslConf;
# Conf supplémentaire pour le proxy principal
vhostExtraConf =
if vhostConfig.anubisConfig != null then
# Il reçoit les requêtes dAnubis
{
listen = [
{ addr = "unix:/run/nginx/nginx-${vhostName}.sock"; }
];
extraConfig = ''
set_real_ip_from unix:;
real_ip_header X-Real-IP;
'';
}
else
# Il est en entrée
entryExtraConf;
# Les alias : vhostName × otherTld U serverAliases × allTld
aliases =
lib.foldr
(
tld: acc:
acc
++ (lib.foldr (alias: acc: acc ++ [ "${alias}.crans.${tld}" ]) [
"${vhostName}.crans.${tld}"
] vhostConfig.serverAliases)
)
(lib.foldr (alias: acc: acc ++ [ "${alias}.crans.${mainTld}" ]) [ ] vhostConfig.serverAliases)
otherTld;
in
{
# Configuration du service à proxy.
"${vhostName}" = vhostExtraConf // {
serverName = "${vhostName}.crans.${mainTld}";
locations."/" = mkIf (vhostConfig.proxyPass != null) {
proxyPass = "http://${vhostConfig.proxyPass}";
proxyWebsockets = vhostConfig.proxyWebsockets;
};
root = vhostConfig.serveLocalFiles;
globalRedirect = vhostConfig.globalRedirect;
};
# Entrée dAnubis
"${vhostName}-anubis" = mkIf (vhostConfig.anubisConfig != null) (
entryExtraConf
// {
serverName = "${vhostName}.crans.${mainTld}";
locations."/" = {
proxyPass = "http://unix:/run/anubis/anubis-${vhostName}/socket.sock";
proxyWebsockets = vhostConfig.proxyWebsockets;
};
extraConfig = entryExtraConf.extraConfig + ''
access_log /var/log/nginx/anubis.access.log;
error_log /var/log/nginx/anubis.error.log;
'';
}
);
}
# Les alias
// lib.mergeAttrsList (
lib.map (alias: {
"${vhostName}-alias-${alias}" = sslConf // {
serverName = alias;
globalRedirect = vhostConfig.globalRedirect or "${vhostName}.crans.${mainTld}";
};
}) aliases
);
in
{
enable = true;
virtualHosts = lib.concatMapAttrs configVhost cfg.virtualHosts;
};
};
};
}