feat(refactor): WIP 2.0 some progress
This commit is contained in:
39
flake.nix
39
flake.nix
@@ -1,9 +1,8 @@
|
||||
{
|
||||
description = "cnix nix";
|
||||
|
||||
outputs =
|
||||
inputs:
|
||||
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
outputs = inputs:
|
||||
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
|
||||
systems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
@@ -17,25 +16,23 @@
|
||||
./fmt-hooks.nix
|
||||
];
|
||||
|
||||
perSystem =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = [
|
||||
pkgs.git
|
||||
config.packages.repl
|
||||
];
|
||||
name = "dots";
|
||||
env.DIRENV_LOG_FORMAT = "";
|
||||
shellHook = ''
|
||||
${config.pre-commit.installationScript}
|
||||
'';
|
||||
};
|
||||
perSystem = {
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = [
|
||||
pkgs.git
|
||||
config.packages.repl
|
||||
];
|
||||
name = "dots";
|
||||
env.DIRENV_LOG_FORMAT = "";
|
||||
shellHook = ''
|
||||
${config.pre-commit.installationScript}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
inputs = {
|
||||
|
||||
@@ -4,114 +4,111 @@
|
||||
homeImports,
|
||||
self,
|
||||
...
|
||||
}:
|
||||
{
|
||||
flake.nixosConfigurations =
|
||||
let
|
||||
cLib = import ../lib inputs.nixpkgs.lib;
|
||||
userConfig = "${self}/home";
|
||||
systemConfig = "${self}/system";
|
||||
hostConfig = "${self}/hosts";
|
||||
}: {
|
||||
flake.nixosConfigurations = let
|
||||
cLib = import ../lib inputs.nixpkgs.lib;
|
||||
userConfig = "${self}/home";
|
||||
systemConfig = "${self}/system";
|
||||
hostConfig = "${self}/hosts";
|
||||
|
||||
cnstConfig = "${self}/users/cnst";
|
||||
toothpickConfig = "${self}/users/toothpick";
|
||||
cnstConfig = "${self}/users/cnst";
|
||||
toothpickConfig = "${self}/users/toothpick";
|
||||
|
||||
umodPath = "${self}/modules/home";
|
||||
smodPath = "${self}/modules/system";
|
||||
umodPath = "${self}/modules/home";
|
||||
smodPath = "${self}/modules/system";
|
||||
|
||||
inherit (inputs.nixpkgs.lib) nixosSystem;
|
||||
inherit (self) outputs;
|
||||
inherit (inputs.nixpkgs.lib) nixosSystem;
|
||||
inherit (self) outputs;
|
||||
|
||||
specialArgs = {
|
||||
inherit
|
||||
cLib
|
||||
inputs
|
||||
outputs
|
||||
self
|
||||
userConfig
|
||||
systemConfig
|
||||
hostConfig
|
||||
cnstConfig
|
||||
toothpickConfig
|
||||
umodPath
|
||||
smodPath
|
||||
;
|
||||
};
|
||||
in
|
||||
{
|
||||
kima = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./kima
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.cnst.imports = homeImports."cnst@kima";
|
||||
extraSpecialArgs = specialArgs;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
inputs.chaotic.nixosModules.default
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
bunk = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./bunk
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.cnst.imports = homeImports."cnst@bunk";
|
||||
extraSpecialArgs = specialArgs;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
inputs.chaotic.nixosModules.default
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
sobotka = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./sobotka
|
||||
"${self}/nix"
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
self.nixosModules.server
|
||||
inputs.agenix.nixosModules.default
|
||||
inputs.authentik.nixosModules.default
|
||||
];
|
||||
};
|
||||
ziggy = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./ziggy
|
||||
"${self}/nix"
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
self.nixosModules.server
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
toothpc = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./toothpc
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.toothpick.imports = homeImports."toothpick@toothpc";
|
||||
extraSpecialArgs = specialArgs;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
inputs.chaotic.nixosModules.default
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
specialArgs = {
|
||||
inherit
|
||||
cLib
|
||||
inputs
|
||||
outputs
|
||||
self
|
||||
userConfig
|
||||
systemConfig
|
||||
hostConfig
|
||||
cnstConfig
|
||||
toothpickConfig
|
||||
umodPath
|
||||
smodPath
|
||||
;
|
||||
};
|
||||
in {
|
||||
kima = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./kima
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.cnst.imports = homeImports."cnst@kima";
|
||||
extraSpecialArgs = specialArgs;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
inputs.chaotic.nixosModules.default
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
bunk = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./bunk
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.cnst.imports = homeImports."cnst@bunk";
|
||||
extraSpecialArgs = specialArgs;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
inputs.chaotic.nixosModules.default
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
sobotka = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./sobotka
|
||||
"${self}/nix"
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
self.nixosModules.server
|
||||
inputs.agenix.nixosModules.default
|
||||
inputs.authentik.nixosModules.default
|
||||
];
|
||||
};
|
||||
ziggy = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./ziggy
|
||||
"${self}/nix"
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
self.nixosModules.server
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
toothpc = nixosSystem {
|
||||
inherit specialArgs;
|
||||
modules = [
|
||||
./toothpc
|
||||
"${self}/nix"
|
||||
{
|
||||
home-manager = {
|
||||
users.toothpick.imports = homeImports."toothpick@toothpc";
|
||||
extraSpecialArgs = specialArgs;
|
||||
};
|
||||
}
|
||||
self.nixosModules.nixos
|
||||
self.nixosModules.settings
|
||||
inputs.chaotic.nixosModules.default
|
||||
inputs.agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -55,160 +55,159 @@
|
||||
};
|
||||
|
||||
services = {
|
||||
# homepage-dashboard = {
|
||||
# enable = true;
|
||||
# subdomain = "";
|
||||
# port = "8082";
|
||||
# };
|
||||
# n8n = {
|
||||
# enable = true;
|
||||
# subdomain = "n8n";
|
||||
# port = "5678";
|
||||
# homepage = {
|
||||
# name = "n8n";
|
||||
# description = "A workflow automation platform";
|
||||
# icon = "n8n.svg";
|
||||
# category = "Services";
|
||||
# };
|
||||
# };
|
||||
# bazarr = {
|
||||
# enable = true;
|
||||
# subdomain = "bazarr";
|
||||
# port = 6767;
|
||||
# homepage = {
|
||||
# name = "Bazarr";
|
||||
# description = "Subtitle manager";
|
||||
# icon = "bazarr.svg";
|
||||
# category = "Arr";
|
||||
# };
|
||||
# };
|
||||
# prowlarr = {
|
||||
# enable = true;
|
||||
# subdomain = "prowlarr";
|
||||
# port = 9696;
|
||||
# homepage = {
|
||||
# name = "prowlarr";
|
||||
# description = "PVR indexer";
|
||||
# icon = "prowlarr.svg";
|
||||
# category = "Arr";
|
||||
# };
|
||||
# };
|
||||
# flaresolverr = {
|
||||
# enable = true;
|
||||
# subdomain = "flaresolverr";
|
||||
# port = 8191;
|
||||
# homepage = {
|
||||
# name = "FlareSolverr";
|
||||
# description = "Proxy to bypass Cloudflare/DDoS-GUARD protection";
|
||||
# icon = "flaresolverr.svg";
|
||||
# category = "Arr";
|
||||
# };
|
||||
# };
|
||||
# lidarr = {
|
||||
# enable = true;
|
||||
# subdomain = "lidarr";
|
||||
# port = 8686;
|
||||
# homepage = {
|
||||
# name = "Lidarr";
|
||||
# description = "Music collection manager";
|
||||
# icon = "lidarr.svg";
|
||||
# category = "Arr";
|
||||
# };
|
||||
# };
|
||||
# sonarr = {
|
||||
# enable = true;
|
||||
# subdomain = "sonarr";
|
||||
# port = 8989;
|
||||
# homepage = {
|
||||
# name = "Sonarr";
|
||||
# description = "Internet PVR for Usenet and Torrents";
|
||||
# icon = "sonarr.svg";
|
||||
# category = "Arr";
|
||||
# };
|
||||
# };
|
||||
# radarr = {
|
||||
# enable = true;
|
||||
# subdomain = "radarr";
|
||||
# port = 7878;
|
||||
# homepage = {
|
||||
# name = "Radarr";
|
||||
# description = "Movie collection manager";
|
||||
# icon = "radarr.svg";
|
||||
# category = "Arr";
|
||||
# };
|
||||
# };
|
||||
# jellyseerr = {
|
||||
# enable = true;
|
||||
# subdomain = "jellyseerr";
|
||||
# port = 5055;
|
||||
# homepage = {
|
||||
# name = "Jellyseerr";
|
||||
# description = "Media request and discovery manager";
|
||||
# icon = "jellyserr.svg";
|
||||
# category = "Arr";
|
||||
# };
|
||||
# };
|
||||
# jellyfin = {
|
||||
# enable = true;
|
||||
# subdomain = "fin";
|
||||
# exposure = "tailscale";
|
||||
# port = 8096;
|
||||
# homepage = {
|
||||
# name = "Jellyfin";
|
||||
# description = "The Free Software Media System";
|
||||
# icon = "jellyfin.svg";
|
||||
# category = "Media";
|
||||
# };
|
||||
# };
|
||||
# uptime-kuma = {
|
||||
# enable = true;
|
||||
# subdomain = "uptime";
|
||||
# port = 3001;
|
||||
# homepage = {
|
||||
# name = "Uptime Kuma";
|
||||
# description = "Service monitoring tool";
|
||||
# icon = "uptime-kuma.svg";
|
||||
# category = "Services";
|
||||
# };
|
||||
# };
|
||||
# gitea = {
|
||||
# enable = true;
|
||||
# subdomain = "git";
|
||||
# exposure = "tunnel";
|
||||
# port = 5003;
|
||||
# cloudflared = {
|
||||
# tunnelId = "33e2fb8e-ecef-4d42-b845-6d15e216e448";
|
||||
# credentialsFile = config.age.secrets.giteaCloudflared.path;
|
||||
# };
|
||||
# homepage = {
|
||||
# name = "Gitea";
|
||||
# description = "Git with a cup of tea";
|
||||
# icon = "gitea.svg";
|
||||
# category = "Services";
|
||||
# };
|
||||
# };
|
||||
homepage-dashboard = {
|
||||
enable = true;
|
||||
subdomain = "";
|
||||
port = 8082;
|
||||
};
|
||||
n8n = {
|
||||
enable = true;
|
||||
subdomain = "n8n";
|
||||
port = 5678;
|
||||
homepage = {
|
||||
name = "n8n";
|
||||
description = "A workflow automation platform";
|
||||
icon = "n8n.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
bazarr = {
|
||||
enable = true;
|
||||
subdomain = "bazarr";
|
||||
port = 6767;
|
||||
homepage = {
|
||||
name = "Bazarr";
|
||||
description = "Subtitle manager";
|
||||
icon = "bazarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
prowlarr = {
|
||||
enable = true;
|
||||
subdomain = "prowlarr";
|
||||
port = 9696;
|
||||
homepage = {
|
||||
name = "prowlarr";
|
||||
description = "PVR indexer";
|
||||
icon = "prowlarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
flaresolverr = {
|
||||
enable = true;
|
||||
subdomain = "flaresolverr";
|
||||
port = 8191;
|
||||
homepage = {
|
||||
name = "FlareSolverr";
|
||||
description = "Proxy to bypass Cloudflare/DDoS-GUARD protection";
|
||||
icon = "flaresolverr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
lidarr = {
|
||||
enable = true;
|
||||
subdomain = "lidarr";
|
||||
port = 8686;
|
||||
homepage = {
|
||||
name = "Lidarr";
|
||||
description = "Music collection manager";
|
||||
icon = "lidarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
sonarr = {
|
||||
enable = true;
|
||||
subdomain = "sonarr";
|
||||
port = 8989;
|
||||
homepage = {
|
||||
name = "Sonarr";
|
||||
description = "Internet PVR for Usenet and Torrents";
|
||||
icon = "sonarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
radarr = {
|
||||
enable = true;
|
||||
subdomain = "radarr";
|
||||
port = 7878;
|
||||
homepage = {
|
||||
name = "Radarr";
|
||||
description = "Movie collection manager";
|
||||
icon = "radarr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
jellyseerr = {
|
||||
enable = true;
|
||||
subdomain = "jellyseerr";
|
||||
port = 5055;
|
||||
homepage = {
|
||||
name = "Jellyseerr";
|
||||
description = "Media request and discovery manager";
|
||||
icon = "jellyserr.svg";
|
||||
category = "Arr";
|
||||
};
|
||||
};
|
||||
jellyfin = {
|
||||
enable = true;
|
||||
subdomain = "fin";
|
||||
exposure = "tailscale";
|
||||
port = 8096;
|
||||
homepage = {
|
||||
name = "Jellyfin";
|
||||
description = "The Free Software Media System";
|
||||
icon = "jellyfin.svg";
|
||||
category = "Media";
|
||||
};
|
||||
};
|
||||
uptime-kuma = {
|
||||
enable = true;
|
||||
subdomain = "uptime";
|
||||
port = 3001;
|
||||
homepage = {
|
||||
name = "Uptime Kuma";
|
||||
description = "Service monitoring tool";
|
||||
icon = "uptime-kuma.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
gitea = {
|
||||
enable = true;
|
||||
subdomain = "git";
|
||||
exposure = "tunnel";
|
||||
port = 5003;
|
||||
cloudflared = {
|
||||
tunnelId = "33e2fb8e-ecef-4d42-b845-6d15e216e448";
|
||||
credentialsFile = config.age.secrets.giteaCloudflared.path;
|
||||
};
|
||||
homepage = {
|
||||
name = "Gitea";
|
||||
description = "Git with a cup of tea";
|
||||
icon = "gitea.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
vaultwarden = {
|
||||
enable = true;
|
||||
# subdomain = "vault";
|
||||
# exposure = "tunnel";
|
||||
# port = 8222;
|
||||
# cloudflared = {
|
||||
# tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
||||
# credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
|
||||
# };
|
||||
# homepage = {
|
||||
# name = "Vaultwarden";
|
||||
# description = "Password manager";
|
||||
# icon = "vaultwarden.svg";
|
||||
# category = "Services";
|
||||
# };
|
||||
subdomain = "vault";
|
||||
exposure = "tunnel";
|
||||
port = 8222;
|
||||
cloudflared = {
|
||||
tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
||||
credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
|
||||
};
|
||||
homepage = {
|
||||
name = "Vaultwarden";
|
||||
description = "Password manager";
|
||||
icon = "vaultwarden.svg";
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
nextcloud = {
|
||||
enable = true;
|
||||
subdomain = "cloud";
|
||||
exposure = "local";
|
||||
port = 8182;
|
||||
adminpassFile = config.age.secrets.nextcloudAdminPass.path;
|
||||
homepage = {
|
||||
name = "Nextcloud";
|
||||
description = "A safe home for all your data";
|
||||
@@ -216,40 +215,40 @@
|
||||
category = "Services";
|
||||
};
|
||||
};
|
||||
# qbittorrent = {
|
||||
# enable = true;
|
||||
# subdomain = "qbt";
|
||||
# port = 8080;
|
||||
# homepage = {
|
||||
# name = "qBittorrent";
|
||||
# description = "Torrent client";
|
||||
# icon = "qbittorrent.svg";
|
||||
# category = "Downloads";
|
||||
# };
|
||||
# };
|
||||
# slskd = {
|
||||
# enable = true;
|
||||
# subdomain = "slskd";
|
||||
# port = 5030;
|
||||
# homepage = {
|
||||
# name = "Soulseek";
|
||||
# description = "Web-based Soulseek client";
|
||||
# icon = "slskd.svg";
|
||||
# category = "Downloads";
|
||||
# };
|
||||
# };
|
||||
# pihole = {
|
||||
# enable = true;
|
||||
# subdomain = "pihole";
|
||||
# port = 8053;
|
||||
# homepage = {
|
||||
# name = "PiHole";
|
||||
# description = "Adblocking and DNS service";
|
||||
# icon = "pi-hole.svg";
|
||||
# category = "Services";
|
||||
# path = "/admin";
|
||||
# };
|
||||
# };
|
||||
qbittorrent = {
|
||||
enable = true;
|
||||
subdomain = "qbt";
|
||||
port = 8080;
|
||||
homepage = {
|
||||
name = "qBittorrent";
|
||||
description = "Torrent client";
|
||||
icon = "qbittorrent.svg";
|
||||
category = "Downloads";
|
||||
};
|
||||
};
|
||||
slskd = {
|
||||
enable = true;
|
||||
subdomain = "slskd";
|
||||
port = 5030;
|
||||
homepage = {
|
||||
name = "Soulseek";
|
||||
description = "Web-based Soulseek client";
|
||||
icon = "slskd.svg";
|
||||
category = "Downloads";
|
||||
};
|
||||
};
|
||||
pihole = {
|
||||
enable = true;
|
||||
subdomain = "pihole";
|
||||
port = 8053;
|
||||
homepage = {
|
||||
name = "PiHole";
|
||||
description = "Adblocking and DNS service";
|
||||
icon = "pi-hole.svg";
|
||||
category = "Services";
|
||||
path = "/admin";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
5
lib/server/default.nix
Normal file
5
lib/server/default.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
imports = [
|
||||
./serviceurl
|
||||
];
|
||||
}
|
||||
23
lib/server/serviceurl/default.nix
Normal file
23
lib/server/serviceurl/default.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
mkServiceUrl' = import ./serviceurl.nix {inherit config;};
|
||||
in {
|
||||
options.clib = {
|
||||
server = {
|
||||
mkServiceUrl = lib.mkOption {
|
||||
type = lib.types.function;
|
||||
readOnly = true;
|
||||
description = "Helper function to generate a service URL.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config.clib = {
|
||||
server = {
|
||||
mkServiceUrl = mkServiceUrl';
|
||||
};
|
||||
};
|
||||
}
|
||||
11
lib/server/serviceurl/serviceurl.nix
Normal file
11
lib/server/serviceurl/serviceurl.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{config}: service: let
|
||||
mainDomain = config.server.networking.domain;
|
||||
tailscaleDomain = "ts.${mainDomain}";
|
||||
|
||||
domain =
|
||||
if service.exposure == "tunnel"
|
||||
then mainDomain
|
||||
else if service.exposure == "tailscale"
|
||||
then tailscaleDomain
|
||||
else (service.domain or mainDomain);
|
||||
in "${service.subdomain}.${domain}"
|
||||
@@ -123,31 +123,6 @@
|
||||
server = {
|
||||
imports = [
|
||||
./server
|
||||
|
||||
./server/infra/authentik
|
||||
./server/infra/fail2ban
|
||||
./server/infra/keepalived
|
||||
./server/infra/podman
|
||||
./server/infra/postgres
|
||||
./server/infra/tailscale
|
||||
./server/infra/traefik
|
||||
./server/infra/unbound
|
||||
./server/infra/www
|
||||
|
||||
./server/services/bazarr
|
||||
./server/services/flaresolverr
|
||||
./server/services/gitea
|
||||
./server/services/homepage-dashboard
|
||||
./server/services/jellyfin
|
||||
./server/services/jellyseerr
|
||||
./server/services/lidarr
|
||||
./server/services/n8n
|
||||
./server/services/nextcloud
|
||||
./server/services/prowlarr
|
||||
./server/services/radarr
|
||||
./server/services/sonarr
|
||||
./server/services/uptime-kuma
|
||||
./server/services/vaultwarden
|
||||
];
|
||||
};
|
||||
settings = {
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
osConfig,
|
||||
cLib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
}: let
|
||||
inherit (lib) mkIf mkEnableOption;
|
||||
cfg = osConfig.nixos.programs.hyprland;
|
||||
|
||||
@@ -15,8 +14,7 @@ let
|
||||
#
|
||||
bg = osConfig.settings.theme.background;
|
||||
inherit (cLib.theme.bgs) resolve;
|
||||
in
|
||||
{
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
programs.hyprlock = {
|
||||
enable = true;
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
osConfig,
|
||||
cLib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = osConfig.nixos.programs.hyprland;
|
||||
@@ -32,8 +31,7 @@ let
|
||||
bg = bg.primary;
|
||||
}
|
||||
];
|
||||
in
|
||||
{
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
services.hyprpaper = {
|
||||
enable = true;
|
||||
|
||||
@@ -1,186 +1,8 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
hardDrives = [
|
||||
"/dev/disk/by-label/data"
|
||||
{self, ...}: {
|
||||
imports = [
|
||||
"${self}/lib/server"
|
||||
./options.nix
|
||||
./infra
|
||||
./services
|
||||
];
|
||||
inherit (lib) mkOption types;
|
||||
cfg = config.server;
|
||||
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
||||
in {
|
||||
options.server = {
|
||||
enable = lib.mkEnableOption "The server services and configuration variables";
|
||||
email = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Email name to be used to access the server services via Caddy reverse proxy
|
||||
'';
|
||||
};
|
||||
domain = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Domain name to be used to access the server services via Caddy reverse proxy
|
||||
'';
|
||||
};
|
||||
ip = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "The local IP of the service.";
|
||||
};
|
||||
user = lib.mkOption {
|
||||
default = "share";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
User to run the server services as
|
||||
'';
|
||||
};
|
||||
group = lib.mkOption {
|
||||
default = "share";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Group to run the server services as
|
||||
'';
|
||||
};
|
||||
uid = lib.mkOption {
|
||||
default = 1000;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
UID to run the server services as
|
||||
'';
|
||||
};
|
||||
gid = lib.mkOption {
|
||||
default = 1000;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
GID to run the server services as
|
||||
'';
|
||||
};
|
||||
timeZone = lib.mkOption {
|
||||
default = "Europe/Stockholm";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Time zone to be used for the server services
|
||||
'';
|
||||
};
|
||||
services = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "the service";
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "The subdomain for the service (e.g., 'jellyfin')";
|
||||
};
|
||||
exposure = lib.mkOption {
|
||||
type = lib.types.enum ["local" "tunnel" "tailscale"];
|
||||
default = "local";
|
||||
description = "Controls where the service is exposed";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 80;
|
||||
description = "The port to host service on.";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/${name}";
|
||||
description = "Configuration directory for ${name}.";
|
||||
};
|
||||
cloudflared = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
credentialsFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "/path/to/cloudflare-credentials.json";
|
||||
# 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";
|
||||
};
|
||||
};
|
||||
};
|
||||
description = "Cloudflare tunnel configuration for this service.";
|
||||
};
|
||||
homepage = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Display name on the homepage.";
|
||||
};
|
||||
description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "A short description for the homepage tile.";
|
||||
};
|
||||
icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Zervices c00l stuff";
|
||||
description = "Icon file name for the homepage tile.";
|
||||
};
|
||||
category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Homepage category grouping.";
|
||||
};
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "/admin";
|
||||
description = "Optional path suffix for homepage links (e.g. /admin).";
|
||||
};
|
||||
};
|
||||
};
|
||||
description = "Homepage metadata for this service.";
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
users = {
|
||||
groups.${cfg.group} = {
|
||||
gid = cfg.gid;
|
||||
};
|
||||
users.${cfg.user} = {
|
||||
uid = cfg.uid;
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
extraGroups = ifTheyExist [
|
||||
"audio"
|
||||
"video"
|
||||
"docker"
|
||||
"libvirtd"
|
||||
"qemu-libvirtd"
|
||||
"rtkit"
|
||||
"fail2ban"
|
||||
"vaultwarden"
|
||||
"qbittorrent"
|
||||
"lidarr"
|
||||
"prowlarr"
|
||||
"bazarr"
|
||||
"sonarr"
|
||||
"radarr"
|
||||
"media"
|
||||
"share"
|
||||
"render"
|
||||
"input"
|
||||
"authentik"
|
||||
"traefik"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
13
modules/server/infra/default.nix
Normal file
13
modules/server/infra/default.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
imports = [
|
||||
./authentik
|
||||
./fail2ban
|
||||
./keepalived
|
||||
./podman
|
||||
./postgres
|
||||
./tailscale
|
||||
./traefik
|
||||
./unbound
|
||||
./www
|
||||
];
|
||||
}
|
||||
@@ -11,23 +11,34 @@
|
||||
srv = config.server;
|
||||
|
||||
# Generates all Traefik routers from the central service list
|
||||
# generateRouters = services:
|
||||
# lib.mapAttrs' (
|
||||
# name: service: let
|
||||
# domain =
|
||||
# if service.exposure == "tunnel"
|
||||
# then "cnst.dev"
|
||||
# else if service.exposure == "tailscale"
|
||||
# then "ts.cnst.dev"
|
||||
# else srv.domain;
|
||||
# in
|
||||
# lib.nameValuePair "${service.subdomain}" {
|
||||
# entryPoints = ["websecure"];
|
||||
# rule = "Host(`${service.subdomain}.${domain}`)";
|
||||
# service = service.subdomain;
|
||||
# tls.certResolver = "letsencrypt";
|
||||
# }
|
||||
# ) (lib.filterAttrs (name: service: service.enable) services);
|
||||
|
||||
generateRouters = services:
|
||||
lib.mapAttrs' (
|
||||
name: service: let
|
||||
domain =
|
||||
if service.exposure == "tunnel"
|
||||
then "cnst.dev"
|
||||
else if service.exposure == "tailscale"
|
||||
then "ts.cnst.dev"
|
||||
else srv.domain;
|
||||
in
|
||||
name: service:
|
||||
lib.nameValuePair "${service.subdomain}" {
|
||||
entryPoints = ["websecure"];
|
||||
rule = "Host(`${service.subdomain}.${domain}`)";
|
||||
rule = "Host(`${config.clib.server.mkServiceUrl service}`)";
|
||||
service = service.subdomain;
|
||||
tls.certResolver = "letsencrypt";
|
||||
}
|
||||
) (lib.filterAttrs (name: service: service.enable) services);
|
||||
) (lib.filterAttrs (_: s: s.enable) services);
|
||||
|
||||
# Generates all Traefik backend services
|
||||
generateServices = services:
|
||||
|
||||
180
modules/server/options.nix
Normal file
180
modules/server/options.nix
Normal file
@@ -0,0 +1,180 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkOption types;
|
||||
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
||||
cfg = config.server;
|
||||
in {
|
||||
options.server = {
|
||||
enable = lib.mkEnableOption "The server services and configuration variables";
|
||||
email = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Email name to be used to access the server services via Caddy reverse proxy
|
||||
'';
|
||||
};
|
||||
domain = mkOption {
|
||||
default = "";
|
||||
type = types.str;
|
||||
description = ''
|
||||
Domain name to be used to access the server services via Caddy reverse proxy
|
||||
'';
|
||||
};
|
||||
ip = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "The local IP of the service.";
|
||||
};
|
||||
user = lib.mkOption {
|
||||
default = "share";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
User to run the server services as
|
||||
'';
|
||||
};
|
||||
group = lib.mkOption {
|
||||
default = "share";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Group to run the server services as
|
||||
'';
|
||||
};
|
||||
uid = lib.mkOption {
|
||||
default = 1000;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
UID to run the server services as
|
||||
'';
|
||||
};
|
||||
gid = lib.mkOption {
|
||||
default = 1000;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
GID to run the server services as
|
||||
'';
|
||||
};
|
||||
timeZone = lib.mkOption {
|
||||
default = "Europe/Stockholm";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Time zone to be used for the server services
|
||||
'';
|
||||
};
|
||||
services = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "the service";
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "The subdomain for the service (e.g., 'jellyfin')";
|
||||
};
|
||||
exposure = lib.mkOption {
|
||||
type = lib.types.enum ["local" "tunnel" "tailscale"];
|
||||
default = "local";
|
||||
description = "Controls where the service is exposed";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 80;
|
||||
description = "The port to host service on.";
|
||||
};
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/${name}";
|
||||
description = "Configuration directory for ${name}.";
|
||||
};
|
||||
cloudflared = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
description = "Cloudflare tunnel configuration for this service.";
|
||||
};
|
||||
homepage = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Display name on the homepage.";
|
||||
};
|
||||
description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "A short description for the homepage tile.";
|
||||
};
|
||||
icon = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Zervices c00l stuff";
|
||||
description = "Icon file name for the homepage tile.";
|
||||
};
|
||||
category = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Homepage category grouping.";
|
||||
};
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "/admin";
|
||||
description = "Optional path suffix for homepage links (e.g. /admin).";
|
||||
};
|
||||
};
|
||||
};
|
||||
description = "Homepage metadata for this service.";
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
users = {
|
||||
groups.${cfg.group} = {
|
||||
gid = cfg.gid;
|
||||
};
|
||||
users.${cfg.user} = {
|
||||
uid = cfg.uid;
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
extraGroups = ifTheyExist [
|
||||
"audio"
|
||||
"video"
|
||||
"docker"
|
||||
"libvirtd"
|
||||
"qemu-libvirtd"
|
||||
"rtkit"
|
||||
"fail2ban"
|
||||
"vaultwarden"
|
||||
"qbittorrent"
|
||||
"lidarr"
|
||||
"prowlarr"
|
||||
"bazarr"
|
||||
"sonarr"
|
||||
"radarr"
|
||||
"media"
|
||||
"share"
|
||||
"render"
|
||||
"input"
|
||||
"authentik"
|
||||
"traefik"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
18
modules/server/services/default.nix
Normal file
18
modules/server/services/default.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
imports = [
|
||||
./bazarr
|
||||
./flaresolverr
|
||||
./gitea
|
||||
./homepage-dashboard
|
||||
./jellyfin
|
||||
./jellyseerr
|
||||
./lidarr
|
||||
./n8n
|
||||
./nextcloud
|
||||
./prowlarr
|
||||
./radarr
|
||||
./sonarr
|
||||
./uptime-kuma
|
||||
./vaultwarden
|
||||
];
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
# "inspired" by @jtojnar <3
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
@@ -7,21 +6,23 @@
|
||||
}: let
|
||||
unit = "gitea";
|
||||
cfg = config.server.services.${unit};
|
||||
domain = "${cfg.subdomain}.${config.server.infra.www.url}";
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets = {
|
||||
giteaCloudflared.file = "${self}/secrets/giteaCloudflared.age";
|
||||
};
|
||||
age.secrets.giteaCloudflared.file = "${self}/secrets/giteaCloudflared.age";
|
||||
|
||||
server.infra = {
|
||||
fail2ban = {
|
||||
jails = {
|
||||
gitea = {
|
||||
serviceName = "gitea";
|
||||
failRegex = ''.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>'';
|
||||
};
|
||||
};
|
||||
fail2ban.jails.unit = {
|
||||
serviceName = "${unit}";
|
||||
failRegex = ''
|
||||
.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).*
|
||||
from <HOST>
|
||||
'';
|
||||
};
|
||||
|
||||
postgresql.databases = [
|
||||
{database = unit;}
|
||||
];
|
||||
};
|
||||
|
||||
services = {
|
||||
@@ -30,11 +31,11 @@ in {
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${cfg.url}".service = "http://localhost:${toString cfg.port}";
|
||||
ingress."${domain}".service = "http://localhost:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
${unit} = {
|
||||
gitea = {
|
||||
enable = true;
|
||||
appName = "cnix code forge";
|
||||
|
||||
@@ -46,63 +47,51 @@ in {
|
||||
createDatabase = false;
|
||||
};
|
||||
|
||||
lfs = {
|
||||
enable = true;
|
||||
};
|
||||
lfs.enable = true;
|
||||
|
||||
settings = {
|
||||
cors = {
|
||||
ENABLED = true;
|
||||
SCHEME = "https";
|
||||
ALLOW_DOMAIN = cfg.url;
|
||||
};
|
||||
log = {
|
||||
MODE = "console";
|
||||
ALLOW_DOMAIN = domain;
|
||||
};
|
||||
|
||||
log.MODE = "console";
|
||||
|
||||
mailer = {
|
||||
ENABLED = false;
|
||||
MAILER_TYPE = "sendmail";
|
||||
FROM = "noreply+adam@cnst.dev";
|
||||
SENDMAIL_PATH = "/run/wrappers/bin/sendmail";
|
||||
};
|
||||
picture = {
|
||||
DISABLE_GRAVATAR = true;
|
||||
};
|
||||
|
||||
picture.DISABLE_GRAVATAR = true;
|
||||
|
||||
repository = {
|
||||
DEFAULT_BRANCH = "main";
|
||||
DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
|
||||
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true;
|
||||
};
|
||||
indexer = {
|
||||
REPO_INDEXER_ENABLED = true;
|
||||
};
|
||||
|
||||
indexer.REPO_INDEXER_ENABLED = true;
|
||||
|
||||
oauth2_client = {
|
||||
ENABLE_AUTO_REGISTRATION = true;
|
||||
ACCOUNT_LINKING = "auto";
|
||||
};
|
||||
|
||||
server = {
|
||||
DOMAIN = cfg.url;
|
||||
DOMAIN = domain;
|
||||
LANDING_PAGE = "explore";
|
||||
HTTP_PORT = cfg.port;
|
||||
ROOT_URL = "https://${cfg.url}/";
|
||||
};
|
||||
security = {
|
||||
DISABLE_GIT_HOOKS = false;
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
};
|
||||
session = {
|
||||
COOKIE_SECURE = true;
|
||||
ROOT_URL = "https://${domain}/";
|
||||
};
|
||||
|
||||
security.DISABLE_GIT_HOOKS = false;
|
||||
service.DISABLE_REGISTRATION = true;
|
||||
session.COOKIE_SECURE = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
server.infra.postgresql.databases = [
|
||||
{
|
||||
database = "gitea";
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
...
|
||||
}: let
|
||||
unit = "homepage-dashboard";
|
||||
cfg = config.server.services.homepage-dashboard;
|
||||
cfg = config.server.services.${unit};
|
||||
srv = config.server;
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -14,11 +14,14 @@ in {
|
||||
file = "${self}/secrets/homepageEnvironment.age";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
glances.enable = true;
|
||||
|
||||
${unit} = {
|
||||
enable = true;
|
||||
environmentFile = config.age.secrets.homepageEnvironment.path;
|
||||
|
||||
settings = {
|
||||
layout = [
|
||||
{
|
||||
@@ -53,10 +56,12 @@ in {
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
headerStyle = "clean";
|
||||
statusStyle = "dot";
|
||||
hideVersion = "true";
|
||||
};
|
||||
|
||||
widgets = [
|
||||
{
|
||||
openmeteo = {
|
||||
@@ -77,6 +82,7 @@ in {
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
services = let
|
||||
homepageCategories = [
|
||||
"Arr"
|
||||
@@ -84,21 +90,30 @@ in {
|
||||
"Downloads"
|
||||
"Services"
|
||||
];
|
||||
hl = config.server.services;
|
||||
homepageServices = x: (lib.attrsets.filterAttrs (
|
||||
_name: value: value ? homepage && value.homepage.category == x
|
||||
|
||||
allServices = srv.services;
|
||||
|
||||
homepageServicesFor = category:
|
||||
lib.filterAttrs
|
||||
(
|
||||
name: value:
|
||||
name
|
||||
!= unit
|
||||
&& value ? homepage
|
||||
&& value.homepage.category == category
|
||||
)
|
||||
srv.services);
|
||||
allServices;
|
||||
in
|
||||
lib.lists.forEach homepageCategories (cat: {
|
||||
"${cat}" =
|
||||
lib.lists.forEach (lib.attrsets.mapAttrsToList (name: _value: name) (homepageServices "${cat}"))
|
||||
lib.lists.forEach
|
||||
(lib.attrsets.mapAttrsToList (name: _value: name) (homepageServicesFor cat))
|
||||
(x: {
|
||||
"${hl.${x}.homepage.name}" = {
|
||||
icon = hl.${x}.homepage.icon;
|
||||
description = hl.${x}.homepage.description;
|
||||
href = "https://${hl.${x}.url}";
|
||||
siteMonitor = "https://${hl.${x}.url}";
|
||||
"${allServices.${x}.homepage.name}" = {
|
||||
icon = allServices.${x}.homepage.icon;
|
||||
description = allServices.${x}.homepage.description;
|
||||
href = "https://${allServices.${x}.url}";
|
||||
siteMonitor = "https://${allServices.${x}.url}";
|
||||
};
|
||||
});
|
||||
})
|
||||
|
||||
@@ -15,19 +15,15 @@ in {
|
||||
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
|
||||
};
|
||||
|
||||
server.infra.fail2ban = lib.mkIf srv.infra.fail2ban.enable {
|
||||
jails = {
|
||||
nextcloud = {
|
||||
serviceName = "${unit}";
|
||||
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
|
||||
failRegex = ''
|
||||
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
|
||||
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Two-factor challenge failed:
|
||||
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
|
||||
'';
|
||||
datePattern = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
|
||||
};
|
||||
};
|
||||
server.infra.fail2ban.jails.nextcloud = {
|
||||
serviceName = "${unit}";
|
||||
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
|
||||
failRegex = ''
|
||||
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
|
||||
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Two-factor challenge failed:
|
||||
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
|
||||
'';
|
||||
datePattern = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
|
||||
};
|
||||
|
||||
services = {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
}: let
|
||||
unit = "vaultwarden";
|
||||
cfg = config.server.services.${unit};
|
||||
www = config.server.infra.www;
|
||||
domain = "${cfg.subdomain}.${config.server.infra.www.url}";
|
||||
in {
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets = {
|
||||
@@ -15,15 +15,9 @@ in {
|
||||
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
|
||||
};
|
||||
|
||||
server.infra = {
|
||||
fail2ban = {
|
||||
jails = {
|
||||
vaultwarden = {
|
||||
serviceName = "${unit}";
|
||||
failRegex = ''^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$'';
|
||||
};
|
||||
};
|
||||
};
|
||||
server.infra.fail2ban.jails.${unit} = {
|
||||
serviceName = "${unit}";
|
||||
failRegex = ''^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$'';
|
||||
};
|
||||
|
||||
services = {
|
||||
@@ -32,7 +26,7 @@ in {
|
||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||
default = "http_status:404";
|
||||
ingress."${cfg.url}".service = "http://localhost:${toString cfg.port}";
|
||||
ingress."${domain}".service = "http://localhost:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -43,7 +37,7 @@ in {
|
||||
backupDir = "/var/backup/vaultwarden";
|
||||
|
||||
config = {
|
||||
DOMAIN = "https://vault.${www.url}";
|
||||
DOMAIN = "https://${domain}";
|
||||
SIGNUPS_ALLOWED = false;
|
||||
ROCKET_ADDRESS = "127.0.0.1";
|
||||
ROCKET_PORT = cfg.port;
|
||||
|
||||
Reference in New Issue
Block a user