A Python port of the Invisible Internet Project (I2P)
at main 132 lines 3.3 kB view raw
1# NixOS module for the I2P Python router. 2# 3# Usage in configuration.nix or flake-based config: 4# 5# services.i2p-python = { 6# enable = true; 7# ntcp2.port = 9700; 8# ssu2.port = 9700; 9# console.enable = true; 10# console.port = 7657; 11# openFirewall = true; 12# }; 13 14flake: 15{ config, lib, pkgs, ... }: 16 17let 18 cfg = config.services.i2p-python; 19in 20{ 21 options.services.i2p-python = { 22 enable = lib.mkEnableOption "I2P Python router"; 23 24 package = lib.mkPackageOption flake.packages.${pkgs.system} "default" { }; 25 26 ntcp2 = { 27 port = lib.mkOption { 28 type = lib.types.port; 29 default = 9700; 30 description = "NTCP2 transport listen port."; 31 }; 32 address = lib.mkOption { 33 type = lib.types.str; 34 default = "0.0.0.0"; 35 description = "NTCP2 bind address."; 36 }; 37 }; 38 39 ssu2 = { 40 port = lib.mkOption { 41 type = lib.types.port; 42 default = 9700; 43 description = "SSU2 transport listen port (UDP)."; 44 }; 45 }; 46 47 console = { 48 enable = lib.mkEnableOption "web console"; 49 port = lib.mkOption { 50 type = lib.types.port; 51 default = 7657; 52 description = "Web console listen port."; 53 }; 54 address = lib.mkOption { 55 type = lib.types.str; 56 default = "127.0.0.1"; 57 description = "Web console bind address."; 58 }; 59 }; 60 61 dataDir = lib.mkOption { 62 type = lib.types.path; 63 default = "/var/lib/i2p-python"; 64 description = "Directory for router state and data."; 65 }; 66 67 logLevel = lib.mkOption { 68 type = lib.types.enum [ "DEBUG" "INFO" "WARNING" "ERROR" ]; 69 default = "INFO"; 70 description = "Log verbosity level."; 71 }; 72 73 openFirewall = lib.mkOption { 74 type = lib.types.bool; 75 default = false; 76 description = "Whether to open transport ports in the firewall."; 77 }; 78 }; 79 80 config = lib.mkIf cfg.enable { 81 users.users.i2p-python = { 82 isSystemUser = true; 83 group = "i2p-python"; 84 home = cfg.dataDir; 85 createHome = true; 86 description = "I2P Python router daemon"; 87 }; 88 89 users.groups.i2p-python = { }; 90 91 systemd.services.i2p-python = { 92 description = "I2P Python Router"; 93 after = [ "network-online.target" ]; 94 wants = [ "network-online.target" ]; 95 wantedBy = [ "multi-user.target" ]; 96 97 environment = { 98 I2P_DATA_DIR = cfg.dataDir; 99 }; 100 101 serviceConfig = { 102 Type = "simple"; 103 User = "i2p-python"; 104 Group = "i2p-python"; 105 ExecStart = lib.concatStringsSep " " [ 106 (lib.getExe cfg.package) 107 "--host ${cfg.ntcp2.address}" 108 "--port ${toString cfg.ntcp2.port}" 109 "--data-dir ${cfg.dataDir}" 110 "--log-level ${cfg.logLevel}" 111 ]; 112 Restart = "on-failure"; 113 RestartSec = 10; 114 115 # Hardening 116 StateDirectory = "i2p-python"; 117 StateDirectoryMode = "0700"; 118 ProtectSystem = "strict"; 119 ProtectHome = true; 120 PrivateTmp = true; 121 NoNewPrivileges = true; 122 ReadWritePaths = [ cfg.dataDir ]; 123 LimitNOFILE = 65536; 124 }; 125 }; 126 127 networking.firewall = lib.mkIf cfg.openFirewall { 128 allowedTCPPorts = [ cfg.ntcp2.port ]; 129 allowedUDPPorts = [ cfg.ssu2.port ]; 130 }; 131 }; 132}