This commit is contained in:
rasmus-kirk
2024-02-20 15:38:34 +01:00
parent d0a87c984a
commit f5b6c56797
15 changed files with 674 additions and 432 deletions
Generated
+192
View File
@@ -0,0 +1,192 @@
{
"nodes": {
"devshell": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1705332421,
"narHash": "sha256-USpGLPme1IuqG78JNqSaRabilwkCyHmVWY0M9vYyqEA=",
"owner": "numtide",
"repo": "devshell",
"rev": "83cb93d6d063ad290beee669f4badf9914cc16ec",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1706830856,
"narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-root": {
"locked": {
"lastModified": 1692742795,
"narHash": "sha256-f+Y0YhVCIJ06LemO+3Xx00lIcqQxSKJHXT/yk1RTKxw=",
"owner": "srid",
"repo": "flake-root",
"rev": "d9a70d9c7a5fd7f3258ccf48da9335e9b47c3937",
"type": "github"
},
"original": {
"owner": "srid",
"repo": "flake-root",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1708294481,
"narHash": "sha256-DZtxmeb4OR7iCaKUUuq05ADV2rX8WReZEF7Tq//W0+Y=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "a54e05bc12d88ff2df941d0dc1183cb5235fa438",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1708118438,
"narHash": "sha256-kk9/0nuVgA220FcqH/D2xaN6uGyHp/zoxPNUmPCMmEE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5863c27340ba4de8f83e7e3c023b9599c3cb3c80",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-flood": {
"locked": {
"lastModified": 1701810456,
"narHash": "sha256-jOl3DMrDgJYZeE/w5p7zQe+Ift7R307mXG/tyhH8WHE=",
"owner": "3JlOy-PYCCKUi",
"repo": "nixpkgs",
"rev": "aff5b3aa1a95876fd426ab024d68ab2d87b0ebbd",
"type": "github"
},
"original": {
"owner": "3JlOy-PYCCKUi",
"ref": "flood-module",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1708407374,
"narHash": "sha256-EECzarm+uqnNDCwaGg/ppXCO11qibZ1iigORShkkDf0=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "f33dd27a47ebdf11dc8a5eb05e7c8fbdaf89e73f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"devshell": "devshell",
"flake-parts": "flake-parts",
"flake-root": "flake-root",
"home-manager": "home-manager",
"nixpkgs": "nixpkgs_2",
"nixpkgs-flood": "nixpkgs-flood",
"treefmt-nix": "treefmt-nix"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1708335038,
"narHash": "sha256-ETLZNFBVCabo7lJrpjD6cAbnE11eDOjaQnznmg/6hAE=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "e504621290a1fd896631ddbc5e9c16f4366c9f65",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}
+5 -25
View File
@@ -1,5 +1,5 @@
{
description = "Kirk nix modules";
description = "The servarr.enable nixos module";
nixConfig = {
extra-substituters = ["https://nix-community.cachix.org"];
@@ -46,12 +46,8 @@
flake = {
nixosModules = rec {
kirk = import ./nixos;
default = kirk;
};
homeManagerModules = rec {
kirk = import ./home-manager;
default = kirk;
servarr = import ./servarr;
default = servarr;
};
};
@@ -71,8 +67,8 @@
};
packages = {
docs = pkgs.callPackage ./mkDocs.nix { inherit inputs; };
hugo = pkgs.callPackage ./mkHugo.nix { inherit inputs; };
docs = pkgs.callPackage ./mkDocs.nix {inherit inputs;};
hugo = pkgs.callPackage ./mkHugo.nix {inherit inputs;};
};
devshells.default = {
@@ -89,20 +85,4 @@
};
};
};
# outputs = {
# self,
# }: {
# nixosModules.kirk = import ./nixos;
# nixosModules.default = self.nixosModules.kirk;
#
# homeManagerModules.kirk = import ./home-manager;
# homeManagerModules.default = self.homeManagerModules.kirk;
#
# # TODO: Find a way to generate documentation from modules using the same
# # tools as nixos. See ./mkDocs.nix
#
# #packages.x86_64-linux.mkdocs = {};
# #defaultPackage.x86_64-linux = self.packages.x86_64-linux.report;
# };
}
-1
View File
@@ -55,7 +55,6 @@
optionsDocNixos = nixosOptionsDoc {
inherit (evalNixos) options;
};
in
# create a derivation for capturing the markdown output
runCommand "options-doc.md" {} ''
+4 -5
View File
@@ -1,12 +1,11 @@
{ pkgs, ... }:
pkgs.writeShellApplication {
{pkgs, ...}:
pkgs.writeShellApplication {
name = "my-script";
runtimeInputs = with pkgs; [ hugo ];
runtimeInputs = with pkgs; [hugo];
text = ''
cat hugo/content/header.md result/home.md | sed "s/DATE-TIMESTAMP/$(date -u +%Y-%m-%d)/g" > hugo/content/home-manager/index.md
cat hugo/content/header.md result/nixos.md | sed "s/DATE-TIMESTAMP/$(date -u +%Y-%m-%d)/g" > hugo/content/nixos/index.md
cd hugo
hugo
'';
}
}
+4 -3
View File
@@ -14,6 +14,7 @@ in {
./sonarr
./prowlarr
./transmission
../util
];
options.kirk.servarr = {
@@ -71,7 +72,7 @@ in {
Extra DNS servers for the VPN. If your wg config has a DNS field,
then this should not be necessary.
'';
example = [ "1.1.1.2" ];
example = ["1.1.1.2"];
};
vpnTestService = {
@@ -95,7 +96,7 @@ in {
if you're port forwarding on your VPN provider and you're setting
up services that is not covered in by this module.
'';
example = [ 46382 38473 ];
example = [46382 38473];
};
openUdpPorts = mkOption {
@@ -106,7 +107,7 @@ in {
if you're port forwarding on your VPN provider and you're setting
up services that is not covered in by this module.
'';
example = [ 46382 38473 ];
example = [46382 38473];
};
};
};
+10 -5
View File
@@ -51,10 +51,13 @@ in {
{
services.jellyfin.enable = cfg.enable;
networking.firewall.allowedTCPPorts = if cfg.nginx.enable then [
networking.firewall.allowedTCPPorts =
if cfg.nginx.enable
then [
80 # http
443 # https
] else [];
]
else [];
services.nginx = mkIf (cfg.nginx.enable || cfg.useVpn) {
enable = true;
@@ -93,17 +96,19 @@ in {
defaults.email = cfg.nginx.acmeMail;
};
kirk.vpnnamespace.portMappings = [(
kirk.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)];
)
];
containers.jellyfin = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = [ "--network-namespace-path=/var/run/netns/wg" ];
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${servarr.mediaDir}/library".isReadOnly = false;
+6 -4
View File
@@ -35,17 +35,19 @@ in {
dataDir = cfg.stateDir;
};
kirk.vpnnamespace.portMappings = [(
kirk.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)];
)
];
containers.lidarr= mkIf cfg.useVpn {
containers.lidarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = [ "--network-namespace-path=/var/run/netns/wg" ];
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${servarr.mediaDir}".isReadOnly = false;
+5 -3
View File
@@ -39,17 +39,19 @@ in {
openFirewall = true;
};
kirk.vpnnamespace.portMappings = [(
kirk.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)];
)
];
containers.prowlarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = [ "--network-namespace-path=/var/run/netns/wg" ];
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"/var/lib/prowlarr" = {
+6 -5
View File
@@ -39,17 +39,19 @@ in {
dataDir = cfg.stateDir;
};
kirk.vpnnamespace.portMappings = [(
kirk.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)];
)
];
containers.radarr= mkIf cfg.useVpn {
containers.radarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = [ "--network-namespace-path=/var/run/netns/wg" ];
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${servarr.mediaDir}".isReadOnly = false;
@@ -103,6 +105,5 @@ in {
};
};
};
};
}
+5 -4
View File
@@ -35,17 +35,19 @@ in {
dataDir = cfg.stateDir;
};
kirk.vpnnamespace.portMappings = [(
kirk.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)];
)
];
containers.readarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = [ "--network-namespace-path=/var/run/netns/wg" ];
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${servarr.mediaDir}".isReadOnly = false;
@@ -99,6 +101,5 @@ in {
};
};
};
};
}
+1 -2
View File
@@ -1,6 +1,5 @@
# TODO: Dir creation and file permissions in nix
{
pkgs,
config,
lib,
...
@@ -49,7 +48,7 @@ in {
containers.sonarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = [ "--network-namespace-path=/var/run/netns/wg" ];
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${servarr.mediaDir}".isReadOnly = false;
+23 -11
View File
@@ -67,11 +67,15 @@ in {
enable = true;
group = "media";
#home = cfg.stateDir;
webHome = if cfg.useFlood then pkgs.flood-for-transmission else null;
webHome =
if cfg.useFlood
then pkgs.flood-for-transmission
else null;
package = pkgs.transmission_4;
openRPCPort = true;
openPeerPorts = true;
settings = {
settings =
{
download-dir = "${servarr.mediaDir}/torrents";
incomplete-dir-enabled = true;
incomplete-dir = "${servarr.mediaDir}/torrents/.incomplete";
@@ -92,22 +96,25 @@ in {
anti-brute-force-enabled = true;
anti-brute-force-threshold = 10;
} // cfg.extraConfig;
}
// cfg.extraConfig;
};
kirk.vpnnamespace = mkIf cfg.useVpn {
portMappings = [{
portMappings = [
{
From = cfg.uiPort;
To = cfg.uiPort;
}];
openUdpPorts = [ cfg.peerPort ];
openTcpPorts = [ cfg.peerPort ];
}
];
openUdpPorts = [cfg.peerPort];
openTcpPorts = [cfg.peerPort];
};
containers.transmission = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = [ "--network-namespace-path=/var/run/netns/wg" ];
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${servarr.mediaDir}/torrents".isReadOnly = false;
@@ -142,11 +149,15 @@ in {
enable = true;
# This is maybe wrong, too afraid to fix it lol
group = "media";
webHome = if cfg.useFlood then pkgs.flood-for-transmission else null;
webHome =
if cfg.useFlood
then pkgs.flood-for-transmission
else null;
package = pkgs.transmission_4;
openRPCPort = true;
openPeerPorts = true;
settings = {
settings =
{
download-dir = "${servarr.mediaDir}/torrents";
incomplete-dir-enabled = true;
incomplete-dir = "${servarr.mediaDir}/torrents/.incomplete";
@@ -174,7 +185,8 @@ in {
# 0 = None, 1 = Critical, 2 = Error, 3 = Warn, 4 = Info, 5 = Debug, 6 = Trace
message-level = 3;
} // cfg.extraConfig;
}
// cfg.extraConfig;
};
environment.systemPackages = with pkgs; [
+19
View File
@@ -0,0 +1,19 @@
{
imports = [
./fonts
./foot
./fzf
./git
./gruvboxTheme
./helix
./homeManagerScripts
./jiten
./joshuto
./kakoune
./ssh
./terminalTools
./userDirs
./zathura
./zsh
];
}
+7 -6
View File
@@ -17,7 +17,7 @@ in {
description = lib.mdDoc ''
What TCP ports to open using UPNP.
'';
example = [ 46382 38473 ];
example = [46382 38473];
};
openUdpPorts = mkOption {
@@ -26,7 +26,7 @@ in {
description = lib.mdDoc ''
What UDP ports to open using UPNP.
'';
example = [ 46382 38473 ];
example = [46382 38473];
};
};
@@ -71,12 +71,13 @@ in {
runtimeInputs = with pkgs; [miniupnpc];
text = (
strings.concatMapStrings (x: "upnpc -r ${builtins.toString x} UDP" + "\n") cfg.openUpdPorts ++
strings.concatMapStrings (x: "upnpc -r ${builtins.toString x} TCP" + "\n") cfg.openTcpPorts ++
''echo "Successfully requested upnp ports to be opened".''
strings.concatMapStrings (x: "upnpc -r ${builtins.toString x} UDP" + "\n") cfg.openUpdPorts
++ strings.concatMapStrings (x: "upnpc -r ${builtins.toString x} TCP" + "\n") cfg.openTcpPorts
++ ''echo "Successfully requested upnp ports to be opened".''
);
};
in mkIf cfg.upnp.enable {
in
mkIf cfg.upnp.enable {
enable = true;
description = "Sets port on router";
script = "${upnp-ports}/bin/upnp-ports";
+92 -63
View File
@@ -1,15 +1,21 @@
{ lib, pkgs, config, ... }:
{
lib,
pkgs,
config,
...
}:
# Thanks to Maroka-chan...
# TODO: Make it so you can make multiple namespaces by giving a list of
# objects with settings as attributes. Also add an option to enable whether
# the namespace should use a vpn or not.
with builtins;
with lib;
let
with lib; let
cfg = config.kirk.vpnnamespace;
in {
options.kirk.vpnnamespace = {
enable = mkEnableOption (lib.mdDoc "VPN Namespace") // {
enable =
mkEnableOption (lib.mdDoc "VPN Namespace")
// {
description = lib.mdDoc ''
Whether to enable the VPN namespace.
@@ -33,7 +39,7 @@ in {
accessibleFrom = mkOption {
type = types.listOf types.str;
default = [ ];
default = [];
description = lib.mdDoc ''
Subnets or specific addresses that the namespace should be accessible to.
'';
@@ -94,10 +100,12 @@ in {
description = lib.mdDoc ''
A list of pairs mapping a port from the host to a port in the namespace.
'';
example = [{
example = [
{
From = 80;
To = 80;
}];
}
];
};
dnsServers = mkOption {
@@ -106,7 +114,7 @@ in {
description = lib.mdDoc ''
YOUR VPN WILL LEAK IF THIS IS NOT SET. The dns address of your vpn.
'';
example = [ "1.1.1.2" ];
example = ["1.1.1.2"];
};
openTcpPorts = mkOption {
@@ -116,7 +124,7 @@ in {
What TCP ports to allow incoming traffic from. You need this if
you're port forwarding on your VPN provider.
'';
example = [ 46382 38473 ];
example = [46382 38473];
};
openUdpPorts = mkOption {
@@ -126,7 +134,7 @@ in {
What UDP ports to allow incoming traffic from. You need this if
you're port forwarding on your VPN provider.
'';
example = [ 46382 38473 ];
example = [46382 38473];
};
vpnTestService = {
@@ -134,46 +142,55 @@ in {
port = mkOption {
type = types.port;
default = [ 12300 ];
default = [12300];
description = lib.mdDoc ''
The port that the vpn test service listens to.
'';
example = [ 58403 ];
example = [58403];
};
};
};
config =
let
headMay = list: if list == [] then null else head list;
config = let
headMay = list:
if list == []
then null
else head list;
# Checks if string is ipv4, from SO, hope it works well
# https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
isIpv4 = address:
let pat = "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])?/?[0-9]?[0-9]";
isIpv4 = address: let
pat = "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])?/?[0-9]?[0-9]";
regex = match pat address;
in regex != null;
in
regex != null;
# Checks if string is ipv6, from SO, hope it works well
# https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
isIpv6 = address:
let pat = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
isIpv6 = address: let
pat = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
regex = match pat address;
in regex != null;
in
regex != null;
isIp = ip: (isIpv4 ip || isIpv6 ip);
in
mkIf cfg.enable {
lib.vpn = {
dnsServers =
let lines = split "\n" (readFile cfg.wireguardConfigFile);
dnsServers = let
lines = split "\n" (readFile cfg.wireguardConfigFile);
dnsLine = headMay (filter (x: typeOf x == "string" && match ".*DNS.*" x != null) lines);
in if dnsLine == null then [] else let
in
if dnsLine == null
then []
else let
ipsUnsplit = head (match "DNS ?=(.*)" dnsLine);
in if ipsUnsplit == null then [] else let
in
if ipsUnsplit == null
then []
else let
ips = filter (x: typeOf x == "string") (split "," ipsUnsplit);
ipsNoSpaces = map (replaceStrings [" "] [""]) ips;
correctIps = filter isIp ipsNoSpaces;
in
assert ( correctIps != [] ) || abort "There must be at least 1 DNS server set.";
correctIps;
assert (correctIps != []) || abort "There must be at least 1 DNS server set."; correctIps;
};
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
@@ -181,7 +198,7 @@ in {
systemd.services = {
"netns@" = {
description = "%I network namespace";
before = [ "network.target" ];
before = ["network.target"];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
@@ -192,17 +209,23 @@ in {
wg = {
description = "wg network interface";
bindsTo = [ "netns@wg.service" ];
requires = [ "network-online.target" ];
after = [ "netns@wg.service" ];
wantedBy = [ "netns@wg.service" ];
bindsTo = ["netns@wg.service"];
requires = ["network-online.target"];
after = ["netns@wg.service"];
wantedBy = ["netns@wg.service"];
serviceConfig = let
lines = split "\n" (readFile cfg.wireguardConfigFile);
addrLine = headMay (filter (x: typeOf x == "string" && match ".*Address.*" x != null) lines);
in if addrLine == null then [] else let
in
if addrLine == null
then []
else let
ipsUnsplit = head (match "Address ?=(.*)" addrLine);
in if ipsUnsplit == null then [] else let
in
if ipsUnsplit == null
then []
else let
ips = filter (x: typeOf x == "string") (split "," ipsUnsplit);
ipsNoSpaces = map (replaceStrings [" "] [""]) ips;
wgIpv4Address = headMay (filter isIpv4 ipsNoSpaces);
@@ -210,9 +233,10 @@ in {
vpn-namespace = pkgs.writeShellApplication {
name = "vpn-namespace";
runtimeInputs = with pkgs; [ iproute2 wireguard-tools iptables ];
runtimeInputs = with pkgs; [iproute2 wireguard-tools iptables];
text = ''
text =
''
# Set up the wireguard interface
tmpdir=$(mktemp -d)
cat ${cfg.wireguardConfigFile} > "$tmpdir/wg.conf"
@@ -250,36 +274,42 @@ in {
echo "Hello test"
''
# Add routes to make the namespace accessible
+ strings.concatMapStrings (x:
+ strings.concatMapStrings (
x:
"ip -n wg route add ${x} via ${cfg.bridgeAddress}" + "\n"
) cfg.accessibleFrom
)
cfg.accessibleFrom
# Add prerouting rules
+ strings.concatMapStrings (x:
"iptables -t nat -A PREROUTING -p tcp --dport ${builtins.toString x.From} -j DNAT --to-destination ${cfg.namespaceAddress}:${builtins.toString x.To}" +
"\n"
) cfg.portMappings
+ strings.concatMapStrings (
x:
"iptables -t nat -A PREROUTING -p tcp --dport ${builtins.toString x.From} -j DNAT --to-destination ${cfg.namespaceAddress}:${builtins.toString x.To}"
+ "\n"
)
cfg.portMappings
# Allow VPN TCP ports
+ strings.concatMapStrings (x:
"ip netns exec wg iptables -I INPUT -p tcp --dport ${builtins.toString x} -j ACCEPT" +
"\n"
) cfg.openTcpPorts
+ strings.concatMapStrings (
x:
"ip netns exec wg iptables -I INPUT -p tcp --dport ${builtins.toString x} -j ACCEPT"
+ "\n"
)
cfg.openTcpPorts
# Allow VPN UDP ports
+ strings.concatMapStrings (x:
"ip netns exec wg iptables -I INPUT -p udp --dport ${builtins.toString x} -j ACCEPT" +
"\n"
) cfg.openUdpPorts;
+ strings.concatMapStrings (
x:
"ip netns exec wg iptables -I INPUT -p udp --dport ${builtins.toString x} -j ACCEPT"
+ "\n"
)
cfg.openUdpPorts;
};
in assert ( wgIpv4Address != null ) || abort "No address found in config file."; {
in
assert (wgIpv4Address != null) || abort "No address found in config file."; {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${vpn-namespace}/bin/vpn-namespace";
ExecStopPost = with pkgs; writers.writeBash "wg-down" (''
ExecStopPost = with pkgs;
writers.writeBash "wg-down" (''
${iproute2}/bin/ip -n wg route del default dev wg0
${iproute2}/bin/ip -n wg link del wg0
${iproute2}/bin/ip -n wg link del veth-vpn
@@ -289,7 +319,6 @@ in {
# https://www.man7.org/linux/man-pages/man8/wg-quick.8.html
#${iproute2}/bin/ip netns exec wg resolvconf -d wg0
''
# Delete prerouting rules
+ strings.concatMapStrings (x: "${iptables}/bin/iptables -t nat -D PREROUTING -p tcp --dport ${builtins.toString x.From} -j DNAT --to-destination ${cfg.namespaceAddress}:${builtins.toString x.To}" + "\n") cfg.portMappings);
};
@@ -302,7 +331,7 @@ in {
vpn-test = pkgs.writeShellApplication {
name = "vpn-test";
runtimeInputs = with pkgs; [ util-linux unixtools.ping coreutils curl bash libressl netcat-gnu openresolv dig ];
runtimeInputs = with pkgs; [util-linux unixtools.ping coreutils curl bash libressl netcat-gnu openresolv dig];
text = ''
cd "$(mktemp -d)"
@@ -333,13 +362,13 @@ in {
};
in "${vpn-test}/bin/vpn-test";
bindsTo = [ "netns@wg.service" ];
requires = [ "network-online.target" ];
after = [ "wg.service" ];
bindsTo = ["netns@wg.service"];
requires = ["network-online.target"];
after = ["wg.service"];
serviceConfig = {
User="prowlarr";
User = "prowlarr";
NetworkNamespacePath = "/var/run/netns/wg";
BindReadOnlyPaths=["/etc/netns/wg/resolv.conf:/etc/resolv.conf:norbind" "/data/test.file:/etc/test.file:norbind"];
BindReadOnlyPaths = ["/etc/netns/wg/resolv.conf:/etc/resolv.conf:norbind" "/data/test.file:/etc/test.file:norbind"];
};
};
};