summaryrefslogtreecommitdiffstats
path: root/modules/tv/retiolum/config.nix
blob: f1d227f6b2d538f59f60b0f35e175a74b7b47698 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{ cfg, config, lib, pkgs, ... }:

let
  inherit (lib) concatStrings singleton;

  tinc = cfg.tincPackage;
  hostsType = builtins.typeOf cfg.hosts;
  hosts =
    if hostsType == "package" then
      # use package as is
      cfg.hosts
    else if hostsType == "path" then
      # use path to generate a package
      pkgs.stdenv.mkDerivation {
        name = "custom-retiolum-hosts";
        src = cfg.hosts;
        installPhase = ''
          mkdir $out
          find . -name .git -prune -o -type f -print0 | xargs -0 cp --target-directory $out
        '';
      }
    else
      abort "The option `services.retiolum.hosts' must be set to a package or a path"
    ;
  iproute = cfg.iproutePackage;

  retiolumExtraHosts = import (pkgs.runCommand "retiolum-etc-hosts"
    { }
    ''
      generate() {
        (cd ${hosts}
          printf \'\'
          for i in `ls`; do
            names=$(hostnames $i)
            for j in `sed -En 's|^ *Aliases *= *(.+)|\1|p' $i`; do
              names="$names $(hostnames $j)"
            done
            sed -En '
              s|^ *Subnet *= *([^ /]*)(/[0-9]*)? *$|\1  '"$names"'|p
            ' $i
          done | sort
          printf \'\'
        )
      }

      case ${cfg.generateEtcHosts} in
        short)
          hostnames() { echo "$1"; }
          generate
          ;;
        long)
          hostnames() { echo "$1.${cfg.network}"; }
          generate
          ;;
        both)
          hostnames() { echo "$1.${cfg.network} $1"; }
          generate
          ;;
        *)
          echo '""'
          ;;
      esac > $out
    '');


  confDir = pkgs.runCommand "retiolum" {
    # TODO text
    executable = true;
    preferLocalBuild = true;
  } ''
    set -euf

    mkdir -p $out

    ln -s ${hosts} $out/hosts

    cat > $out/tinc.conf <<EOF
    Name = ${cfg.name}
    Device = /dev/net/tun
    Interface = ${cfg.network}
    ${concatStrings (map (c : "ConnectTo = " + c + "\n") cfg.connectTo)}
    PrivateKeyFile = ${cfg.privateKeyFile}
    EOF

    # source: krebscode/painload/retiolum/scripts/tinc_setup/tinc-up
    cat > $out/tinc-up <<EOF
    host=$out/hosts/${cfg.name}
    ${iproute}/sbin/ip link set \$INTERFACE up

    addr4=\$(sed -n 's|^ *Subnet *= *\(10[.][^ ]*\) *$|\1|p' \$host)
    if [ -n "\$addr4" ];then
        ${iproute}/sbin/ip -4 addr add \$addr4 dev \$INTERFACE
        ${iproute}/sbin/ip -4 route add 10.243.0.0/16 dev \$INTERFACE
    fi
    addr6=\$(sed -n 's|^ *Subnet *= *\(42[:][^ ]*\) *$|\1|p' \$host)
    ${iproute}/sbin/ip -6 addr add \$addr6 dev \$INTERFACE
    ${iproute}/sbin/ip -6 route add 42::/16 dev \$INTERFACE
    EOF

    chmod +x $out/tinc-up
  '';


  user = cfg.network + "-tinc";

in

{
  environment.systemPackages = [ tinc hosts iproute ];

  networking.extraHosts = retiolumExtraHosts;

  systemd.services.retiolum = {
    description = "Tinc daemon for Retiolum";
    after = [ "network.target" ];
    wantedBy = [ "multi-user.target" ];
    path = [ tinc iproute ];
    serviceConfig = {
      # TODO we cannot chroot (-R) b/c we use symlinks to hosts
      #      and the private key.
      ExecStart = "${tinc}/sbin/tincd -c ${confDir} -d 0 -U ${user} -D";
      SyslogIdentifier = "retiolum-tincd";
    };
  };

  users.extraUsers = singleton {
    name = user;
    uid = 2961822815; # bin/genid retiolum-tinc
  };
}