factorisation reverse proxy

merge-requests/18/head
korenstin 2025-06-23 23:50:10 +02:00
parent 5d99a7fea1
commit f553309944
6 changed files with 389 additions and 98 deletions

View File

@ -22,6 +22,10 @@ Serveur Matrix, bridge IRC <-> Matrix et interface admin pour synapse, accessibl
Serveur redlib (client WEB alternatif pour Reddit), accessible à <https://redite.crans.org>.
## reverseproxy
Serveur qui héberge un reverseproxy et une instance de anubis.
## two
Serveur NixOS de test. Vous pouvez vous en servir comme base pour la configuration d'une nouvelle machine.

View File

@ -1,15 +1,70 @@
{ ... }:
{ pkgs, ... }:
{
let
anubisBotsMirror = pkgs.writeText "anubis_bots_mirror.yaml" ''
- name: whitelist-crans
action: ALLOW
remote_addresses:
- 185.230.79.0/22
- 2a0c:700::/32
- 46.105.102.188/32
- 2001:41d0:2:d5bc::/128
- name: no-user-agent-string
action: DENY
expression: userAgent == ""
- name: ban-gpt
user_agent_regex: ".*gpt.*"
action: DENY
- name: ban-bot
user_agent_regex: ".*(b|B)ot.*"
action: DENY
- name: ban-WebKit
action: DENY
expression:
all:
- userAgent.startsWith("Mozilla")
- userAgent.matches("AppleWebKit")
- userAgent.matches("Safari")
- userAgent.matches("Chrome")
- name: ban-Barkrowler
user_agent_regex: ".*Barkrowler.*"
action: DENY
'';
anubisMirror = pkgs.writeText "anubis_mirror.json" ''
{
"bots": [
{
"import": "${anubisBotsMirror}"
},
{
"name": "allow-repo",
"path_regex": "^...*",
"action": "ALLOW"
},
{
"name": "deny-other",
"path_regex": ".*",
"action": "ALLOW"
}
]
}
'';
in {
services.anubis = {
instances."muraille" = {
instances."mirror" = {
enable = true;
settings = {
BIND_NETWORK = "tcp";
BIND = "127.0.0.1:7777";
TARGET = "http://localhost:8888";
BIND = "127.0.0.1:7779";
TARGET = "http://localhost:8890";
COOKIE_DOMAIN = "crans.org";
REDIRECT_DOMAINS = "install-party.crans.org,mediawiki.crans.org,wiki.crans.org";
REDIRECT_DOMAINS = "eclat.crans.org,mirror.crans.org";
POLICY_FNAME = "${anubisMirror}";
};
};
};

View File

@ -1,10 +1,87 @@
{ ... }:
{ pkgs, ... }:
{
let
antibot = pkgs.writeText "antibot.yaml"
''
- name: whitelist-crans
action: ALLOW
remote_addresses:
- 185.230.79.0/22
- 2a0c:700::/32
- 46.105.102.188/32
- 2001:41d0:2:d5bc::/128
- name: no-user-agent-string
action: DENY
expression: userAgent == ""
- name: ban-gpt
user_agent_regex: ".*gpt.*"
action: DENY
- name: ban-bot
user_agent_regex: ".*(b|B)ot.*"
action: DENY
- name: ban-WebKit
action: CHALLENGE
expression:
all:
- userAgent.startsWith("Mozilla")
- userAgent.matches("AppleWebKit")
- userAgent.matches("Safari")
- userAgent.matches("Chrome")
- name: ban-Barkrowler
user_agent_regex: ".*Barkrowler.*"
action: DENY
'';
anubisChallenge = pkgs.writeText "anubis_challenge.json"
''
{
"bots": [
{
"import": "${antibot}"
},
{
"name": "challenge-other",
"path_regex": "^*",
"action": "CHALLENGE"
}
]
}
'';
anubisMirrors = pkgs.writeText "anubis_mirrors.json"
''
{
"bots": [
{
"import": "${antibot}"
},
{
"name": "deny-other",
"path_regex": ".*cdimage-.*",
"action": "ALLOW"
},
{
"name": "allow-repo",
"path_regex": "^...*",
"action": "ALLOW"
},
{
"name": "deny-other",
"path_regex": ".*",
"action": "CHALLENGE"
}
]
}
'';
in {
imports = [
./anubis.nix
./hardware-configuration.nix
./networking.nix
./anubis.nix
./reverseproxy.nix
];
@ -12,6 +89,8 @@
networking.hostName = "reverseproxy";
boot.loader.grub.devices = [ "/dev/sda" ];
users.users."nginx".home = "/var/lib/nginx";
crans = {
enable = true;
@ -27,6 +106,51 @@
resticClient.when = "03:42";
reverseProxy = {
enable = true;
virtualHosts = {
"eclats" = {
anubisConfig = "${anubisMirrors}";
target = "172.16.10.104";
};
"install-party" = {
anubisConfig = "${anubisChallenge}";
target = "/var/www/install-party.crans.org";
serverAliases = [
"i-p"
"adopteunmanchot"
"adopteunpingouin"
];
};
"mediawiki" = {
anubisConfig = "${anubisChallenge}";
target = "172.16.10.144";
serverAliases = [
"mediakiwi"
];
};
"mirrors" = {
anubisConfig = "${anubisMirrors}";
target = "172.16.10.104";
};
"perso" = {
anubisConfig = "${anubisChallenge}";
target = "172.16.10.31";
serverAliases = [
"clubs"
];
};
"wiki" = {
anubisConfig = "${anubisChallenge}";
target = "172.16.10.161";
serverAliases = [
"wikipedia"
];
};
};
};
services = {
acme.enable = true;
};

View File

@ -1,100 +1,53 @@
{ config, ... }:
{
users.users."nginx".home = "/var/lib/nginx";
services.nginx.virtualHosts = {
# redirection eclat
"eclat.crans.fr" = {
rejectSSL = true;
serverAliases = [
"eclat.crans.eu"
];
extraConfig = ''
return 301 http://eclat.crans.org$request_uri;
'';
};
services.nginx = {
enable = true;
virtualHosts =
let anubisConf = [
# redirection mirror
"mirror.crans.fr" = {
rejectSSL = true;
serverAliases = [
"mirror.crans.eu"
];
extraConfig = ''
return 301 http://mirror.crans.org$request_uri;
'';
};
# redirection anubis mirrors
"anubis-mirror" = {
rejectSSL = true;
locations."/" = {
proxyPass = "http://${config.services.anubis.instances."mirror".settings.BIND}";
};
serverName = "mirror.crans.org";
serverAliases = [
"eclat.crans.org"
];
};
# mirror
"mirror.crans.org" = {
locations."/".proxyPass = "http://172.16.10.104";
listen = [
{
addr = "localhost";
port = 8888;
port = 8890;
}
];
in {
# redirection install-party
"install-party.crans.fr" = {
enableACME = true;
forceSSL = true;
serverAliases = [
"i-p.crans.org"
"adopteunmanchot.crans.org"
"adopteunpingouin.crans.org"
"i-p.crans.fr"
"adopteunmanchot.crans.fr"
"adopteunpingouin.crans.fr"
"i-p.crans.eu"
"install-party.crans.eu"
"adopteunmanchot.crans.eu"
"adopteunpingouin.crans.eu"
"eclat.crans.org"
];
extraConfig = ''
return 301 https://install-party.crans.org$request_uri;
'';
};
# redirection mediawiki
"mediawiki.crans.fr" = {
enableACME = true;
forceSSL = true;
serverAliases = [
"mediakiwi.crans.org"
"mediakiwi.crans.fr"
"mediakiwi.crans.eu"
"mediawiki.crans.eu"
];
extraConfig = ''
return 301 https://mediawiki.crans.org$request_uri;
'';
};
# redirection wiki
"wiki.crans.fr" = {
enableACME = true;
forceSSL = true;
serverAliases = [
"wikipedia.crans.org"
"wikipedia.crans.fr"
"wikipedia.crans.eu"
"wiki.crans.eu"
];
extraConfig = ''
return 301 https://wiki.crans.org$request_uri;
'';
};
# redirection anubis
"anubis" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://${config.services.anubis.instances."muraille".settings.BIND}";
};
serverName = "install-party.crans.org";
serverAliases = [
"mediawiki.crans.org"
"wiki.crans.org"
];
};
# install-party
"install-party.crans.org" = {
root = "/var/www/install-party.crans.org";
listen = anubisConf;
};
# mediawiki
"mediawiki.crans.org" = {
locations."/".proxyPass = "http://172.16.10.144";
listen = anubisConf;
};
# wiki
"wiki.crans.org" = {
locations."/".proxyPass = "http://172.16.10.161";
listen = anubisConf;
};
};
};
}

View File

@ -6,5 +6,6 @@
./coturn.nix
./nginx.nix
./restic.nix
./reverseproxy.nix
];
}

View File

@ -0,0 +1,154 @@
{ pkgs, lib, config, ... }:
let
cfg = config.crans.reverseProxy;
allowAll = pkgs.writeText "allow_all.json"
''
{
"bots": [
{
"name": "allow_all",
"path_regex": ".*",
"action": "ALLOW"
}
]
}
'';
inherit (lib)
cartesianProduct
literalExpression
mapAttrs
mapAttrs'
mkEnableOption
mkIf
mkOption
nameValuePair
substring
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.
'';
};
target = mkOption {
type = types.str;
default = "";
description = ''
Indique la destination. Il peut s'agir du chemin vers des fichiers statiques.
'';
example = "172.16.10.128:8000";
};
anubisConfig = mkOption {
type = types.str;
default = "";
description = ''
Chemin du fichier de configuration
'';
example = "/var/www/anubis.conf";
};
};
}
);
default = {};
example = literalExpression ''
{
"framadate" = {
host = "176.16.10.128:8000";
serverAliases = [
"everything"
"voyager"
]
};
};
'';
description = "Déclaration des machines.";
};
};
config.services = mkIf cfg.enable {
anubis.instances = mapAttrs (
vhostName: vhostConfig: {
enable = true;
settings = {
BIND_NETWORK = "unix";
TARGET = "unix:/run/nginx/nginx-${vhostName}.sock";
COOKIE_DOMAIN = "crans.org";
REDIRECT_DOMAINS = "${vhostName}.crans.org";
POLICY_FNAME =
if (vhostConfig.anubisConfig == "")
then allowAll
else vhostConfig.anubisConfig;
};
}
) cfg.virtualHosts;
nginx =
let
domaines = [
"crans.org"
"crans.fr"
"crans.eu"
];
redirectConfig = mapAttrs (
vhostName: vhostConfig: {
locations = mkIf ((substring 0 1 vhostConfig.target) != "/") {
"/".proxyPass = "http://${vhostConfig.target}";
};
root = mkIf ((substring 0 1 vhostConfig.target) == "/") vhostConfig.target;
listen = [
{ addr = "unix:/run/nginx/nginx-${vhostName}.sock"; }
];
}
) cfg.virtualHosts;
aliasConfig = mapAttrs' (
vhostName: vhostConfig: nameValuePair (vhostName + "-alias") {
enableACME = true;
forceSSL = true;
serverName = "${vhostName}.crans.fr";
serverAliases = let
aliases = cartesianProduct {
name = vhostConfig.serverAliases;
domaine = domaines;
};
in [
"${vhostName}.crans.eu"
] ++ map (value: value.name + "." + value.domaine) aliases;
extraConfig = ''
return 301 https://${vhostName}.crans.org$request_uri;
'';
}
) cfg.virtualHosts;
anubisConfig = mapAttrs' (
vhostName: vhostConfig: nameValuePair (vhostName + "-anubis") {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "unix:/run/anubis/anubis-${vhostName}.sock";
serverName = "${vhostName}.crans.org";
}
) cfg.virtualHosts;
in {
enable = true;
virtualHosts = redirectConfig // aliasConfig // anubisConfig;
};
};
}