feat(cloud): a lot of shitty stuff
This commit is contained in:
@@ -126,6 +126,8 @@
|
||||
./server/caddy
|
||||
./server/fail2ban
|
||||
./server/homepage-dashboard
|
||||
./server/ocis
|
||||
./server/keycloak
|
||||
./server/vaultwarden
|
||||
./server/bazarr
|
||||
./server/prowlarr
|
||||
|
||||
@@ -5,17 +5,16 @@
|
||||
pkgs,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkIf
|
||||
mkEnableOption
|
||||
mkOption
|
||||
mkMerge
|
||||
;
|
||||
cfg = config.nixos.services.agenix;
|
||||
in
|
||||
{
|
||||
in {
|
||||
options = {
|
||||
nixos.services.agenix = {
|
||||
enable = mkEnableOption "Enables agenix system environment";
|
||||
@@ -75,6 +74,10 @@ in
|
||||
wgCredentials.file = "${self}/secrets/wgCredentials.age";
|
||||
wgSobotkaPrivateKey.file = "${self}/secrets/wgSobotkaPrivateKey.age";
|
||||
gluetunEnvironment.file = "${self}/secrets/gluetunEnvironment.age";
|
||||
keycloakCloudflared.file = "${self}/secrets/keycloakCloudflared.age";
|
||||
keycloakDbPasswordFile.file = "${self}/secrets/keycloakDbPasswordFile.age";
|
||||
nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age";
|
||||
ocisCloudflared.file = "${self}/secrets/ocisCloudflared.age";
|
||||
vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age";
|
||||
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
|
||||
homepageEnvironment.file = "${self}/secrets/homepageEnvironment.age";
|
||||
|
||||
2
modules/server/README.md
Normal file
2
modules/server/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
This server/homelab configuration is largely a copy (with some tweaks) of
|
||||
@notthebee's homelab setup.
|
||||
100
modules/server/keycloak/default.nix
Normal file
100
modules/server/keycloak/default.nix
Normal file
@@ -0,0 +1,100 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
unit = "keycloak";
|
||||
cfg = config.server.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "login.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Keycloak";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Open Source Identity and Access Management";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "keycloak.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Services";
|
||||
};
|
||||
dbPasswordFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
};
|
||||
cloudflared = {
|
||||
credentialsFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = lib.literalExpression ''
|
||||
pkgs.writeText "cloudflare-credentials.json" '''
|
||||
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
|
||||
'''
|
||||
'';
|
||||
};
|
||||
tunnelId = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "00000000-0000-0000-0000-000000000000";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
server.postgresql.databases = [
|
||||
{
|
||||
database = "keycloak";
|
||||
}
|
||||
];
|
||||
services.cloudflared = {
|
||||
enable = true;
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${cfg.url}".service = "http://127.0.0.1:${
|
||||
toString config.services.${unit}.settings.http-port
|
||||
}";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.keycloak
|
||||
];
|
||||
|
||||
services.${unit} = {
|
||||
enable = true;
|
||||
initialAdminPassword = "pwpwpw";
|
||||
database = {
|
||||
type = "postgresql";
|
||||
host = "127.0.0.1";
|
||||
port = 5432;
|
||||
name = "keycloak";
|
||||
username = "keycloak";
|
||||
passwordFile = cfg.dbPasswordFile;
|
||||
useSSL = false;
|
||||
};
|
||||
settings = {
|
||||
spi-theme-static-max-age = "-1";
|
||||
spi-theme-cache-themes = false;
|
||||
spi-theme-cache-templates = false;
|
||||
http-port = 8821;
|
||||
hostname = cfg.url;
|
||||
hostname-strict = false;
|
||||
hostname-strict-https = false;
|
||||
proxy-headers = "xforwarded";
|
||||
http-enabled = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
unit = "nextcloud";
|
||||
cfg = config.server.${unit};
|
||||
srv = config.server;
|
||||
in
|
||||
{
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
adminUser = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "cnst";
|
||||
};
|
||||
adminPass = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "cloud.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Nextcloud";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "A safe home for all your data";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "nextcloud.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Services";
|
||||
};
|
||||
cloudflared = {
|
||||
credentialsFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = lib.literalExpression ''
|
||||
pkgs.writeText "cloudflare-credentials.json" '''
|
||||
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
|
||||
'''
|
||||
'';
|
||||
};
|
||||
tunnelId = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "00000000-0000-0000-0000-000000000000";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
server = {
|
||||
postgresql.databases = [
|
||||
{
|
||||
database = "nextcloud";
|
||||
}
|
||||
];
|
||||
fail2ban = lib.mkIf config.server.fail2ban.enable {
|
||||
jails = {
|
||||
nextcloud = {
|
||||
serviceName = "phpfm-nextcloud";
|
||||
failRegex = "^.*Login failed:.*(Remote IP: <HOST>).*$";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
cloudflared = {
|
||||
enable = true;
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${cfg.url}".service = "http://127.0.0.1:8083";
|
||||
};
|
||||
};
|
||||
|
||||
${unit} = {
|
||||
enable = true;
|
||||
package = pkgs.nextcloud31;
|
||||
hostName = "nextcloud";
|
||||
configureRedis = true;
|
||||
caching = {
|
||||
redis = true;
|
||||
};
|
||||
maxUploadSize = "50G";
|
||||
settings = {
|
||||
trusted_proxies = [ "127.0.0.1" ];
|
||||
overwriteprotocol = "https";
|
||||
overwritehost = "cloud.${srv.domain}";
|
||||
overwrite.cli.url = "https://cloud.${srv.domain}";
|
||||
mail_smtpmode = "sendmail";
|
||||
mail_sendmailmode = "pipe";
|
||||
user_oidc = {
|
||||
allow_multiple_user_backends = 0;
|
||||
};
|
||||
forwarded_for_headers = [
|
||||
"HTTP_CF_CONNECTING_IP"
|
||||
];
|
||||
enabledPreviewProviders = [
|
||||
"OC\\Preview\\BMP"
|
||||
"OC\\Preview\\GIF"
|
||||
"OC\\Preview\\JPEG"
|
||||
"OC\\Preview\\Krita"
|
||||
"OC\\Preview\\MarkDown"
|
||||
"OC\\Preview\\MP3"
|
||||
"OC\\Preview\\OpenDocument"
|
||||
"OC\\Preview\\PNG"
|
||||
"OC\\Preview\\TXT"
|
||||
"OC\\Preview\\XBitmap"
|
||||
"OC\\Preview\\HEIC"
|
||||
];
|
||||
};
|
||||
config = {
|
||||
dbtype = "pgsql";
|
||||
dbuser = "nextcloud";
|
||||
dbhost = "/run/postgresql";
|
||||
dbname = "nextcloud";
|
||||
adminuser = cfg.adminUser;
|
||||
adminpassFile = cfg.adminPass;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
155
modules/server/ocis/default.nix
Normal file
155
modules/server/ocis/default.nix
Normal file
@@ -0,0 +1,155 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
unit = "ocis";
|
||||
cfg = config.server.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
options.server.${unit} = {
|
||||
enable = lib.mkEnableOption {
|
||||
description = "Enable ${unit}";
|
||||
};
|
||||
adminUser = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "cnst";
|
||||
};
|
||||
adminPass = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${unit}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "cloud.${srv.domain}";
|
||||
};
|
||||
homepage.name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "OCIS";
|
||||
};
|
||||
homepage.description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "A safe home for all your data";
|
||||
};
|
||||
homepage.icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "owncloud.svg";
|
||||
};
|
||||
homepage.category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Services";
|
||||
};
|
||||
cloudflared = {
|
||||
credentialsFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = lib.literalExpression ''
|
||||
pkgs.writeText "cloudflare-credentials.json" '''
|
||||
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
|
||||
'''
|
||||
'';
|
||||
};
|
||||
tunnelId = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "00000000-0000-0000-0000-000000000000";
|
||||
};
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
server = {
|
||||
postgresql.databases = [
|
||||
{
|
||||
database = "ocis";
|
||||
}
|
||||
];
|
||||
fail2ban = lib.mkIf config.server.fail2ban.enable {
|
||||
jails = {
|
||||
nextcloud = {
|
||||
serviceName = "phpfm-nextcloud";
|
||||
failRegex = "^.*Login failed:.*(Remote IP: <HOST>).*$";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
systemd.services.ocis.preStart = ''
|
||||
${lib.getExe pkgs.ocis} init || true
|
||||
'';
|
||||
services = {
|
||||
cloudflared = {
|
||||
enable = true;
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${cfg.url}".service = "http://${config.services.ocis.address}:${toString config.services.ocis.port}";
|
||||
};
|
||||
};
|
||||
${unit} = {
|
||||
enable = true;
|
||||
url = "https://${cfg.url}";
|
||||
environment = let
|
||||
cspFormat = pkgs.formats.yaml {};
|
||||
cspConfig = {
|
||||
directives = {
|
||||
child-src = ["'self'"];
|
||||
connect-src = [
|
||||
"'self'"
|
||||
"blob:"
|
||||
"https://${srv.keycloak.url}"
|
||||
];
|
||||
default-src = ["'none'"];
|
||||
font-src = ["'self'"];
|
||||
frame-ancestors = ["'none'"];
|
||||
frame-src = [
|
||||
"'self'"
|
||||
"blob:"
|
||||
"https://embed.diagrams.net"
|
||||
];
|
||||
img-src = [
|
||||
"'self'"
|
||||
"data:"
|
||||
"blob:"
|
||||
];
|
||||
manifest-src = ["'self'"];
|
||||
media-src = ["'self'"];
|
||||
object-src = [
|
||||
"'self'"
|
||||
"blob:"
|
||||
];
|
||||
script-src = [
|
||||
"'self'"
|
||||
"'unsafe-inline'"
|
||||
];
|
||||
style-src = [
|
||||
"'self'"
|
||||
"'unsafe-inline'"
|
||||
];
|
||||
};
|
||||
};
|
||||
in {
|
||||
PROXY_AUTOPROVISION_ACCOUNTS = "true";
|
||||
PROXY_ROLE_ASSIGNMENT_DRIVER = "oidc";
|
||||
OCIS_OIDC_ISSUER = "https://${srv.keycloak.url}/realms/master";
|
||||
PROXY_OIDC_REWRITE_WELLKNOWN = "true";
|
||||
WEB_OIDC_CLIENT_ID = "ocis";
|
||||
OCIS_LOG_LEVEL = "error";
|
||||
PROXY_TLS = "false";
|
||||
PROXY_USER_OIDC_CLAIM = "preferred_username";
|
||||
PROXY_USER_CS3_CLAIM = "username";
|
||||
OCIS_ADMIN_USER_ID = "";
|
||||
OCIS_INSECURE = "false";
|
||||
OCIS_EXCLUDE_RUN_SERVICES = "idp";
|
||||
GRAPH_ASSIGN_DEFAULT_USER_ROLE = "false";
|
||||
PROXY_CSP_CONFIG_FILE_LOCATION = toString (cspFormat.generate "csp.yaml" cspConfig);
|
||||
GRAPH_USERNAME_MATCH = "none";
|
||||
# PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD = "none";
|
||||
PROXY_ROLE_ASSIGNMENT_ENABLED = "true";
|
||||
PROXY_ROLE_ASSIGNMENT_OIDC_CLAIM = "realm_access.roles";
|
||||
PROXY_ROLE_ASSIGNMENT_MAPPING = "ocisAdmin:admin,cnst:user";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -54,14 +54,28 @@ in {
|
||||
local all postgres peer
|
||||
local sameuser all peer
|
||||
|
||||
# extra users
|
||||
# local peer access for extra users
|
||||
${lib.concatMapStringsSep "\n" (
|
||||
{
|
||||
database,
|
||||
extraUsers,
|
||||
...
|
||||
}:
|
||||
lib.concatMapStringsSep "\n" (user: "local ${database} ${user} peer") extraUsers
|
||||
lib.concatMapStringsSep "\n" (user: "local ${database} ${user} peer") ([database] ++ extraUsers)
|
||||
)
|
||||
cfg.databases}
|
||||
|
||||
# host access (TCP) for databases and their users
|
||||
${lib.concatMapStringsSep "\n" (
|
||||
{
|
||||
database,
|
||||
extraUsers,
|
||||
...
|
||||
}:
|
||||
lib.concatMapStringsSep "\n" (user: ''
|
||||
host ${database} ${user} 127.0.0.1/32 trust
|
||||
host ${database} ${user} ::1/128 trust
|
||||
'') ([database] ++ extraUsers)
|
||||
)
|
||||
cfg.databases}
|
||||
'';
|
||||
|
||||
Reference in New Issue
Block a user