Compare commits
7 Commits
e69fd5bf8f
...
eac443f280
Author | SHA1 | Date | |
---|---|---|---|
eac443f280 | |||
d557820d6c | |||
4d658e10d3 | |||
9ac9613d67 | |||
e657ebb134 | |||
d1b07ec06b | |||
89621945f8 |
5
Makefile
5
Makefile
@ -20,3 +20,8 @@ rekey-secrets:
|
||||
.PHONY: clean-old-nixos-profiles
|
||||
clean-old-nixos-profiles:
|
||||
doas nix-collect-garbage -d
|
||||
|
||||
# Garbage Collect
|
||||
.PHONY: gc
|
||||
gc:
|
||||
nix store gc
|
@ -37,17 +37,5 @@ in
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts."s0.koi-bebop.ts.net" = {
|
||||
default = true;
|
||||
addSSL = true;
|
||||
serverAliases = [ "s0" ];
|
||||
sslCertificate = "/secret/ssl/s0.koi-bebop.ts.net.crt";
|
||||
sslCertificateKey = "/secret/ssl/s0.koi-bebop.ts.net.key";
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -22,5 +22,6 @@
|
||||
./dashy.nix
|
||||
./librechat.nix
|
||||
./actualbudget.nix
|
||||
./unifi.nix
|
||||
];
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ in
|
||||
HOST = "0.0.0.0";
|
||||
MONGO_URI = "mongodb://host.containers.internal:27017/LibreChat";
|
||||
ENDPOINTS = "openAI,google,bingAI,gptPlugins";
|
||||
REFRESH_TOKEN_EXPIRY = toString (1000 * 60 * 60 * 24 * 30); # 30 days
|
||||
};
|
||||
environmentFiles = [
|
||||
"/run/agenix/librechat-env-file"
|
||||
|
@ -4,6 +4,10 @@ let
|
||||
cfg = config.services.nginx;
|
||||
in
|
||||
{
|
||||
options.services.nginx = {
|
||||
openFirewall = lib.mkEnableOption "Open firewall ports 80 and 443";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.nginx = {
|
||||
recommendedGzipSettings = true;
|
||||
@ -12,6 +16,8 @@ in
|
||||
recommendedTlsSettings = true;
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
services.nginx.openFirewall = lib.mkDefault true;
|
||||
|
||||
networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ 80 443 ];
|
||||
};
|
||||
}
|
||||
|
25
common/server/unifi.nix
Normal file
25
common/server/unifi.nix
Normal file
@ -0,0 +1,25 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.unifi;
|
||||
in
|
||||
{
|
||||
options.services.unifi = {
|
||||
# Open select Unifi ports instead of using openFirewall to avoid opening access to unifi's control panel
|
||||
openMinimalFirewall = lib.mkEnableOption "Open bare minimum firewall ports";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.unifi.unifiPackage = pkgs.unifi8;
|
||||
|
||||
networking.firewall = lib.mkIf cfg.openMinimalFirewall {
|
||||
allowedUDPPorts = [
|
||||
3478 # STUN
|
||||
10001 # used for device discovery.
|
||||
];
|
||||
allowedTCPPorts = [
|
||||
8080 # Used for device and application communication.
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
@ -34,6 +34,8 @@
|
||||
io_seq_write = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=write --size=2g --io_size=10g --blocksize=1024k --ioengine=libaio --fsync=10000 --iodepth=32 --direct=1 --numjobs=1 --runtime=60 --group_reporting; rm temp.file";
|
||||
io_rand_read = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=randread --size=2g --io_size=10g --blocksize=4k --ioengine=libaio --fsync=1 --iodepth=1 --direct=1 --numjobs=32 --runtime=60 --group_reporting; rm temp.file";
|
||||
io_rand_write = "${pkgs.fio}/bin/fio --name TEST --eta-newline=5s --filename=temp.file --rw=randrw --size=2g --io_size=10g --blocksize=4k --ioengine=libaio --fsync=1 --iodepth=1 --direct=1 --numjobs=1 --runtime=60 --group_reporting; rm temp.file";
|
||||
|
||||
llsblk = "lsblk -o +uuid,fsType";
|
||||
};
|
||||
|
||||
nixpkgs.overlays = [
|
||||
|
92
flake.lock
generated
92
flake.lock
generated
@ -7,7 +7,9 @@
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": "systems"
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716561646,
|
||||
@ -55,11 +57,11 @@
|
||||
"rev": "1290ddd9a2ff2bf2d0f702750768312b80efcd34",
|
||||
"revCount": 19,
|
||||
"type": "git",
|
||||
"url": "https://git.neet.dev/zuckerberg/dailybuild_modules.git"
|
||||
"url": "https://git.neet.dev/zuckerberg/dailybot.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.neet.dev/zuckerberg/dailybuild_modules.git"
|
||||
"url": "https://git.neet.dev/zuckerberg/dailybot.git"
|
||||
}
|
||||
},
|
||||
"darwin": {
|
||||
@ -86,21 +88,22 @@
|
||||
},
|
||||
"deploy-rs": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-compat": [
|
||||
"flake-compat"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"utils": [
|
||||
"simple-nixos-mailserver",
|
||||
"utils"
|
||||
"flake-utils"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715699772,
|
||||
"narHash": "sha256-sKhqIgucN5sI/7UQgBwsonzR4fONjfMr9OcHK/vPits=",
|
||||
"lastModified": 1718194053,
|
||||
"narHash": "sha256-FaGrf7qwZ99ehPJCAwgvNY5sLCqQ3GDiE/6uLhxxwSY=",
|
||||
"owner": "serokell",
|
||||
"repo": "deploy-rs",
|
||||
"rev": "b3ea6f333f9057b77efd9091119ba67089399ced",
|
||||
"rev": "3867348fa92bc892eba5d9ddb2d7a97b9e127a8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -125,25 +128,11 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
@ -294,6 +283,7 @@
|
||||
"agenix": "agenix",
|
||||
"dailybuild_modules": "dailybuild_modules",
|
||||
"deploy-rs": "deploy-rs",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"nix-index-database": "nix-index-database",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
@ -301,24 +291,32 @@
|
||||
"nixpkgs-frigate": "nixpkgs-frigate",
|
||||
"radio": "radio",
|
||||
"radio-web": "radio-web",
|
||||
"simple-nixos-mailserver": "simple-nixos-mailserver"
|
||||
"simple-nixos-mailserver": "simple-nixos-mailserver",
|
||||
"systems": "systems"
|
||||
}
|
||||
},
|
||||
"simple-nixos-mailserver": {
|
||||
"inputs": {
|
||||
"blobs": "blobs",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"flake-compat": [
|
||||
"flake-compat"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"utils": "utils"
|
||||
"nixpkgs-24_05": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"utils": [
|
||||
"flake-utils"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1714720456,
|
||||
"narHash": "sha256-e0WFe1BHqX23ADpGBc4ZRu38Mg+GICCZCqyS6EWCbHc=",
|
||||
"lastModified": 1718084203,
|
||||
"narHash": "sha256-Cx1xoVfSMv1XDLgKg08CUd1EoTYWB45VmB9XIQzhmzI=",
|
||||
"owner": "simple-nixos-mailserver",
|
||||
"repo": "nixos-mailserver",
|
||||
"rev": "41059fc548088e49e3ddb3a2b4faeb5de018e60f",
|
||||
"rev": "29916981e7b3b5782dc5085ad18490113f8ff63b",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
@ -342,36 +340,6 @@
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"locked": {
|
||||
"lastModified": 1605370193,
|
||||
"narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "5021eac20303a61fafe17224c087f5519baed54d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
88
flake.nix
88
flake.nix
@ -1,40 +1,80 @@
|
||||
{
|
||||
inputs = {
|
||||
# nixpkgs
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||
nixpkgs-frigate.url = "github:NixOS/nixpkgs/5cfafa12d57374f48bcc36fda3274ada276cf69e";
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
# Common Utils Among flake inputs
|
||||
systems.url = "github:nix-systems/default";
|
||||
flake-utils = {
|
||||
url = "github:numtide/flake-utils";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
flake-compat = {
|
||||
url = "github:edolstra/flake-compat";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
# NixOS hardware
|
||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||
|
||||
# mail server
|
||||
simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/master";
|
||||
simple-nixos-mailserver.inputs.nixpkgs.follows = "nixpkgs";
|
||||
# Mail Server
|
||||
simple-nixos-mailserver = {
|
||||
url = "gitlab:simple-nixos-mailserver/nixos-mailserver/master";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
nixpkgs-24_05.follows = "nixpkgs";
|
||||
flake-compat.follows = "flake-compat";
|
||||
utils.follows = "flake-utils";
|
||||
};
|
||||
};
|
||||
|
||||
# agenix
|
||||
agenix.url = "github:ryantm/agenix";
|
||||
agenix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
# Agenix
|
||||
agenix = {
|
||||
url = "github:ryantm/agenix";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
systems.follows = "systems";
|
||||
};
|
||||
};
|
||||
|
||||
# radio
|
||||
radio.url = "git+https://git.neet.dev/zuckerberg/radio.git?ref=main&rev=5bf607fed977d41a269942a7d1e92f3e6d4f2473";
|
||||
radio.inputs.nixpkgs.follows = "nixpkgs";
|
||||
radio.inputs.flake-utils.follows = "flake-utils";
|
||||
radio-web.url = "git+https://git.neet.dev/zuckerberg/radio-web.git";
|
||||
radio-web.flake = false;
|
||||
# Radio
|
||||
radio = {
|
||||
url = "git+https://git.neet.dev/zuckerberg/radio.git?ref=main&rev=5bf607fed977d41a269942a7d1e92f3e6d4f2473";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
flake-utils.follows = "flake-utils";
|
||||
};
|
||||
};
|
||||
radio-web = {
|
||||
url = "git+https://git.neet.dev/zuckerberg/radio-web.git";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
# drastikbot
|
||||
dailybuild_modules.url = "git+https://git.neet.dev/zuckerberg/dailybuild_modules.git";
|
||||
dailybuild_modules.inputs.nixpkgs.follows = "nixpkgs";
|
||||
dailybuild_modules.inputs.flake-utils.follows = "flake-utils";
|
||||
# Dailybot
|
||||
dailybuild_modules = {
|
||||
url = "git+https://git.neet.dev/zuckerberg/dailybot.git";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
flake-utils.follows = "flake-utils";
|
||||
};
|
||||
};
|
||||
|
||||
# nixos config deployment
|
||||
deploy-rs.url = "github:serokell/deploy-rs";
|
||||
deploy-rs.inputs.nixpkgs.follows = "nixpkgs";
|
||||
deploy-rs.inputs.utils.follows = "simple-nixos-mailserver/utils";
|
||||
# NixOS deployment
|
||||
deploy-rs = {
|
||||
url = "github:serokell/deploy-rs";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
flake-compat.follows = "flake-compat";
|
||||
utils.follows = "flake-utils";
|
||||
};
|
||||
};
|
||||
|
||||
# prebuilt nix-index database
|
||||
nix-index-database.url = "github:Mic92/nix-index-database";
|
||||
nix-index-database.inputs.nixpkgs.follows = "nixpkgs";
|
||||
# Prebuilt nix-index database
|
||||
nix-index-database = {
|
||||
url = "github:Mic92/nix-index-database";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, ... }@inputs:
|
||||
|
@ -118,14 +118,6 @@
|
||||
|
||||
# proxied web services
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts."jellyfin.neet.cloud" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://s0.koi-bebop.ts.net";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
services.nginx.virtualHosts."navidrome.neet.cloud" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
@ -60,73 +60,65 @@ sections:
|
||||
- &ref_0
|
||||
title: Jellyfin
|
||||
icon: hl-jellyfin
|
||||
url: http://s0:8097
|
||||
url: https://jellyfin.s0.neet.dev
|
||||
target: sametab
|
||||
statusCheck: true
|
||||
statusCheckUrl: http://jellyfin.s0
|
||||
statusCheck: false
|
||||
id: 0_1956_jellyfin
|
||||
- &ref_1
|
||||
title: Sonarr
|
||||
description: Manage TV
|
||||
icon: hl-sonarr
|
||||
url: http://s0:8989
|
||||
url: https://sonarr.s0.neet.dev
|
||||
target: sametab
|
||||
statusCheck: true
|
||||
statusCheckUrl: http://sonarr.s0
|
||||
statusCheck: false
|
||||
id: 1_1956_sonarr
|
||||
- &ref_2
|
||||
title: Radarr
|
||||
description: Manage Movies
|
||||
icon: hl-radarr
|
||||
url: http://s0:7878
|
||||
url: https://radarr.s0.neet.dev
|
||||
target: sametab
|
||||
statusCheck: true
|
||||
statusCheckUrl: http://radarr.s0
|
||||
statusCheck: false
|
||||
id: 2_1956_radarr
|
||||
- &ref_3
|
||||
title: Lidarr
|
||||
description: Manage Music
|
||||
icon: hl-lidarr
|
||||
url: http://s0:8686
|
||||
url: https://lidarr.s0.neet.dev
|
||||
target: sametab
|
||||
statusCheck: true
|
||||
statusCheckUrl: http://lidarr.s0
|
||||
statusCheck: false
|
||||
id: 3_1956_lidarr
|
||||
- &ref_4
|
||||
title: Prowlarr
|
||||
description: Indexers
|
||||
icon: hl-prowlarr
|
||||
url: http://prowlarr.s0
|
||||
url: https://prowlarr.s0.neet.dev
|
||||
target: sametab
|
||||
statusCheck: true
|
||||
statusCheckUrl: http://prowlarr.s0
|
||||
statusCheck: false
|
||||
id: 4_1956_prowlarr
|
||||
- &ref_5
|
||||
title: Bazarr
|
||||
description: Subtitles
|
||||
icon: hl-bazarr
|
||||
url: http://s0:6767
|
||||
url: https://bazarr.s0.neet.dev
|
||||
target: sametab
|
||||
statusCheck: true
|
||||
statusCheckUrl: http://bazarr.s0
|
||||
statusCheck: false
|
||||
id: 5_1956_bazarr
|
||||
- &ref_6
|
||||
title: Navidrome
|
||||
description: Play Music
|
||||
icon: hl-navidrome
|
||||
url: http://s0:4534
|
||||
url: https://music.s0.neet.dev
|
||||
target: sametab
|
||||
statusCheck: true
|
||||
statusCheckUrl: http://music.s0
|
||||
statusCheck: false
|
||||
id: 6_1956_navidrome
|
||||
- &ref_7
|
||||
title: Transmission
|
||||
description: Torrenting
|
||||
icon: hl-transmission
|
||||
url: http://s0:9091
|
||||
url: https://transmission.s0.neet.dev
|
||||
target: sametab
|
||||
statusCheck: true
|
||||
statusCheckUrl: http://transmission.s0
|
||||
statusCheck: false
|
||||
id: 7_1956_transmission
|
||||
filteredItems:
|
||||
- *ref_0
|
||||
|
@ -165,61 +165,96 @@
|
||||
};
|
||||
|
||||
# nginx
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts."bazarr.s0" = {
|
||||
listen = [{ addr = "0.0.0.0"; port = 6767; } { addr = "0.0.0.0"; port = 80; }];
|
||||
locations."/".proxyPass = "http://vpn.containers:6767";
|
||||
};
|
||||
services.nginx.virtualHosts."radarr.s0" = {
|
||||
listen = [{ addr = "0.0.0.0"; port = 7878; } { addr = "0.0.0.0"; port = 80; }];
|
||||
locations."/".proxyPass = "http://vpn.containers:7878";
|
||||
};
|
||||
services.nginx.virtualHosts."lidarr.s0" = {
|
||||
listen = [{ addr = "0.0.0.0"; port = 8686; } { addr = "0.0.0.0"; port = 80; }];
|
||||
locations."/".proxyPass = "http://vpn.containers:8686";
|
||||
};
|
||||
services.nginx.virtualHosts."sonarr.s0" = {
|
||||
listen = [{ addr = "0.0.0.0"; port = 8989; } { addr = "0.0.0.0"; port = 80; }];
|
||||
locations."/".proxyPass = "http://vpn.containers:8989";
|
||||
};
|
||||
services.nginx.virtualHosts."prowlarr.s0" = {
|
||||
listen = [{ addr = "0.0.0.0"; port = 9696; } { addr = "0.0.0.0"; port = 80; }];
|
||||
locations."/".proxyPass = "http://vpn.containers:9696";
|
||||
};
|
||||
services.nginx.virtualHosts."music.s0" = {
|
||||
listen = [{ addr = "0.0.0.0"; port = 4534; } { addr = "0.0.0.0"; port = 80; }];
|
||||
locations."/".proxyPass = "http://localhost:4533";
|
||||
};
|
||||
services.nginx.virtualHosts."jellyfin.s0" = {
|
||||
listen = [{ addr = "0.0.0.0"; port = 8097; } { addr = "0.0.0.0"; port = 80; }];
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:8096";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
services.nginx.virtualHosts."jellyfin.neet.cloud".locations."/" = {
|
||||
proxyPass = "http://localhost:8096";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
services.nginx.virtualHosts."transmission.s0" = {
|
||||
listen = [{ addr = "0.0.0.0"; port = 9091; } { addr = "0.0.0.0"; port = 80; }];
|
||||
locations."/" = {
|
||||
proxyPass = "http://vpn.containers:9091";
|
||||
proxyWebsockets = true;
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
openFirewall = false; # All nginx services are internal
|
||||
virtualHosts =
|
||||
let
|
||||
mkVirtualHost = external: internal:
|
||||
{
|
||||
${external} = {
|
||||
useACMEHost = "s0.neet.dev"; # Use wildcard cert
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = internal;
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
lib.mkMerge [
|
||||
(mkVirtualHost "bazarr.s0.neet.dev" "http://vpn.containers:6767")
|
||||
(mkVirtualHost "radarr.s0.neet.dev" "http://vpn.containers:7878")
|
||||
(mkVirtualHost "lidarr.s0.neet.dev" "http://vpn.containers:8686")
|
||||
(mkVirtualHost "sonarr.s0.neet.dev" "http://vpn.containers:8989")
|
||||
(mkVirtualHost "prowlarr.s0.neet.dev" "http://vpn.containers:9696")
|
||||
(mkVirtualHost "transmission.s0.neet.dev" "http://vpn.containers:9091")
|
||||
(mkVirtualHost "unifi.s0.neet.dev" "https://localhost:8443")
|
||||
(mkVirtualHost "music.s0.neet.dev" "http://localhost:4533")
|
||||
(mkVirtualHost "jellyfin.s0.neet.dev" "http://localhost:8096")
|
||||
(mkVirtualHost "s0.neet.dev" "http://localhost:56815")
|
||||
(mkVirtualHost "ha.s0.neet.dev" "http://localhost:8123") # home assistant
|
||||
(mkVirtualHost "esphome.s0.neet.dev" "http://localhost:6052")
|
||||
(mkVirtualHost "zigbee.s0.neet.dev" "http://localhost:55834")
|
||||
{
|
||||
# Landing page LAN redirect
|
||||
"s0" = {
|
||||
default = true;
|
||||
redirectCode = 302;
|
||||
globalRedirect = "s0.neet.dev";
|
||||
};
|
||||
"frigate.s0.neet.dev" = {
|
||||
# Just configure SSL, frigate module configures the rest of nginx
|
||||
useACMEHost = "s0.neet.dev";
|
||||
forceSSL = true;
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# Problem #1: Keeping certain programs from being accessed from certain external networks/VLANs
|
||||
# Solution #1: Isolate that service in a container system that automatically fowards the ports to the right network interface(s)
|
||||
# Solution #2: Don't open the firewall for these services, manually open the ports instead for the specific network interface(s) (trickier and easy to miss ports or ports can change)
|
||||
# Untrusted network list:
|
||||
# - VLANs [cameras]
|
||||
|
||||
# Problem #2: Untrusted internal services. Prevent them from accessing certain internal services (usually key unauth'd services like frigate)
|
||||
# Solution #1: Isolate the untrusted services into their own container
|
||||
# Untrusted services list:
|
||||
# - Unifi? (it already has access to the cameras anyway?)
|
||||
# - torrenting, *arr (worried about vulns)
|
||||
|
||||
|
||||
tailscaleAuth = {
|
||||
enable = true;
|
||||
virtualHosts = [
|
||||
"bazarr.s0.neet.dev"
|
||||
"radarr.s0.neet.dev"
|
||||
"lidarr.s0.neet.dev"
|
||||
"sonarr.s0.neet.dev"
|
||||
"prowlarr.s0.neet.dev"
|
||||
"transmission.s0.neet.dev"
|
||||
"unifi.s0.neet.dev"
|
||||
# "music.s0.neet.dev" # messes up navidrome
|
||||
"jellyfin.s0.neet.dev"
|
||||
"s0.neet.dev"
|
||||
# "ha.s0.neet.dev" # messes up home assistant
|
||||
"esphome.s0.neet.dev"
|
||||
"zigbee.s0.neet.dev"
|
||||
];
|
||||
expectedTailnet = "koi-bebop.ts.net";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
6767
|
||||
7878
|
||||
8686
|
||||
8989
|
||||
9696
|
||||
4534
|
||||
8097
|
||||
9091
|
||||
8443 # unifi
|
||||
];
|
||||
# Get wildcard cert
|
||||
security.acme.certs."s0.neet.dev" = {
|
||||
dnsProvider = "digitalocean";
|
||||
credentialsFile = "/run/agenix/digitalocean-dns-credentials";
|
||||
extraDomainNames = [ "*.s0.neet.dev" ];
|
||||
group = "nginx";
|
||||
dnsResolver = "1.1.1.1:53";
|
||||
dnsPropagationCheck = false; # sadly this erroneously fails
|
||||
};
|
||||
age.secrets.digitalocean-dns-credentials.file = ../../../secrets/digitalocean-dns-credentials.age;
|
||||
|
||||
virtualisation.oci-containers.backend = "podman";
|
||||
virtualisation.podman.dockerSocket.enable = true; # TODO needed?
|
||||
@ -230,8 +265,7 @@
|
||||
|
||||
services.unifi = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
unifiPackage = pkgs.unifi8;
|
||||
openMinimalFirewall = true;
|
||||
};
|
||||
|
||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
|
||||
|
@ -1,8 +1,7 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
frigateHostname = "frigate.s0";
|
||||
frigatePort = 61617;
|
||||
frigateHostname = "frigate.s0.neet.dev";
|
||||
|
||||
mkEsp32Cam = address: {
|
||||
ffmpeg = {
|
||||
@ -41,9 +40,6 @@ in
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
# 1883 # mqtt
|
||||
55834 # mqtt zigbee frontend
|
||||
frigatePort
|
||||
4180 # oauth proxy
|
||||
];
|
||||
|
||||
services.frigate = {
|
||||
@ -80,21 +76,7 @@ in
|
||||
# Coral PCIe driver
|
||||
kernel.enableGasketKernelModule = true;
|
||||
|
||||
# Allow accessing frigate UI on a specific port in addition to by hostname
|
||||
services.nginx.virtualHosts.${frigateHostname} = {
|
||||
listen = [{ addr = "0.0.0.0"; port = frigatePort; } { addr = "0.0.0.0"; port = 80; }];
|
||||
};
|
||||
|
||||
services.esphome = {
|
||||
enable = true;
|
||||
address = "0.0.0.0";
|
||||
openFirewall = true;
|
||||
};
|
||||
# TODO remove after upgrading nixos version
|
||||
systemd.services.esphome.serviceConfig.ProcSubset = lib.mkForce "all";
|
||||
systemd.services.esphome.serviceConfig.ProtectHostname = lib.mkForce false;
|
||||
systemd.services.esphome.serviceConfig.ProtectKernelLogs = lib.mkForce false;
|
||||
systemd.services.esphome.serviceConfig.ProtectKernelTunables = lib.mkForce false;
|
||||
services.esphome.enable = true;
|
||||
|
||||
# TODO lock down
|
||||
services.mosquitto = {
|
||||
@ -121,7 +103,7 @@ in
|
||||
# base_topic = "zigbee2mqtt";
|
||||
};
|
||||
frontend = {
|
||||
host = "0.0.0.0";
|
||||
host = "localhost";
|
||||
port = 55834;
|
||||
};
|
||||
};
|
||||
@ -129,60 +111,52 @@ in
|
||||
|
||||
services.home-assistant = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
configWritable = true;
|
||||
extraComponents = [
|
||||
"default_config"
|
||||
"esphome"
|
||||
"met"
|
||||
"radio_browser"
|
||||
"wled"
|
||||
"mqtt"
|
||||
"apple_tv" # why is this even needed? I get `ModuleNotFoundError: No module named 'pyatv'` errors otherwise for some reason.
|
||||
"unifi"
|
||||
"digital_ocean"
|
||||
"downloader"
|
||||
"mailgun"
|
||||
"minecraft_server"
|
||||
"mullvad"
|
||||
"nextcloud"
|
||||
"ollama"
|
||||
"openweathermap"
|
||||
"jellyfin"
|
||||
"transmission"
|
||||
"radarr"
|
||||
"sonarr"
|
||||
"syncthing"
|
||||
"tailscale"
|
||||
"weather"
|
||||
"whois"
|
||||
"youtube"
|
||||
];
|
||||
# config = null;
|
||||
config = {
|
||||
# Includes dependencies for a basic setup
|
||||
# https://www.home-assistant.io/integrations/default_config/
|
||||
default_config = { };
|
||||
|
||||
# Enable reverse proxy support
|
||||
http = {
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
};
|
||||
|
||||
"automation manual" = [
|
||||
];
|
||||
# Allow using automations generated from the UI
|
||||
"automation ui" = "!include automations.yaml";
|
||||
};
|
||||
};
|
||||
|
||||
# TODO need services.oauth2-proxy.cookie.domain ?
|
||||
services.oauth2-proxy =
|
||||
let
|
||||
nextcloudServer = "https://neet.cloud/";
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
|
||||
httpAddress = "http://0.0.0.0:4180";
|
||||
|
||||
nginx.domain = frigateHostname;
|
||||
# nginx.virtualHosts = [
|
||||
# frigateHostname
|
||||
# ];
|
||||
|
||||
email.domains = [ "*" ];
|
||||
|
||||
cookie.secure = false;
|
||||
|
||||
provider = "nextcloud";
|
||||
|
||||
# redirectURL = "http://s0:4180/oauth2/callback"; # todo forward with nginx?
|
||||
clientID = "4FfhEB2DNzUh6wWhXTjqQQKu3Ibm6TeYpS8TqcHe55PJC1DorE7vBZBELMKDjJ0X";
|
||||
keyFile = "/run/agenix/oauth2-proxy-env";
|
||||
|
||||
loginURL = "${nextcloudServer}/index.php/apps/oauth2/authorize";
|
||||
redeemURL = "${nextcloudServer}/index.php/apps/oauth2/api/v1/token";
|
||||
validateURL = "${nextcloudServer}/ocs/v2.php/cloud/user?format=json";
|
||||
|
||||
# todo --cookie-refresh
|
||||
|
||||
extraConfig = {
|
||||
# cookie-csrf-per-request = true;
|
||||
# cookie-csrf-expire = "5m";
|
||||
# user-id-claim = "preferred_username";
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets.oauth2-proxy-env.file = ../../../secrets/oauth2-proxy-env.age;
|
||||
}
|
||||
|
@ -42,25 +42,25 @@
|
||||
];
|
||||
|
||||
# System wide barrier instance
|
||||
systemd.services.barrier-sddm = {
|
||||
description = "Barrier mouse/keyboard share";
|
||||
requires = [ "display-manager.service" ];
|
||||
after = [ "network.target" "display-manager.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Restart = "always";
|
||||
RestartSec = 10;
|
||||
# todo use user/group
|
||||
};
|
||||
path = with pkgs; [ barrier doas ];
|
||||
script = ''
|
||||
# Wait for file to show up. "display-manager.service" finishes a bit too soon
|
||||
while ! [ -e /run/sddm/* ]; do sleep 1; done;
|
||||
export XAUTHORITY=$(ls /run/sddm/*)
|
||||
# Disable crypto is fine because tailscale is E2E encrypting better than barrier could anyway
|
||||
barrierc -f --disable-crypto --name zoidberg ray.koi-bebop.ts.net
|
||||
'';
|
||||
};
|
||||
# systemd.services.barrier-sddm = {
|
||||
# description = "Barrier mouse/keyboard share";
|
||||
# requires = [ "display-manager.service" ];
|
||||
# after = [ "network.target" "display-manager.service" ];
|
||||
# wantedBy = [ "multi-user.target" ];
|
||||
# serviceConfig = {
|
||||
# Restart = "always";
|
||||
# RestartSec = 10;
|
||||
# # todo use user/group
|
||||
# };
|
||||
# path = with pkgs; [ barrier doas ];
|
||||
# script = ''
|
||||
# # Wait for file to show up. "display-manager.service" finishes a bit too soon
|
||||
# while ! [ -e /run/sddm/* ]; do sleep 1; done;
|
||||
# export XAUTHORITY=$(ls /run/sddm/*)
|
||||
# # Disable crypto is fine because tailscale is E2E encrypting better than barrier could anyway
|
||||
# barrierc -f --disable-crypto --name zoidberg ray.koi-bebop.ts.net
|
||||
# '';
|
||||
# };
|
||||
|
||||
# Login into X11 plasma so barrier works well
|
||||
services.displayManager.defaultSession = "plasma";
|
||||
|
@ -7,7 +7,7 @@
|
||||
];
|
||||
|
||||
# boot
|
||||
efi.enable = true;
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.timeout = lib.mkForce 15;
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "usbhid" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
@ -35,7 +35,7 @@
|
||||
};
|
||||
fileSystems."/boot" =
|
||||
{
|
||||
device = "/dev/disk/by-uuid/8074-B04D";
|
||||
device = "/dev/disk/by-uuid/954B-AB3E";
|
||||
fsType = "vfat";
|
||||
};
|
||||
swapDevices =
|
||||
|
11
secrets/digitalocean-dns-credentials.age
Normal file
11
secrets/digitalocean-dns-credentials.age
Normal file
@ -0,0 +1,11 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 WBT1Hw wjZGPvilRXGZsC2+7dWm/Nbau8Allv29WwQCr0XSAWU
|
||||
uTOf/sokutOGDyc8fbTbBWXqCVQCFhGdHxwA6SXqhdA
|
||||
-> ssh-ed25519 6AT2/g NU068qwqOWiKk0QwqP9vU4xJaND2OR4bo8xkmdWATgY
|
||||
uGd0sb5PH+rREn9pgLOFwk29CX66aPBQMvr4rBazylc
|
||||
-> ssh-ed25519 hPp1nw r2JRiZ7fsHPYDlte6Oh2Gx1KkugekFeeg3xSjziI+hQ
|
||||
xnO0gscMdR25mj5uAX7D42FCbCQhqbU0wkiLX4OmVqk
|
||||
-> ssh-ed25519 w3nu8g F03mPU63WwEs1SLUFErLOVCkARoggGIvvz9TFZfMOBY
|
||||
HOdVA3xW9pqUPhclO6VueSfXg3ux06Ch3fucF6Vr4hM
|
||||
--- niyo231HPT/+2dzflP+zhYjL9XiWsk7svesCYdkU1jA
|
||||
DÑØQî¬5–-ô@<40>¢¿—ßÐN5<4E> Ãÿ$Ø‚™’Çž…êÐ<C3AA>X=ŒHŽDÁ`P×5ZA´÷¼YóäÓ?¡é^[³1”6ÕK*mP݈ªæ1æç÷ß›ƒ:$^ÑfDœ*î†ÿ“š-zi´"·Tàuÿüò
|
@ -51,4 +51,7 @@ with roles;
|
||||
|
||||
# Librechat
|
||||
"librechat-env-file.age".publicKeys = librechat;
|
||||
|
||||
# For ACME DNS Challenge
|
||||
"digitalocean-dns-credentials.age".publicKeys = server;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user