feat(refactor): WIP 2.0 some progress
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
description = "cnix nix";
|
description = "cnix nix";
|
||||||
|
|
||||||
outputs =
|
outputs = inputs:
|
||||||
inputs:
|
|
||||||
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
|
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
|
||||||
systems = [
|
systems = [
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
@@ -17,13 +16,11 @@
|
|||||||
./fmt-hooks.nix
|
./fmt-hooks.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
perSystem =
|
perSystem = {
|
||||||
{
|
|
||||||
config,
|
config,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}: {
|
||||||
{
|
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
packages = [
|
packages = [
|
||||||
pkgs.git
|
pkgs.git
|
||||||
|
|||||||
@@ -4,10 +4,8 @@
|
|||||||
homeImports,
|
homeImports,
|
||||||
self,
|
self,
|
||||||
...
|
...
|
||||||
}:
|
}: {
|
||||||
{
|
flake.nixosConfigurations = let
|
||||||
flake.nixosConfigurations =
|
|
||||||
let
|
|
||||||
cLib = import ../lib inputs.nixpkgs.lib;
|
cLib = import ../lib inputs.nixpkgs.lib;
|
||||||
userConfig = "${self}/home";
|
userConfig = "${self}/home";
|
||||||
systemConfig = "${self}/system";
|
systemConfig = "${self}/system";
|
||||||
@@ -37,8 +35,7 @@
|
|||||||
smodPath
|
smodPath
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
kima = nixosSystem {
|
kima = nixosSystem {
|
||||||
inherit specialArgs;
|
inherit specialArgs;
|
||||||
modules = [
|
modules = [
|
||||||
|
|||||||
@@ -55,160 +55,159 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
# homepage-dashboard = {
|
homepage-dashboard = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "";
|
subdomain = "";
|
||||||
# port = "8082";
|
port = 8082;
|
||||||
# };
|
};
|
||||||
# n8n = {
|
n8n = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "n8n";
|
subdomain = "n8n";
|
||||||
# port = "5678";
|
port = 5678;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "n8n";
|
name = "n8n";
|
||||||
# description = "A workflow automation platform";
|
description = "A workflow automation platform";
|
||||||
# icon = "n8n.svg";
|
icon = "n8n.svg";
|
||||||
# category = "Services";
|
category = "Services";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# bazarr = {
|
bazarr = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "bazarr";
|
subdomain = "bazarr";
|
||||||
# port = 6767;
|
port = 6767;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Bazarr";
|
name = "Bazarr";
|
||||||
# description = "Subtitle manager";
|
description = "Subtitle manager";
|
||||||
# icon = "bazarr.svg";
|
icon = "bazarr.svg";
|
||||||
# category = "Arr";
|
category = "Arr";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# prowlarr = {
|
prowlarr = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "prowlarr";
|
subdomain = "prowlarr";
|
||||||
# port = 9696;
|
port = 9696;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "prowlarr";
|
name = "prowlarr";
|
||||||
# description = "PVR indexer";
|
description = "PVR indexer";
|
||||||
# icon = "prowlarr.svg";
|
icon = "prowlarr.svg";
|
||||||
# category = "Arr";
|
category = "Arr";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# flaresolverr = {
|
flaresolverr = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "flaresolverr";
|
subdomain = "flaresolverr";
|
||||||
# port = 8191;
|
port = 8191;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "FlareSolverr";
|
name = "FlareSolverr";
|
||||||
# description = "Proxy to bypass Cloudflare/DDoS-GUARD protection";
|
description = "Proxy to bypass Cloudflare/DDoS-GUARD protection";
|
||||||
# icon = "flaresolverr.svg";
|
icon = "flaresolverr.svg";
|
||||||
# category = "Arr";
|
category = "Arr";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# lidarr = {
|
lidarr = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "lidarr";
|
subdomain = "lidarr";
|
||||||
# port = 8686;
|
port = 8686;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Lidarr";
|
name = "Lidarr";
|
||||||
# description = "Music collection manager";
|
description = "Music collection manager";
|
||||||
# icon = "lidarr.svg";
|
icon = "lidarr.svg";
|
||||||
# category = "Arr";
|
category = "Arr";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# sonarr = {
|
sonarr = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "sonarr";
|
subdomain = "sonarr";
|
||||||
# port = 8989;
|
port = 8989;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Sonarr";
|
name = "Sonarr";
|
||||||
# description = "Internet PVR for Usenet and Torrents";
|
description = "Internet PVR for Usenet and Torrents";
|
||||||
# icon = "sonarr.svg";
|
icon = "sonarr.svg";
|
||||||
# category = "Arr";
|
category = "Arr";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# radarr = {
|
radarr = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "radarr";
|
subdomain = "radarr";
|
||||||
# port = 7878;
|
port = 7878;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Radarr";
|
name = "Radarr";
|
||||||
# description = "Movie collection manager";
|
description = "Movie collection manager";
|
||||||
# icon = "radarr.svg";
|
icon = "radarr.svg";
|
||||||
# category = "Arr";
|
category = "Arr";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# jellyseerr = {
|
jellyseerr = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "jellyseerr";
|
subdomain = "jellyseerr";
|
||||||
# port = 5055;
|
port = 5055;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Jellyseerr";
|
name = "Jellyseerr";
|
||||||
# description = "Media request and discovery manager";
|
description = "Media request and discovery manager";
|
||||||
# icon = "jellyserr.svg";
|
icon = "jellyserr.svg";
|
||||||
# category = "Arr";
|
category = "Arr";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# jellyfin = {
|
jellyfin = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "fin";
|
subdomain = "fin";
|
||||||
# exposure = "tailscale";
|
exposure = "tailscale";
|
||||||
# port = 8096;
|
port = 8096;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Jellyfin";
|
name = "Jellyfin";
|
||||||
# description = "The Free Software Media System";
|
description = "The Free Software Media System";
|
||||||
# icon = "jellyfin.svg";
|
icon = "jellyfin.svg";
|
||||||
# category = "Media";
|
category = "Media";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# uptime-kuma = {
|
uptime-kuma = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "uptime";
|
subdomain = "uptime";
|
||||||
# port = 3001;
|
port = 3001;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Uptime Kuma";
|
name = "Uptime Kuma";
|
||||||
# description = "Service monitoring tool";
|
description = "Service monitoring tool";
|
||||||
# icon = "uptime-kuma.svg";
|
icon = "uptime-kuma.svg";
|
||||||
# category = "Services";
|
category = "Services";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# gitea = {
|
gitea = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "git";
|
subdomain = "git";
|
||||||
# exposure = "tunnel";
|
exposure = "tunnel";
|
||||||
# port = 5003;
|
port = 5003;
|
||||||
# cloudflared = {
|
cloudflared = {
|
||||||
# tunnelId = "33e2fb8e-ecef-4d42-b845-6d15e216e448";
|
tunnelId = "33e2fb8e-ecef-4d42-b845-6d15e216e448";
|
||||||
# credentialsFile = config.age.secrets.giteaCloudflared.path;
|
credentialsFile = config.age.secrets.giteaCloudflared.path;
|
||||||
# };
|
};
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Gitea";
|
name = "Gitea";
|
||||||
# description = "Git with a cup of tea";
|
description = "Git with a cup of tea";
|
||||||
# icon = "gitea.svg";
|
icon = "gitea.svg";
|
||||||
# category = "Services";
|
category = "Services";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
vaultwarden = {
|
vaultwarden = {
|
||||||
enable = true;
|
enable = true;
|
||||||
# subdomain = "vault";
|
subdomain = "vault";
|
||||||
# exposure = "tunnel";
|
exposure = "tunnel";
|
||||||
# port = 8222;
|
port = 8222;
|
||||||
# cloudflared = {
|
cloudflared = {
|
||||||
# tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
||||||
# credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
|
credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
|
||||||
# };
|
};
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Vaultwarden";
|
name = "Vaultwarden";
|
||||||
# description = "Password manager";
|
description = "Password manager";
|
||||||
# icon = "vaultwarden.svg";
|
icon = "vaultwarden.svg";
|
||||||
# category = "Services";
|
category = "Services";
|
||||||
# };
|
};
|
||||||
};
|
};
|
||||||
nextcloud = {
|
nextcloud = {
|
||||||
enable = true;
|
enable = true;
|
||||||
subdomain = "cloud";
|
subdomain = "cloud";
|
||||||
exposure = "local";
|
exposure = "local";
|
||||||
port = 8182;
|
port = 8182;
|
||||||
adminpassFile = config.age.secrets.nextcloudAdminPass.path;
|
|
||||||
homepage = {
|
homepage = {
|
||||||
name = "Nextcloud";
|
name = "Nextcloud";
|
||||||
description = "A safe home for all your data";
|
description = "A safe home for all your data";
|
||||||
@@ -216,40 +215,40 @@
|
|||||||
category = "Services";
|
category = "Services";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
# qbittorrent = {
|
qbittorrent = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "qbt";
|
subdomain = "qbt";
|
||||||
# port = 8080;
|
port = 8080;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "qBittorrent";
|
name = "qBittorrent";
|
||||||
# description = "Torrent client";
|
description = "Torrent client";
|
||||||
# icon = "qbittorrent.svg";
|
icon = "qbittorrent.svg";
|
||||||
# category = "Downloads";
|
category = "Downloads";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# slskd = {
|
slskd = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "slskd";
|
subdomain = "slskd";
|
||||||
# port = 5030;
|
port = 5030;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "Soulseek";
|
name = "Soulseek";
|
||||||
# description = "Web-based Soulseek client";
|
description = "Web-based Soulseek client";
|
||||||
# icon = "slskd.svg";
|
icon = "slskd.svg";
|
||||||
# category = "Downloads";
|
category = "Downloads";
|
||||||
# };
|
};
|
||||||
# };
|
};
|
||||||
# pihole = {
|
pihole = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# subdomain = "pihole";
|
subdomain = "pihole";
|
||||||
# port = 8053;
|
port = 8053;
|
||||||
# homepage = {
|
homepage = {
|
||||||
# name = "PiHole";
|
name = "PiHole";
|
||||||
# description = "Adblocking and DNS service";
|
description = "Adblocking and DNS service";
|
||||||
# icon = "pi-hole.svg";
|
icon = "pi-hole.svg";
|
||||||
# category = "Services";
|
category = "Services";
|
||||||
# path = "/admin";
|
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 = {
|
server = {
|
||||||
imports = [
|
imports = [
|
||||||
./server
|
./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 = {
|
settings = {
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
osConfig,
|
osConfig,
|
||||||
cLib,
|
cLib,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
cfg = osConfig.nixos.programs.hyprland;
|
cfg = osConfig.nixos.programs.hyprland;
|
||||||
|
|
||||||
@@ -15,8 +14,7 @@ let
|
|||||||
#
|
#
|
||||||
bg = osConfig.settings.theme.background;
|
bg = osConfig.settings.theme.background;
|
||||||
inherit (cLib.theme.bgs) resolve;
|
inherit (cLib.theme.bgs) resolve;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
programs.hyprlock = {
|
programs.hyprlock = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
osConfig,
|
osConfig,
|
||||||
cLib,
|
cLib,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
inherit (lib) mkIf;
|
inherit (lib) mkIf;
|
||||||
|
|
||||||
cfg = osConfig.nixos.programs.hyprland;
|
cfg = osConfig.nixos.programs.hyprland;
|
||||||
@@ -32,8 +31,7 @@ let
|
|||||||
bg = bg.primary;
|
bg = bg.primary;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services.hyprpaper = {
|
services.hyprpaper = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|||||||
@@ -1,186 +1,8 @@
|
|||||||
{
|
{self, ...}: {
|
||||||
lib,
|
imports = [
|
||||||
config,
|
"${self}/lib/server"
|
||||||
pkgs,
|
./options.nix
|
||||||
...
|
./infra
|
||||||
}: let
|
./services
|
||||||
hardDrives = [
|
|
||||||
"/dev/disk/by-label/data"
|
|
||||||
];
|
];
|
||||||
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;
|
srv = config.server;
|
||||||
|
|
||||||
# Generates all Traefik routers from the central service list
|
# 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:
|
generateRouters = services:
|
||||||
lib.mapAttrs' (
|
lib.mapAttrs' (
|
||||||
name: service: let
|
name: service:
|
||||||
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}" {
|
lib.nameValuePair "${service.subdomain}" {
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
rule = "Host(`${service.subdomain}.${domain}`)";
|
rule = "Host(`${config.clib.server.mkServiceUrl service}`)";
|
||||||
service = service.subdomain;
|
service = service.subdomain;
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
}
|
}
|
||||||
) (lib.filterAttrs (name: service: service.enable) services);
|
) (lib.filterAttrs (_: s: s.enable) services);
|
||||||
|
|
||||||
# Generates all Traefik backend services
|
# Generates all Traefik backend services
|
||||||
generateServices = 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,
|
config,
|
||||||
lib,
|
lib,
|
||||||
@@ -7,21 +6,23 @@
|
|||||||
}: let
|
}: let
|
||||||
unit = "gitea";
|
unit = "gitea";
|
||||||
cfg = config.server.services.${unit};
|
cfg = config.server.services.${unit};
|
||||||
|
domain = "${cfg.subdomain}.${config.server.infra.www.url}";
|
||||||
in {
|
in {
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
age.secrets = {
|
age.secrets.giteaCloudflared.file = "${self}/secrets/giteaCloudflared.age";
|
||||||
giteaCloudflared.file = "${self}/secrets/giteaCloudflared.age";
|
|
||||||
};
|
|
||||||
|
|
||||||
server.infra = {
|
server.infra = {
|
||||||
fail2ban = {
|
fail2ban.jails.unit = {
|
||||||
jails = {
|
serviceName = "${unit}";
|
||||||
gitea = {
|
failRegex = ''
|
||||||
serviceName = "gitea";
|
.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).*
|
||||||
failRegex = ''.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>'';
|
from <HOST>
|
||||||
};
|
'';
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
postgresql.databases = [
|
||||||
|
{database = unit;}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
@@ -30,11 +31,11 @@ in {
|
|||||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||||
default = "http_status:404";
|
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;
|
enable = true;
|
||||||
appName = "cnix code forge";
|
appName = "cnix code forge";
|
||||||
|
|
||||||
@@ -46,63 +47,51 @@ in {
|
|||||||
createDatabase = false;
|
createDatabase = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
lfs = {
|
lfs.enable = true;
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
cors = {
|
cors = {
|
||||||
ENABLED = true;
|
ENABLED = true;
|
||||||
SCHEME = "https";
|
SCHEME = "https";
|
||||||
ALLOW_DOMAIN = cfg.url;
|
ALLOW_DOMAIN = domain;
|
||||||
};
|
|
||||||
log = {
|
|
||||||
MODE = "console";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log.MODE = "console";
|
||||||
|
|
||||||
mailer = {
|
mailer = {
|
||||||
ENABLED = false;
|
ENABLED = false;
|
||||||
MAILER_TYPE = "sendmail";
|
MAILER_TYPE = "sendmail";
|
||||||
FROM = "noreply+adam@cnst.dev";
|
FROM = "noreply+adam@cnst.dev";
|
||||||
SENDMAIL_PATH = "/run/wrappers/bin/sendmail";
|
SENDMAIL_PATH = "/run/wrappers/bin/sendmail";
|
||||||
};
|
};
|
||||||
picture = {
|
|
||||||
DISABLE_GRAVATAR = true;
|
picture.DISABLE_GRAVATAR = true;
|
||||||
};
|
|
||||||
repository = {
|
repository = {
|
||||||
DEFAULT_BRANCH = "main";
|
DEFAULT_BRANCH = "main";
|
||||||
DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
|
DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
|
||||||
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true;
|
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true;
|
||||||
};
|
};
|
||||||
indexer = {
|
|
||||||
REPO_INDEXER_ENABLED = true;
|
indexer.REPO_INDEXER_ENABLED = true;
|
||||||
};
|
|
||||||
oauth2_client = {
|
oauth2_client = {
|
||||||
ENABLE_AUTO_REGISTRATION = true;
|
ENABLE_AUTO_REGISTRATION = true;
|
||||||
ACCOUNT_LINKING = "auto";
|
ACCOUNT_LINKING = "auto";
|
||||||
};
|
};
|
||||||
|
|
||||||
server = {
|
server = {
|
||||||
DOMAIN = cfg.url;
|
DOMAIN = domain;
|
||||||
LANDING_PAGE = "explore";
|
LANDING_PAGE = "explore";
|
||||||
HTTP_PORT = cfg.port;
|
HTTP_PORT = cfg.port;
|
||||||
ROOT_URL = "https://${cfg.url}/";
|
ROOT_URL = "https://${domain}/";
|
||||||
};
|
|
||||||
security = {
|
|
||||||
DISABLE_GIT_HOOKS = false;
|
|
||||||
};
|
|
||||||
service = {
|
|
||||||
DISABLE_REGISTRATION = true;
|
|
||||||
};
|
|
||||||
session = {
|
|
||||||
COOKIE_SECURE = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
server.infra.postgresql.databases = [
|
security.DISABLE_GIT_HOOKS = false;
|
||||||
{
|
service.DISABLE_REGISTRATION = true;
|
||||||
database = "gitea";
|
session.COOKIE_SECURE = true;
|
||||||
}
|
};
|
||||||
];
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
unit = "homepage-dashboard";
|
unit = "homepage-dashboard";
|
||||||
cfg = config.server.services.homepage-dashboard;
|
cfg = config.server.services.${unit};
|
||||||
srv = config.server;
|
srv = config.server;
|
||||||
in {
|
in {
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
@@ -14,11 +14,14 @@ in {
|
|||||||
file = "${self}/secrets/homepageEnvironment.age";
|
file = "${self}/secrets/homepageEnvironment.age";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
glances.enable = true;
|
glances.enable = true;
|
||||||
|
|
||||||
${unit} = {
|
${unit} = {
|
||||||
enable = true;
|
enable = true;
|
||||||
environmentFile = config.age.secrets.homepageEnvironment.path;
|
environmentFile = config.age.secrets.homepageEnvironment.path;
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
layout = [
|
layout = [
|
||||||
{
|
{
|
||||||
@@ -53,10 +56,12 @@ in {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
headerStyle = "clean";
|
headerStyle = "clean";
|
||||||
statusStyle = "dot";
|
statusStyle = "dot";
|
||||||
hideVersion = "true";
|
hideVersion = "true";
|
||||||
};
|
};
|
||||||
|
|
||||||
widgets = [
|
widgets = [
|
||||||
{
|
{
|
||||||
openmeteo = {
|
openmeteo = {
|
||||||
@@ -77,6 +82,7 @@ in {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
services = let
|
services = let
|
||||||
homepageCategories = [
|
homepageCategories = [
|
||||||
"Arr"
|
"Arr"
|
||||||
@@ -84,21 +90,30 @@ in {
|
|||||||
"Downloads"
|
"Downloads"
|
||||||
"Services"
|
"Services"
|
||||||
];
|
];
|
||||||
hl = config.server.services;
|
|
||||||
homepageServices = x: (lib.attrsets.filterAttrs (
|
allServices = srv.services;
|
||||||
_name: value: value ? homepage && value.homepage.category == x
|
|
||||||
|
homepageServicesFor = category:
|
||||||
|
lib.filterAttrs
|
||||||
|
(
|
||||||
|
name: value:
|
||||||
|
name
|
||||||
|
!= unit
|
||||||
|
&& value ? homepage
|
||||||
|
&& value.homepage.category == category
|
||||||
)
|
)
|
||||||
srv.services);
|
allServices;
|
||||||
in
|
in
|
||||||
lib.lists.forEach homepageCategories (cat: {
|
lib.lists.forEach homepageCategories (cat: {
|
||||||
"${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: {
|
(x: {
|
||||||
"${hl.${x}.homepage.name}" = {
|
"${allServices.${x}.homepage.name}" = {
|
||||||
icon = hl.${x}.homepage.icon;
|
icon = allServices.${x}.homepage.icon;
|
||||||
description = hl.${x}.homepage.description;
|
description = allServices.${x}.homepage.description;
|
||||||
href = "https://${hl.${x}.url}";
|
href = "https://${allServices.${x}.url}";
|
||||||
siteMonitor = "https://${hl.${x}.url}";
|
siteMonitor = "https://${allServices.${x}.url}";
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ in {
|
|||||||
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
|
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
|
||||||
};
|
};
|
||||||
|
|
||||||
server.infra.fail2ban = lib.mkIf srv.infra.fail2ban.enable {
|
server.infra.fail2ban.jails.nextcloud = {
|
||||||
jails = {
|
|
||||||
nextcloud = {
|
|
||||||
serviceName = "${unit}";
|
serviceName = "${unit}";
|
||||||
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
|
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
|
||||||
failRegex = ''
|
failRegex = ''
|
||||||
@@ -27,8 +25,6 @@ in {
|
|||||||
'';
|
'';
|
||||||
datePattern = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
|
datePattern = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
${unit} = {
|
${unit} = {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
}: let
|
}: let
|
||||||
unit = "vaultwarden";
|
unit = "vaultwarden";
|
||||||
cfg = config.server.services.${unit};
|
cfg = config.server.services.${unit};
|
||||||
www = config.server.infra.www;
|
domain = "${cfg.subdomain}.${config.server.infra.www.url}";
|
||||||
in {
|
in {
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
age.secrets = {
|
age.secrets = {
|
||||||
@@ -15,16 +15,10 @@ in {
|
|||||||
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
|
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
|
||||||
};
|
};
|
||||||
|
|
||||||
server.infra = {
|
server.infra.fail2ban.jails.${unit} = {
|
||||||
fail2ban = {
|
|
||||||
jails = {
|
|
||||||
vaultwarden = {
|
|
||||||
serviceName = "${unit}";
|
serviceName = "${unit}";
|
||||||
failRegex = ''^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$'';
|
failRegex = ''^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$'';
|
||||||
};
|
};
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
cloudflared = {
|
cloudflared = {
|
||||||
@@ -32,7 +26,7 @@ in {
|
|||||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||||
default = "http_status:404";
|
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";
|
backupDir = "/var/backup/vaultwarden";
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
DOMAIN = "https://vault.${www.url}";
|
DOMAIN = "https://${domain}";
|
||||||
SIGNUPS_ALLOWED = false;
|
SIGNUPS_ALLOWED = false;
|
||||||
ROCKET_ADDRESS = "127.0.0.1";
|
ROCKET_ADDRESS = "127.0.0.1";
|
||||||
ROCKET_PORT = cfg.port;
|
ROCKET_PORT = cfg.port;
|
||||||
|
|||||||
Reference in New Issue
Block a user