diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index b9da7786d2cf..08b7d621531c 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -164,6 +164,7 @@ ./services/networking/bind.nix ./services/networking/bitlbee.nix ./services/networking/btsync.nix + ./services/networking/cjdns.nix ./services/networking/connman.nix ./services/networking/cntlm.nix ./services/networking/chrony.nix diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix new file mode 100644 index 000000000000..9b715ec63849 --- /dev/null +++ b/nixos/modules/services/networking/cjdns.nix @@ -0,0 +1,207 @@ +# You may notice the commented out sections in this file, +# it would be great to configure cjdns from nix, but cjdns +# reads its configuration from stdin, including the private +# key and admin password, all nested in a JSON structure. +# +# Until a good method of storing the keys outside the nix +# store and mixing them back into a string is devised +# (without too much shell hackery), a skeleton of the +# configuration building lies commented out. + +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.cjdns; + + /* + # can't keep keys and passwords in the nix store, + # but don't want to deal with this stdin quagmire. + + cjdrouteConf = '' { + "admin": {"bind": "${cfg.admin.bind}", "password": "\${CJDNS_ADMIN}" }, + "privateKey": "\${CJDNS_KEY}", + + "interfaces": { + '' + + + optionalString (cfg.interfaces.udp.bind.address != null) '' + "UDPInterface": [ { + "bind": "${cfg.interfaces.udp.bind.address}:"'' + ${if cfg.interfaces.upd.bind.port != null + then ${toString cfg.interfaces.udp.bind.port} + else ${RANDOM} + fi) + + '' } ]'' + + + (if cfg.interfaces.eth.bind != null then '' + "ETHInterface": [ { + "bind": "${cfg.interfaces.eth.bind}", + "beacon": ${toString cfg.interfaces.eth.beacon} + } ] + '' fi ) + + '' + }, + "router": { "interface": { "type": "TUNInterface" }, }, + "security": [ { "setuser": "nobody" } ] + } + ''; + + cjdrouteConfFile = pkgs.writeText "cjdroute.conf" cjdrouteConf + */ +in + +{ + options = { + + services.cjdns = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable this option to start a instance of the + cjdns network encryption and and routing engine. + Configuration will be read from confFile. + ''; + }; + + confFile = mkOption { + default = "/etc/cjdroute.conf"; + description = '' + Configuration file to pipe to cjdroute. + ''; + }; + + /* + admin = { + bind = mkOption { + default = "127.0.0.1:11234"; + description = '' + Bind the administration port to this address and port. + ''; + }; + + passwordFile = mkOption { + example = "/root/cjdns.adminPassword"; + description = '' + File containing a password to the administration port. + ''; + }; + }; + + keyFile = mkOption { + type = types.str; + example = "/root/cjdns.key"; + description = '' + Path to a file containing a cjdns private key on a single line. + ''; + }; + + passwordsFile = mkOption { + type = types.str; + default = null; + example = "/root/cjdns.authorizedPasswords"; + description = '' + A file containing a list of json dictionaries with passwords. + For example: + {"password": "s8xf5z7znl4jt05g922n3wpk75wkypk"}, + { "name": "nice guy", + "password": "xhthk1mglz8tpjrbbvdlhyc092rhpx5"}, + {"password": "3qfxyhmrht7uwzq29pmhbdm9w4bnc8w"} + ''; + }; + + interfaces = { + udp = { + bind = { + address = mkOption { + default = "0.0.0.0"; + description = '' + Address to bind UDP tunnels to; disable by setting to null; + ''; + }; + port = mkOption { + type = types.int; + default = null; + description = '' + Port to bind UDP tunnels to. + A port will be choosen at random if this is not set. + This option is required to act as the server end of + a tunnel. + ''; + }; + }; + }; + + eth = { + bind = mkOption { + default = null; + example = "eth0"; + description = '' + Bind to this device and operate with native wire format. + ''; + }; + + beacon = mkOption { + default = 2; + description = '' + Auto-connect to other cjdns nodes on the same network. + Options: + 0 -- Disabled. + + 1 -- Accept beacons, this will cause cjdns to accept incoming + beacon messages and try connecting to the sender. + + 2 -- Accept and send beacons, this will cause cjdns to broadcast + messages on the local network which contain a randomly + generated per-session password, other nodes which have this + set to 1 or 2 will hear the beacon messages and connect + automatically. + ''; + }; + + connectTo = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Credentials for connecting look similar to UDP credientials + except they begin with the mac address, for example: + "01:02:03:04:05:06":{"password":"a","publicKey":"b"} + ''; + }; + }; + }; + */ + }; + }; + + config = mkIf config.services.cjdns.enable { + + boot.kernelModules = [ "tun" ]; + + /* + networking.firewall.allowedUDPPorts = mkIf (cfg.udp.bind.port != null) [ + cfg.udp.bind.port + ]; + */ + + systemd.services.cjdns = { + description = "encrypted networking for everybody"; + wantedBy = [ "multi-user.target" ]; + wants = [ "network.target" ]; + before = [ "network.target" ]; + path = [ pkgs.cjdns ]; + + serviceConfig = { + Type = "forking"; + ExecStart = '' + ${pkgs.stdenv.shell} -c "${pkgs.cjdns}/sbin/cjdroute < ${cfg.confFile}" + ''; + Restart = "on-failure"; + }; + }; + }; +} diff --git a/pkgs/tools/networking/cjdns/builder.sh b/pkgs/tools/networking/cjdns/builder.sh new file mode 100644 index 000000000000..c2e3701c0468 --- /dev/null +++ b/pkgs/tools/networking/cjdns/builder.sh @@ -0,0 +1,9 @@ +source $stdenv/setup + +unpackPhase +cd git-export + +bash do + +mkdir -p $out/sbin +cp cjdroute $out/sbin diff --git a/pkgs/tools/networking/cjdns/default.nix b/pkgs/tools/networking/cjdns/default.nix index b42f202099b1..48e21f4507e5 100644 --- a/pkgs/tools/networking/cjdns/default.nix +++ b/pkgs/tools/networking/cjdns/default.nix @@ -1,31 +1,27 @@ -{ stdenv, fetchgit, cmake }: +{ stdenv, fetchgit, nodejs, which, python27 }: let - rev = "f7b02ac0cc"; + date = "20140303"; + rev = "f11ce1fd4795b0173ac0ef18c8a6f752aa824adb"; in stdenv.mkDerivation { - name = "cjdns-20130620-${stdenv.lib.strings.substring 0 7 rev}"; + name = "cjdns-${date}-${stdenv.lib.strings.substring 0 7 rev}"; src = fetchgit { - url = "https://github.com/cjdelisle/cjdns.git"; + url = "git://github.com/cjdelisle/cjdns.git"; inherit rev; - sha256 = "1580a62yhph62nv7q2jdqrbkyk9a9g5i17snibkxyykc7rili5zq"; + sha256 = "1bxhf9f1v0slf9mz3ll6jf45mkwvwxlf3yqxx9k23kjyr1nsc8s8"; }; - preConfigure = '' - sed -i -e '/toolchain.*CACHE/d' CMakeLists.txt - ''; + buildInputs = [ which python27 nodejs]; - doCheck = true; - checkPhase = "ctest"; - - buildInputs = [ cmake ]; + builder = ./builder.sh; meta = { homepage = https://github.com/cjdelisle/cjdns; description = "Encrypted networking for regular people"; - license = "GPLv3+"; - maintainers = with stdenv.lib.maintainers; [viric]; - platforms = with stdenv.lib.platforms; linux; + license = stdenv.lib.licenses.gpl3; + maintainers = with stdenv.lib.maintainers; [ viric emery ]; + platforms = stdenv.lib.platforms.linux; }; }