mirror of
https://github.com/foo-dogsquared/nixos-config.git
synced 2025-01-31 22:57:55 +00:00
Gabriel Arazas
2632b75bf2
Even though this is unlikely to be scaled further, we're just being good sysadmins (or at least roleplaying as one).
155 lines
4.7 KiB
Nix
155 lines
4.7 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
let
|
|
monitoringDomain = "monitoring.${config.networking.domain}";
|
|
authDomain = "auth.${config.networking.domain}";
|
|
authSubpath = path: "${authDomain}/${path}";
|
|
|
|
vouchDomain = "vouch.${config.networking.domain}";
|
|
vouchSettings = config.services.vouch-proxy.instances."${vouchDomain}".settings;
|
|
|
|
certDir = file: "${config.security.acme.certs."${monitoringDomain}".directory}/${file}";
|
|
inherit (config.services.grafana) settings;
|
|
in
|
|
{
|
|
services.grafana = {
|
|
enable = true;
|
|
|
|
settings = {
|
|
auth = {
|
|
disable_login_form = true;
|
|
login_maximum_inactive_lifetime_duration = "3d";
|
|
login_maximum_lifetime_duration = "14d";
|
|
};
|
|
|
|
"auth.generic_oauth" = {
|
|
api_url = authSubpath "oauth2/authorise";
|
|
client_id = "grafana";
|
|
client_secret = "$_file{${config.sops.secrets."vouch-proxy/client/secret".path}";
|
|
enabled = true;
|
|
name = "Kanidm";
|
|
oauth_url = authSubpath "ui/oauth2";
|
|
scopes = lib.concatStringsSep " " [ "openid" "email" "profile" ];
|
|
token_url = authSubpath "oauth2/token";
|
|
};
|
|
|
|
database = rec {
|
|
host = "127.0.0.1:${builtins.toString config.services.postgresql.port}";
|
|
password = "$_file{${config.sops.secrets."grafana/database/password".path}}";
|
|
type = "postgres";
|
|
name = "grafana";
|
|
user = name;
|
|
};
|
|
|
|
log = {
|
|
level = "warn";
|
|
mode = "syslog";
|
|
};
|
|
|
|
security = {
|
|
admin_email = config.security.acme.defaults.email;
|
|
admin_password = "$_file{${config.sops.secrets."grafana/users/admin/password".path}}";
|
|
cookie_secure = true;
|
|
csrf_trusted_origins = [
|
|
vouchDomain
|
|
"auth.${config.networking.domain}"
|
|
];
|
|
strict_transport_security = true;
|
|
strict_transport_security_subdomains = true;
|
|
};
|
|
|
|
users = {
|
|
default_theme = "system";
|
|
default_language = "detect";
|
|
};
|
|
|
|
server = {
|
|
enable_gzip = true;
|
|
enforce_domain = true;
|
|
http_addr = "127.0.0.1";
|
|
http_port = 3000;
|
|
root_url = "${monitoringDomain}/grafana";
|
|
serve_from_sub_path = true;
|
|
};
|
|
};
|
|
};
|
|
|
|
services.nginx.virtualHosts."${monitoringDomain}" = {
|
|
forceSSL = true;
|
|
enableACME = true;
|
|
acmeRoot = null;
|
|
|
|
extraConfig = ''
|
|
auth_request /validate;
|
|
|
|
# If the user is not logged in, redirect them to Vouch's login URL
|
|
error_page 401 = @error401;
|
|
location @error401 {
|
|
return 302 http://${vouchDomain}/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
|
|
}
|
|
'';
|
|
|
|
locations = {
|
|
"= /validate" = {
|
|
proxyPass = "http://${vouchSettings.vouch.listen}:${builtins.toString vouchSettings.vouch.port}";
|
|
extraConfig = ''
|
|
proxy_pass_request_body off;
|
|
|
|
# These will be passed to @error_401 call.
|
|
auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user;
|
|
auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt;
|
|
auth_request_set $auth_resp_err $upstream_http_x_vouch_err;
|
|
auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount;
|
|
'';
|
|
};
|
|
|
|
# Make Grafana as the default to be redirected.
|
|
"= /".return = "/grafana";
|
|
|
|
# Serving Grafana with a subpath.
|
|
"/grafana" = {
|
|
proxyPass = "http://grafana";
|
|
extraConfig = ''
|
|
proxy_set_header X-Vouch-User $auth_resp_x_vouch_user;
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
services.nginx.upstreams."grafana" = {
|
|
extraConfig = ''
|
|
zone apps;
|
|
'';
|
|
servers = {
|
|
"localhost:${builtins.toString config.services.grafana.settings.server.http_port}" = { };
|
|
};
|
|
};
|
|
|
|
# Setting up with secure schema usage pattern.
|
|
systemd.services.grafana = {
|
|
preStart =
|
|
let
|
|
grafanaDatabaseUser = config.services.grafana.settings.database.user;
|
|
psql = lib.getExe' config.services.postgresql.package "psql";
|
|
in
|
|
lib.mkBefore ''
|
|
# Setting up the appropriate schema for PostgreSQL secure schema usage.
|
|
${psql} -tAc "SELECT 1 FROM information_schema.schemata WHERE schema_name='${grafanaDatabaseUser}';" \
|
|
grep -q 1 || ${psql} -tAc "CREATE SCHEMA IF NOT EXISTS AUTHORIZATION ${grafanaDatabaseUser};"
|
|
'';
|
|
};
|
|
|
|
sops.secrets =
|
|
let
|
|
grafanaFileAttributes = {
|
|
owner = config.users.users.grafana.name;
|
|
group = config.users.users.grafana.group;
|
|
mode = "0400";
|
|
};
|
|
in
|
|
lib.getSecrets ../../secrets/secrets.yaml {
|
|
"grafana/database/password" = grafanaFileAttributes;
|
|
"grafana/users/admin/password" = grafanaFileAttributes;
|
|
};
|
|
}
|