forked from nyanloutre/nixos-config
453 lines
14 KiB
Nix
453 lines
14 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
nginxSsoAuth = pkgs.writeText "nginx-sso_auth.inc" ''
|
|
# Protect this location using the auth_request
|
|
auth_request /sso-auth;
|
|
|
|
# Redirect the user to the login page when they are not logged in
|
|
error_page 401 = @error401;
|
|
|
|
location /sso-auth {
|
|
# Do not allow requests from outside
|
|
internal;
|
|
|
|
# Access /auth endpoint to query login state
|
|
proxy_pass http://127.0.0.1:${toString(config.services.nginx.sso.configuration.listen.port)}/auth;
|
|
|
|
# Do not forward the request body (nginx-sso does not care about it)
|
|
proxy_pass_request_body off;
|
|
proxy_set_header Content-Length "";
|
|
|
|
# Set custom information for ACL matching: Each one is available as
|
|
# a field for matching: X-Host = x-host, ...
|
|
proxy_set_header X-Origin-URI $request_uri;
|
|
proxy_set_header X-Host $http_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;
|
|
}
|
|
|
|
# If the user is lead to /logout redirect them to the logout endpoint
|
|
# of ngninx-sso which then will redirect the user to / on the current host
|
|
location /sso-logout {
|
|
return 302 https://login.nyanlout.re/logout?go=$scheme://$http_host/;
|
|
}
|
|
|
|
# Define where to send the user to login and specify how to get back
|
|
location @error401 {
|
|
return 302 https://login.nyanlout.re/login?go=$scheme://$http_host$request_uri;
|
|
}
|
|
'';
|
|
in
|
|
{
|
|
security.acme = {
|
|
defaults.email = "paul@nyanlout.re";
|
|
acceptTerms = true;
|
|
};
|
|
|
|
users.groups = {
|
|
work = {};
|
|
webdav = {};
|
|
};
|
|
users.users = {
|
|
work = {
|
|
isSystemUser = true;
|
|
group = config.users.groups.work.name;
|
|
};
|
|
webdav = {
|
|
isSystemUser = true;
|
|
group = config.users.groups.webdav.name;
|
|
};
|
|
wordpress = {
|
|
isSystemUser = true;
|
|
group = config.services.nginx.group;
|
|
};
|
|
};
|
|
|
|
services = {
|
|
phpfpm.pools = {
|
|
# work = {
|
|
# user = config.users.users.work.name;
|
|
# phpPackage = pkgs.php.withExtensions ({ all, ... }: with all; [ redis filter ]);
|
|
# settings = {
|
|
# "listen.owner" = config.services.nginx.user;
|
|
# "pm" = "dynamic";
|
|
# "pm.max_children" = 75;
|
|
# "pm.start_servers" = 10;
|
|
# "pm.min_spare_servers" = 5;
|
|
# "pm.max_spare_servers" = 20;
|
|
# "pm.max_requests" = 500;
|
|
# };
|
|
# };
|
|
|
|
"wordpress-designyourfuture" = {
|
|
user = config.users.users.wordpress.name;
|
|
group = config.services.nginx.group;
|
|
settings = {
|
|
"listen.owner" = config.services.nginx.user;
|
|
"pm" = "dynamic";
|
|
"pm.max_children" = 32;
|
|
"pm.start_servers" = 2;
|
|
"pm.min_spare_servers" = 2;
|
|
"pm.max_spare_servers" = 4;
|
|
"pm.max_requests" = 500;
|
|
};
|
|
};
|
|
|
|
|
|
drive = {
|
|
user = config.users.users.webdav.name;
|
|
settings = {
|
|
"listen.owner" = config.services.nginx.user;
|
|
"pm" = "dynamic";
|
|
"pm.max_children" = 75;
|
|
"pm.start_servers" = 10;
|
|
"pm.min_spare_servers" = 5;
|
|
"pm.max_spare_servers" = 20;
|
|
"pm.max_requests" = 500;
|
|
};
|
|
phpOptions = ''
|
|
output_buffering=off
|
|
'';
|
|
};
|
|
};
|
|
nginx = {
|
|
enable = true;
|
|
package = pkgs.nginx.override {
|
|
modules = with pkgs.nginxModules; [ dav moreheaders ];
|
|
};
|
|
recommendedGzipSettings = true;
|
|
recommendedOptimisation = true;
|
|
recommendedProxySettings = true;
|
|
recommendedTlsSettings = true;
|
|
commonHttpConfig = ''
|
|
map $scheme $hsts_header {
|
|
https "max-age=31536000; includeSubdomains; preload";
|
|
}
|
|
add_header Strict-Transport-Security $hsts_header;
|
|
add_header Referrer-Policy origin-when-cross-origin;
|
|
'';
|
|
sso = {
|
|
enable = true;
|
|
configuration = {
|
|
listen = {
|
|
addr = "127.0.0.1";
|
|
port = 8082;
|
|
};
|
|
login = {
|
|
title = "LoutreOS login";
|
|
default_method = "simple";
|
|
hide_mfa_field = true;
|
|
names.simple = "Username / Password";
|
|
};
|
|
cookie = {
|
|
domain = ".nyanlout.re";
|
|
secure = true;
|
|
};
|
|
audit_log = {
|
|
targets = [ "fd://stdout" ];
|
|
events = [ "access_denied" "login_success" "login_failure" "logout" ];
|
|
};
|
|
providers.simple = {
|
|
enable_basic_auth = true;
|
|
users = {
|
|
paul = "$2y$10$RMqeJF/hUasXZ5/SLKAu4uKKp6ac6qXCaRu4OY/fIN6ZYucDXzqYm";
|
|
};
|
|
groups = {
|
|
admins = [ "paul" ];
|
|
};
|
|
};
|
|
acl = {
|
|
rule_sets = [
|
|
{
|
|
rules = [ { field = "x-host"; regexp = ".*"; } ];
|
|
allow = [ "@admins" ];
|
|
}
|
|
];
|
|
};
|
|
};
|
|
};
|
|
virtualHosts = let
|
|
base = locations: {
|
|
locations = locations // {
|
|
"@maintenance" = {
|
|
root = "/var/www/errorpages/";
|
|
extraConfig = ''
|
|
rewrite ^(.*)$ /50x.html break;
|
|
'';
|
|
};
|
|
};
|
|
forceSSL = true;
|
|
enableACME = true;
|
|
extraConfig = ''
|
|
error_page 500 502 503 504 = @maintenance;
|
|
'';
|
|
};
|
|
simpleReverse = rport: base {
|
|
"/" = {
|
|
proxyPass = "http://127.0.0.1:${toString(rport)}/";
|
|
};
|
|
};
|
|
authReverse = rport: zipAttrsWith (name: vs: if name == "extraConfig" then (concatStrings vs) else elemAt vs 0) [
|
|
(base {
|
|
"/" = {
|
|
proxyPass = "http://127.0.0.1:${toString(rport)}/";
|
|
extraConfig = ''
|
|
auth_request_set $cookie $upstream_http_set_cookie;
|
|
add_header Set-Cookie $cookie;
|
|
'';
|
|
};
|
|
})
|
|
{
|
|
extraConfig = ''
|
|
include ${nginxSsoAuth};
|
|
'';
|
|
}
|
|
];
|
|
in {
|
|
"nyanlout.re" = base {
|
|
"/" = {
|
|
alias = "/var/www/site-perso/";
|
|
};
|
|
"/maintenance/" = {
|
|
alias = "/var/www/errorpages/";
|
|
};
|
|
"/.well-known/openpgpkey/" = {
|
|
alias = "/var/lib/gnupg/wks/nyanlout.re";
|
|
extraConfig = ''
|
|
add_header Access-Control-Allow-Origin * always;
|
|
'';
|
|
};
|
|
} // { default = true; };
|
|
"riot.nyanlout.re" = base { "/" = { root = pkgs.element-web; }; };
|
|
"factorio.nyanlout.re" = base { "/" = { root = "/var/www/factorio"; }; };
|
|
"minecraft.nyanlout.re" = base { "/" = { root = "/var/www/minecraft-overviewer"; }; };
|
|
"musique-meyenheim.fr" = base {
|
|
"/" = {
|
|
proxyPass = "http://unix:/run/site-musique.sock";
|
|
};
|
|
"/static/" = {
|
|
alias = "/var/www/site-musique/staticfiles/";
|
|
};
|
|
"/media/" = {
|
|
alias = "/var/www/site-musique/media/";
|
|
};
|
|
};
|
|
# "maxspiegel.fr" = base { "/" = { root = "/run/python-ci/nyanloutre/site-max"; }; };
|
|
"stream.nyanlout.re" = base {
|
|
"/" = {
|
|
proxyPass = "http://10.30.135.71";
|
|
};
|
|
};
|
|
"login.nyanlout.re" = simpleReverse config.services.nginx.sso.configuration.listen.port;
|
|
"grafana.nyanlout.re" = authReverse config.services.grafana.port;
|
|
"transmission.nyanlout.re" = authReverse config.services.transmission.settings.rpc-port;
|
|
"radarr.nyanlout.re" = authReverse 7878;
|
|
"sonarr.nyanlout.re" = authReverse 8989;
|
|
"syncthing.nyanlout.re" = authReverse 8384;
|
|
"jackett.nyanlout.re" = authReverse 9117;
|
|
"matrix.nyanlout.re" = simpleReverse 8008;
|
|
"emby.nyanlout.re" = recursiveUpdate (simpleReverse 8096) {
|
|
locations."/" = {
|
|
proxyWebsockets = true;
|
|
};
|
|
};
|
|
"ci.nyanlout.re" = simpleReverse 52350;
|
|
"gitea.nyanlout.re" = simpleReverse config.services.gitea.httpPort;
|
|
"musique.nyanlout.re" = simpleReverse config.services.navidrome.settings.Port;
|
|
"apart.nyanlout.re" = recursiveUpdate (simpleReverse config.services.home-assistant.config.http.server_port) {
|
|
locations."/" = {
|
|
proxyWebsockets = true;
|
|
};
|
|
};
|
|
# "work.rezom.eu" = base {
|
|
# "/" = {
|
|
# index = "/_h5ai/public/index.php";
|
|
# extraConfig = ''
|
|
# dav_ext_methods PROPFIND OPTIONS;
|
|
# '';
|
|
# };
|
|
# "~ ^/(_h5ai/public/index|random).php" = {
|
|
# extraConfig = ''
|
|
# fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
# fastcgi_pass unix:${config.services.phpfpm.pools.work.socket};
|
|
# include ${pkgs.nginx}/conf/fastcgi_params;
|
|
# include ${pkgs.nginx}/conf/fastcgi.conf;
|
|
# '';
|
|
# };
|
|
# } // {
|
|
# root = "/mnt/medias/iso_linux";
|
|
# extraConfig = ''
|
|
# access_log /var/log/nginx/$host.log;
|
|
# '';
|
|
# };
|
|
"drive.nyanlout.re" = base {
|
|
"/" = {
|
|
index = "/index.php";
|
|
extraConfig = ''
|
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
fastcgi_pass unix:${config.services.phpfpm.pools.drive.socket};
|
|
include ${pkgs.nginx}/conf/fastcgi_params;
|
|
include ${pkgs.nginx}/conf/fastcgi.conf;
|
|
|
|
client_max_body_size 0;
|
|
'';
|
|
};
|
|
} // {
|
|
root = "/mnt/webdav";
|
|
};
|
|
"rspamd.nyanlout.re" = zipAttrsWith (name: vs: if name == "extraConfig" then (concatStrings vs) else elemAt vs 0) [
|
|
(base {
|
|
"/" = {
|
|
proxyPass = "http://unix:/run/rspamd/worker-controller.sock";
|
|
extraConfig = ''
|
|
auth_request_set $cookie $upstream_http_set_cookie;
|
|
add_header Set-Cookie $cookie;
|
|
'';
|
|
};
|
|
})
|
|
{
|
|
extraConfig = ''
|
|
include ${nginxSsoAuth};
|
|
'';
|
|
}
|
|
];
|
|
"designyourfuture.amandoline-creations.fr" = base {
|
|
"/" = {
|
|
priority = 200;
|
|
extraConfig = ''
|
|
try_files $uri $uri/ /index.php$is_args$args;
|
|
'';
|
|
};
|
|
"~ \\.php$" = {
|
|
priority = 500;
|
|
extraConfig = ''
|
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
|
fastcgi_pass unix:${config.services.phpfpm.pools."wordpress-designyourfuture".socket};
|
|
fastcgi_index index.php;
|
|
include "${config.services.nginx.package}/conf/fastcgi.conf";
|
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
|
|
# Mitigate https://httpoxy.org/ vulnerabilities
|
|
fastcgi_param HTTP_PROXY "";
|
|
fastcgi_intercept_errors off;
|
|
fastcgi_buffer_size 16k;
|
|
fastcgi_buffers 4 16k;
|
|
fastcgi_connect_timeout 300;
|
|
fastcgi_send_timeout 300;
|
|
fastcgi_read_timeout 300;
|
|
'';
|
|
};
|
|
"~ /\\." = {
|
|
priority = 800;
|
|
extraConfig = "deny all;";
|
|
};
|
|
"~* /(?:uploads|files)/.*\\.php$" = {
|
|
priority = 900;
|
|
extraConfig = "deny all;";
|
|
};
|
|
"~* \\.(js|css|png|jpg|jpeg|gif|ico)$" = {
|
|
priority = 1000;
|
|
extraConfig = ''
|
|
expires max;
|
|
log_not_found off;
|
|
'';
|
|
};
|
|
} // {
|
|
root = "/var/www/wordpress-designyourfuture";
|
|
extraConfig = ''
|
|
index index.php;
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
postgresql = {
|
|
enable = true;
|
|
package = pkgs.postgresql_14;
|
|
settings = {
|
|
full_page_writes = false;
|
|
};
|
|
};
|
|
|
|
gitea = {
|
|
enable = true;
|
|
cookieSecure = true;
|
|
httpPort = 3001;
|
|
rootUrl = "https://gitea.nyanlout.re/";
|
|
database = {
|
|
type = "postgres";
|
|
port = 5432;
|
|
passwordFile = "/var/lib/gitea/custom/conf/database_password";
|
|
};
|
|
log.level = "Warn";
|
|
disableRegistration = true;
|
|
settings = {
|
|
ui.DEFAULT_THEME = "arc-green";
|
|
};
|
|
};
|
|
|
|
python-ci.enable = true;
|
|
|
|
mysql = {
|
|
enable = true;
|
|
package = pkgs.mariadb;
|
|
};
|
|
};
|
|
|
|
systemd.services.nginx.serviceConfig = {
|
|
ReadWritePaths = [
|
|
"/var/www/hls"
|
|
"/mnt/webdav"
|
|
];
|
|
};
|
|
|
|
systemd.services.phpfpm-work.serviceConfig = {
|
|
ReadOnlyPaths = "/mnt/medias/iso_linux";
|
|
ReadWritePaths = [
|
|
"/mnt/medias/iso_linux/_h5ai"
|
|
];
|
|
};
|
|
|
|
systemd.services.site-musique = let
|
|
djangoEnv =(pkgs.python3.withPackages (ps: with ps; [ gunicorn django_3 pillow setuptools ]));
|
|
in {
|
|
description = "Site Django de la musique de Meyenheim";
|
|
after = [ "network.target" ];
|
|
requires = [ "site-musique.socket" ];
|
|
preStart = ''
|
|
${djangoEnv}/bin/python manage.py migrate;
|
|
${djangoEnv}/bin/python manage.py collectstatic --no-input;
|
|
'';
|
|
environment = {
|
|
DJANGO_SETTINGS_MODULE = "site_musique.settings.prod";
|
|
NGINX_DIRECTORY = "/var/www/site-musique";
|
|
};
|
|
serviceConfig = {
|
|
DynamicUser = true;
|
|
Group = "nginx";
|
|
StateDirectory = "site-musique";
|
|
WorkingDirectory = "/var/www/site-musique/";
|
|
ReadWritePaths = [ "/var/www/site-musique/staticfiles" "/var/www/site-musique/media" ];
|
|
EnvironmentFile = "/mnt/secrets/site-musique.env";
|
|
ExecStart = ''${djangoEnv}/bin/gunicorn \
|
|
--access-logfile - \
|
|
--bind unix:/run/site-musique.sock \
|
|
site_musique.wsgi:application
|
|
'';
|
|
PrivateTmp = true;
|
|
};
|
|
};
|
|
|
|
systemd.sockets.site-musique = {
|
|
description = "Site Musique socket";
|
|
wantedBy = [ "sockets.target" ];
|
|
listenStreams = [ "/run/site-musique.sock" ];
|
|
};
|
|
|
|
systemd.services.nginx-sso.serviceConfig.EnvironmentFile = "/mnt/secrets/nginx-sso.env";
|
|
}
|