Compare commits

...

10 commits

8 changed files with 293 additions and 95 deletions

View file

@ -6,6 +6,9 @@
... ...
}: }:
let
sshKeyMac = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKbHk7YasSMK5FBCArKLeqIoaGXsN+WlgVquObyC5Zec raphael@MacBook-Pro-de-raphael.local";
in
{ {
imports = [ imports = [
../global.nix ../global.nix
@ -122,6 +125,9 @@
efi.canTouchEfiVariables = true; efi.canTouchEfiVariables = true;
}; };
users.users.raphael.openssh.authorizedKeys.keys = [
sshKeyMac
];
services = { services = {
seatd.enable = true; seatd.enable = true;
xserver = { xserver = {

View file

@ -39,6 +39,13 @@
mode = "0440"; mode = "0440";
}; };
age.secrets."forgejo-oidc-secret" = {
file = ../../secrets/forgejo-oidc-secret.age;
owner = "kanidm";
group = "forgejo";
mode = "0440";
};
age.secrets."nextcloud-database" = { age.secrets."nextcloud-database" = {
file = ../../secrets/nextcloud-database.age; file = ../../secrets/nextcloud-database.age;
owner = "nextcloud"; owner = "nextcloud";

Binary file not shown.

View file

@ -16,6 +16,7 @@ in
"nextcloud-database.age".publicKeys = users ++ systems; "nextcloud-database.age".publicKeys = users ++ systems;
"nextcloud-oidc-secret.age".publicKeys = users ++ systems; "nextcloud-oidc-secret.age".publicKeys = users ++ systems;
"grafana-oidc-secret.age".publicKeys = users ++ systems; "grafana-oidc-secret.age".publicKeys = users ++ systems;
"forgejo-oidc-secret.age".publicKeys = users ++ systems;
"kandim-admin.age".publicKeys = users ++ systems; "kandim-admin.age".publicKeys = users ++ systems;
"kandim-idmAdmin.age".publicKeys = users ++ systems; "kandim-idmAdmin.age".publicKeys = users ++ systems;
} }

View file

@ -1,49 +1,57 @@
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
let let
giteaDomain = "git.enium.eu"; gitDomain = "git.enium.eu";
in in
{ {
services.gitea = { services = {
enable = true; forgejo = {
appName = "Enium Git"; enable = true;
user = "gitea"; database.type = "postgres";
group = "gitea";
database.type = "sqlite3";
settings = { settings = {
server = { server = {
DOMAIN = giteaDomain; "DEFAULT.APP_NAME" = "Enium Git";
ROOT_URL = "https://${giteaDomain}/"; "DEFAULT.APP_SLOGAN" = "Born2Code";
SSH_PORT = 42131; DOMAIN = gitDomain;
HTTP_ADDR = "127.0.0.1"; ROOT_URL = "https://${gitDomain}/";
HTTP_PORT = 3042; SSH_PORT = 42131;
DISABLE_REGISTRATION = true; HTTP_ADDR = "127.0.0.1";
ALLOW_ONLY_EXTERNAL_REGISTRATION = true; HTTP_PORT = 3042;
SHOW_REGISTRATION_BUTTON = false; DISABLE_REGISTRATION = true;
DISABLE_REGULAR_LOGIN = true; ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
}; SHOW_REGISTRATION_BUTTON = false;
DISABLE_REGULAR_LOGIN = true;
};
service = { oauth2 = {
DISABLE_REGISTRATION = true; ENABLED = true;
ALLOW_ONLY_EXTERNAL_REGISTRATION = true; NAME = "Enium";
}; CLIENT_ID = "forgejo";
CLIENT_SECRET = "${config.age.secrets.forgejo-oidc-secret.path}";
SCOPES = "openid email profile groups";
LOGIN_ATTRIBUTE_PATH = "preferred_username";
AUTH_URL = "https://git.enium.eu/ui/oauth2";
TOKEN_URL = "https://git.enium.eu/oauth2/token";
API_URL = "https://git.enium.eu/oauth2/openid/forgejo/userinfo";
CODE_CHALLENGE_METHOD = "S256";
ENABLE_AUTO_REGISTRATION = true;
UPDATE_AVATAR = true;
};
web = { security = {
DISABLE_LOCAL_LOGIN = true; LOGIN_REMEMBER_DAYS = 14;
}; };
oauth2_client = {
ENABLE_AUTO_REGISTRATION = true;
}; };
}; };
};
services.nginx.virtualHosts."${giteaDomain}" = { nginx.virtualHosts."${gitDomain}" = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:3042"; proxyPass = "http://127.0.0.1:3042";
proxyWebsockets = true;
};
}; };
}; };
} }

View file

@ -77,11 +77,6 @@ in
smtpd_tls_cert_file = "/var/lib/acme/mail.enium.eu/fullchain.pem"; smtpd_tls_cert_file = "/var/lib/acme/mail.enium.eu/fullchain.pem";
smtpd_tls_key_file = "/var/lib/acme/mail.enium.eu/key.pem"; smtpd_tls_key_file = "/var/lib/acme/mail.enium.eu/key.pem";
smtpd_milters = "unix:/run/rspamd/rspamd.sock";
non_smtpd_milters = "unix:/run/rspamd/rspamd.sock";
milter_protocol = "6";
milter_default_action = "accept";
milter_mail_macros = "i {mail_addr} {client_addr} {client_name} {auth_authen}";
}; };
master."submission" = { master."submission" = {
type = "inet"; type = "inet";
@ -107,7 +102,7 @@ in
systemd.services.postfix.preStart = lib.mkMerge [ systemd.services.postfix.preStart = lib.mkMerge [
(lib.mkAfter '' (lib.mkAfter ''
umask 077 umask 077
echo "[in-v3.mailjet.com]:587 $(cat ${mailjet-pass}):$(cat ${mailjet-pass})" > /var/lib/postfix/sasl_passwd echo "[in-v3.mailjet.com]:587 $(cat ${mailjet-user}):$(cat ${mailjet-pass})" > /var/lib/postfix/sasl_passwd
chown postfix:postfix /var/lib/postfix/sasl_passwd chown postfix:postfix /var/lib/postfix/sasl_passwd
chmod 600 /var/lib/postfix/sasl_passwd chmod 600 /var/lib/postfix/sasl_passwd
${pkgs.postfix}/bin/postmap /var/lib/postfix/sasl_passwd ${pkgs.postfix}/bin/postmap /var/lib/postfix/sasl_passwd
@ -143,7 +138,7 @@ in
extraConfig = '' extraConfig = ''
protocols = imap lmtp protocols = imap lmtp
auth_mechanisms = plain login auth_mechanisms = plain login
disable_plaintext_auth = yes disable_plaintext_auth = no
base_dir = /run/dovecot base_dir = /run/dovecot
userdb { userdb {
@ -240,57 +235,51 @@ in
services.rspamd = { services.rspamd = {
enable = true; enable = true;
extraConfig = '' postfix.enable = true;
worker "controller" { extraConfig = ''
bind_socket = "127.0.0.1:11334"; worker "controller" {
password = "admin"; bind_socket = "127.0.0.1:11334";
password = "admin";
};
worker "normal" {
bind_socket = "127.0.0.1:11333";
};
worker "rspamd_proxy" {
bind_socket = "127.0.0.1:11332";
milter = yes;
timeout = 120s;
upstream "local" {
self_scan = yes;
};
};
actions {
reject = 12;
add_header = 6;
greylist = 4;
};
classifier "bayes" {
backend = "redis";
servers = "127.0.0.1:6381";
autolearn = true;
min_learns = 200;
new_schema = true;
cache = true;
statfile {
symbol = "BAYES_HAM";
spam = false;
}; };
worker "normal" { statfile {
bind_socket = "127.0.0.1:11333"; symbol = "BAYES_SPAM";
spam = true;
}; };
worker "rspamd_proxy" { learn_condition = <<EOD
bind_socket = "127.0.0.1:11332";
milter = yes;
timeout = 120s;
upstream "local" {
self_scan = yes;
};
};
actions {
reject = 12;
add_header = 6;
greylist = 4;
};
milter {
unix_socket = "/run/rspamd/milter.sock";
unix_permissions = 0660;
user = "rspamd";
group = "postfix";
};
classifier "bayes" {
backend = "redis";
servers = "127.0.0.1:6381";
autolearn = true;
min_learns = 200;
new_schema = true;
cache = true;
statfile {
symbol = "BAYES_HAM";
spam = false;
};
statfile {
symbol = "BAYES_SPAM";
spam = true;
};
learn_condition = <<EOD
return function(task) return function(task)
return true return true
end end
@ -318,6 +307,7 @@ EOD;
}; };
security.acme.certs."mail.enium.eu" = { security.acme.certs."mail.enium.eu" = {
listenHTTP = ":80"; listenHTTP = ":80";
group = "dovecot2";
}; };
}; };
} }

View file

@ -7,6 +7,7 @@
let let
cfg = config.service.selfhost.monitor; cfg = config.service.selfhost.monitor;
dashboardsDir = ../../assets/grafana_dashboards;
monitored = [ monitored = [
"nginx" "nginx"
"grafana" "grafana"
@ -18,7 +19,36 @@ in
enable = true; enable = true;
package = pkgs.grafana; package = pkgs.grafana;
dataDir = "/var/lib/grafana"; dataDir = "/var/lib/grafana";
provision = {
dashboards.settings.providers = [
{
name = "nixos-dashboards";
type = "file";
updateIntervalSeconds = 30;
editable = false;
options = {
path = "/etc/grafana/dashboards";
foldersFromFilesStructure = false;
};
}
];
datasources.settings.datasources = [
{
name = "Prometheus";
type = "prometheus";
uid = "prometheus";
access = "proxy";
url = "http://127.0.0.1:9090";
isDefault = true;
editable = false;
jsonData = {
httpMethod = "POST";
timeInterval = "15s";
};
}
];
};
settings = { settings = {
server = { server = {
root_url = "https://monitor.enium.eu"; root_url = "https://monitor.enium.eu";
@ -26,17 +56,36 @@ in
serve_from_sub_path = false; serve_from_sub_path = false;
}; };
users = { "auth.generic_oauth" = {
auto_assign_org = true; enabled = true;
auto_assign_org_role = "Viewer"; name = "Enium";
allow_sign_up = true;
client_id = "grafana";
client_secret = "$__file{${config.age.secrets.grafana-oidc-secret.path}}";
scopes = "openid profile email groups";
auth_url = "https://auth.enium.eu/ui/oauth2";
token_url = "https://auth.enium.eu/oauth2/token";
api_url = "https://auth.enium.eu/oauth2/openid/grafana/userinfo";
redirect_uri = "https://monitor.enium.eu/login/generic_oauth";
use_pkce = true;
use_refresh_token = true;
login_attribute_path = "preferred_username";
name_attribute_path = "name";
email_attribute_path = "email";
groups_attribute_path = "groups";
role_attribute_path = "contains(groups, 'grafana_superadmins@enium.eu') && 'GrafanaAdmin' || contains(groups, 'grafana_admins@enium.eu') && 'Admin' || contains(groups, 'grafana_editors@enium.eu') && 'Editor' || 'Viewer'";
allow_assign_grafana_admin = true;
role_attribute_strict = false;
skip_org_role_sync = false;
}; };
log.level = "debug";
auth = { auth = {
disable_login_form = true; disable_login_form = true;
disable_signout_menu = false; disable_signout_menu = false;
}; };
security = { security = {
cookie_secure = true;
cookie_samesite = "none";
allow_embedding = true; allow_embedding = true;
}; };
}; };
@ -157,6 +206,8 @@ in
ruleFiles = lib.mkForce [ "/etc/prometheus/services.rules" ]; ruleFiles = lib.mkForce [ "/etc/prometheus/services.rules" ];
}; };
environment.etc."grafana/dashboards".source = dashboardsDir;
environment.etc."prometheus/services.rules".text = '' environment.etc."prometheus/services.rules".text = ''
groups: groups:
- name: services - name: services

View file

@ -9,6 +9,22 @@ let
cfg = config.service.selfhost.sso; cfg = config.service.selfhost.sso;
kanidm-admin = config.age.secrets."kanidm-admin".path; kanidm-admin = config.age.secrets."kanidm-admin".path;
kanidm-idmAdmin = config.age.secrets."kanidm-idmAdmin".path; kanidm-idmAdmin = config.age.secrets."kanidm-idmAdmin".path;
imagesDir = "/user/share/kanidm/assets";
kanidmLogo = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/doc-sheet/forgejo/refs/heads/forgejo/assets/logo.svg";
name = "kanidm.svg";
sha256 = "sha256-rP7aZURtHBfF2OYuGLcKZhbvIN+B596T/3kaOxHUvig=";
};
grafanaLogo = pkgs.fetchurl {
url = "https://upload.wikimedia.org/wikipedia/commons/a/a1/Grafana_logo.svg";
name = "grafana.svg";
sha256 = "sha256-UjE6ArLCa52o3XGUmpqPoakbEOeFi+zfsnATi1FtWmQ=";
};
nextcloudLogo = pkgs.fetchurl {
url = "https://upload.wikimedia.org/wikipedia/commons/6/60/Nextcloud_Logo.svg";
name = "nextcloud.svg";
sha256 = "sha256-hL51zJkFxUys1CoM8yUxiH8BDw111wh3Qv7eTLm+XYo=";
};
in in
{ {
config = lib.mkIf cfg { config = lib.mkIf cfg {
@ -26,7 +42,6 @@ in
package = pkgs.kanidmWithSecretProvisioning_1_8; package = pkgs.kanidmWithSecretProvisioning_1_8;
enableServer = true; enableServer = true;
serverSettings = { serverSettings = {
role = "WriteReplica";
domain = "enium.eu"; domain = "enium.eu";
origin = "https://auth.enium.eu"; origin = "https://auth.enium.eu";
bindaddress = "127.0.0.1:9000"; bindaddress = "127.0.0.1:9000";
@ -47,17 +62,137 @@ in
mailAddresses = [ mailAddresses = [
"raphael@enium.eu" "raphael@enium.eu"
]; ];
groups = [
"grafana_superadmins"
"forgejo_admins"
"nextcloud_user"
];
}; };
}; };
groups = { groups = {
grafana_superadmins = {
present = true;
};
grafana_admins = {
present = true;
};
grafana_editors = {
present = true;
};
grafana_users = {
present = true;
};
forgejo_admins = {
present = true;
};
forgejo_users = {
present = true;
};
nextcloud_user = { nextcloud_user = {
present = true; present = true;
}; };
}; };
systems.oauth2 = { systems.oauth2 = {
forgejo = {
present = true;
displayName = "Forjego";
originUrl = "https://git.enium.eu";
imageFile = kanidmLogo;
originLanding = "https://git.enium.eu/user/oauth2/Enium/callback";
basicSecretFile = config.age.secrets.forgejo-oidc-secret.path;
public = false;
enableLocalhostRedirects = false;
allowInsecureClientDisablePkce = true;
preferShortUsername = true;
scopeMaps = {
forgejo_admins = [
"email"
"openid"
"profile"
"groups"
];
forgejo_users = [
"email"
"openid"
"profile"
"groups"
];
};
claimMaps = {
groups = {
joinType = "array";
valuesByGroup = {
forgejo_admins = [
"forgejo_admins"
];
forgejo_users = [
"forgejo_users"
];
};
};
};
};
grafana = {
present = true;
displayName = "Grafana";
imageFile = grafanaLogo;
originUrl = "https://monitor.enium.eu";
originLanding = "https://monitor.enium.eu/login/generic_oauth";
basicSecretFile = config.age.secrets.grafana-oidc-secret.path;
public = false;
enableLocalhostRedirects = false;
allowInsecureClientDisablePkce = false;
preferShortUsername = true;
scopeMaps = {
grafana_superadmins = [
"email"
"openid"
"profile"
"groups"
];
grafana_admins = [
"email"
"openid"
"profile"
"groups"
];
grafana_editors = [
"email"
"openid"
"profile"
"groups"
];
grafana_users = [
"email"
"openid"
"profile"
"groups"
];
};
claimMaps = {
groups = {
joinType = "array";
valuesByGroup = {
grafana_superadmins = [
"grafana_superadmins"
];
grafana_admins = [
"grafana_admins"
];
grafana_editors = [
"grafana_editors"
];
grafana_users = [
"grafana_users"
];
};
};
};
};
nextcloud = { nextcloud = {
present = true; present = true;
displayName = "Nextcloud"; displayName = "Nextcloud";
imageFile = nextcloudLogo;
originUrl = "https://nextcloud.enium.eu"; originUrl = "https://nextcloud.enium.eu";
originLanding = "https://nextcloud.enium.eu/login"; originLanding = "https://nextcloud.enium.eu/login";
basicSecretFile = config.age.secrets.nextcloud-oidc-secret.path; basicSecretFile = config.age.secrets.nextcloud-oidc-secret.path;