diff options
| author | tv <tv@krebsco.de> | 2015-03-05 13:01:05 +0100 | 
|---|---|---|
| committer | tv <tv@krebsco.de> | 2015-05-19 23:10:57 +0200 | 
| commit | f52e3eb5b94b8cffcc2b57f4604aac2e9402be39 (patch) | |
| tree | e34e330c04beb0822d59da3f43b0a1e32c06b582 | |
initial commit
| -rw-r--r-- | certs/zalora-ca.crt | 24 | ||||
| -rw-r--r-- | lib/default.nix | 44 | ||||
| -rw-r--r-- | modules/base.nix | 17 | ||||
| -rw-r--r-- | modules/exim.nix | 122 | ||||
| -rw-r--r-- | modules/hosts.nix | 25 | ||||
| -rw-r--r-- | modules/iptables.nix | 69 | ||||
| -rw-r--r-- | modules/nginx.nix | 30 | ||||
| -rw-r--r-- | modules/retiolum.nix | 224 | ||||
| -rw-r--r-- | modules/tools.nix | 101 | ||||
| -rw-r--r-- | modules/urxvt.nix | 24 | ||||
| -rw-r--r-- | modules/users.nix | 226 | ||||
| -rw-r--r-- | modules/xserver.nix | 51 | ||||
| -rw-r--r-- | wu.nix | 457 | 
13 files changed, 1414 insertions, 0 deletions
| diff --git a/certs/zalora-ca.crt b/certs/zalora-ca.crt new file mode 100644 index 0000000..12cdf8f --- /dev/null +++ b/certs/zalora-ca.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIJAPImpJwMgGmhMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYD +VQQGEwJTRzESMBAGA1UECAwJU2luZ2Fwb3JlMQ8wDQYDVQQKDAZaYWxvcmExCzAJ +BgNVBAsMAklUMSUwIwYDVQQDDBxaYWxvcmEgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MSUwIwYJKoZIhvcNAQkBFhZpdC1zZXJ2aWNlc0B6YWxvcmEuY29tMB4XDTE0MDkx +ODIxNDY0N1oXDTI0MDkxNTIxNDY0N1owgY0xCzAJBgNVBAYTAlNHMRIwEAYDVQQI +DAlTaW5nYXBvcmUxDzANBgNVBAoMBlphbG9yYTELMAkGA1UECwwCSVQxJTAjBgNV +BAMMHFphbG9yYSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxJTAjBgkqhkiG9w0BCQEW +Fml0LXNlcnZpY2VzQHphbG9yYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDi48Tkh6XuS2gdE1+gsPPQjTI8Q2wbXqZGTHnyAZx75btOIUZHeHJm +Fvu8erAD+vtx1nD1GOG30uvHFk9Of2mFY1fxw0R1LthJHSLFJU1/GjFSggHWkaI3 +HBSmeALjss/XHG3EtShLo8SHBc/+B8ehqj1JqcXF8q50JtfTQ+zlf+k26ke2S5Xo +OdHLxjlNaPwj+TgJI1DHqs/bTapaPHPKk5+jFQzAcMmq0bygzpQTHCvvKqcoXaJk +UgDBQnVsJUtwfObrM1TKu2TOXUhqgfnnflYf2sz5Sr30QlkrHP+PM3BRLB+6FXhr +UlKKVcAcIwrBo0aJ5Sd0fv39GwV1XCWVAgMBAAGjUDBOMB0GA1UdDgQWBBQFftMH +5/dc0pUNDqLbVQ8gm7+I5TAfBgNVHSMEGDAWgBQFftMH5/dc0pUNDqLbVQ8gm7+I +5TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQC2aSKJ15v5OI7Zj/HQ +lW+iY9STBPJi9lgOjaGrNaPX0IuhJLkeKDntmzjvpGwvcylHMp6Im02svTymteNN +38s8A0aStnmW4ysGT853H7L7Jxzf7J2vrUF0Dj4QkZ07Gp3vAgKnWVcqz36Xr0Se +DEqrKMl/6fq3Ygl35fZXP1kb6t/wP6qx69bnENH6ksHFpZapWYssKNZO9yiB8+Eq +ngB22X/ycMmAqOnNQDzw1JBw7LzdXypCG75UKEK6kbnUy2yPADdHpH8v9qcRa1U9 +vEmUTJs6i1CpPO+2frPJ8A8QIp61nNxe7xJ1SnNVtwk9d6SRet6YGySvgG748Wjw +GwWx +-----END CERTIFICATE----- diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..c1663a7 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,44 @@ +{ pkgs, ... }: + +with builtins; + +let +  inherit (pkgs.lib) stringAsChars; +in + +{ + + +  # "7.4.335" -> "74" +  majmin = with pkgs.lib; x : concatStrings (take 2 (splitString "." x)); + + +  concat = xs : +    if xs == [] +      then "" +      else head xs + concat (tail xs) +    ; + +  flip = f : x : y : f y x; + +  # isSuffixOf :: String -> String -> Bool +  isSuffixOf = +    s : xs : +      let +        sn = stringLength s; +        xsn = stringLength xs; +      in +        xsn >= sn && substring (xsn - sn) sn xs == s ; + +  removeSuffix = +    s : xs : substring 0 (stringLength xs - stringLength s) xs; + +  # setMap :: (String -> a -> b) -> Set String a -> [b] +  #setMap = f: xs: map (k : f k (getAttr k xs)) (attrNames xs); + +  # setToList :: Set k a -> [a] +  #setToList = setMap (_: v: v); + +  shell-escape = +    stringAsChars (c: if c == "\n" then ''"${c}"'' else "\\${c}"); +} diff --git a/modules/base.nix b/modules/base.nix new file mode 100644 index 0000000..76c8b89 --- /dev/null +++ b/modules/base.nix @@ -0,0 +1,17 @@ +{ config, pkgs, ... }: + +{ +  time.timeZone = "Europe/Berlin"; + +  nix.maxJobs = 8; +  nix.useChroot = true; +  # TODO check if both are required: +  nix.chrootDirs = [ "/etc/protocols" pkgs.iana_etc.outPath ]; + +  nix.trustedBinaryCaches = [ +    "https://cache.nixos.org" +    "http://cache.nixos.org" +    "http://hydra.nixos.org" +  ]; + +} diff --git a/modules/exim.nix b/modules/exim.nix new file mode 100644 index 0000000..4a0232c --- /dev/null +++ b/modules/exim.nix @@ -0,0 +1,122 @@ +{ config, pkgs, ... }: + +{ +  services.exim = +    let +      retiolumHostname = "wu.retiolum"; # TODO "${networking.hostName}.retiolum"; +    in +      { enable = true; +        config = '' +          primary_hostname = ${retiolumHostname} +          domainlist local_domains    = @ : localhost +          domainlist relay_to_domains = *.retiolum +          hostlist   relay_from_hosts = <; 127.0.0.1 ; ::1 + +          acl_smtp_rcpt = acl_check_rcpt +          acl_smtp_data = acl_check_data + +          host_lookup = * +          rfc1413_hosts = * +          rfc1413_query_timeout = 5s + +          log_file_path = syslog +          syslog_timestamp = false +          syslog_duplication = false + +          begin acl + +          acl_check_rcpt: +            accept  hosts = : +                    control = dkim_disable_verify + +            deny    message       = Restricted characters in address +                    domains       = +local_domains +                    local_parts   = ^[.] : ^.*[@%!/|] + +            deny    message       = Restricted characters in address +                    domains       = !+local_domains +                    local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ + +            accept  local_parts   = postmaster +                    domains       = +local_domains + +            #accept +            #  hosts = *.retiolum +            #  domains = *.retiolum +            #  control = dkim_disable_verify + +            #require verify        = sender + +            accept  hosts         = +relay_from_hosts +                    control       = submission +                    control       = dkim_disable_verify + +            accept  authenticated = * +                    control       = submission +                    control       = dkim_disable_verify + +            require message = relay not permitted +                    domains = +local_domains : +relay_to_domains + +            require verify = recipient + +            accept + + +          acl_check_data: +            accept + + +          begin routers + +          retiolum: +            driver = manualroute +            domains = ! ${retiolumHostname} : *.retiolum +            transport = remote_smtp +            route_list = ^.* $0 byname +            no_more + +          nonlocal: +            debug_print = "R: nonlocal for $local_part@$domain" +            driver = redirect +            domains = ! +local_domains +            allow_fail +            data = :fail: Mailing to remote domains not supported +            no_more + +          local_user: +            # debug_print = "R: local_user for $local_part@$domain" +            driver = accept +            check_local_user +          # local_part_suffix = +* : -* +          # local_part_suffix_optional +            transport = home_maildir +            cannot_route_message = Unknown user + + +          begin transports + +          remote_smtp: +            driver = smtp + +          home_maildir: +            driver = appendfile +            maildir_format +            directory = $home/Maildir +            directory_mode = 0700 +            delivery_date_add +            envelope_to_add +            return_path_add +          # group = mail +          # mode = 0660 + +          begin retry +          *.retiolum             *           F,42d,1m +          *                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h + +          begin rewrite + +          begin authenticators +        ''; +      }; +} diff --git a/modules/hosts.nix b/modules/hosts.nix new file mode 100644 index 0000000..f59f87c --- /dev/null +++ b/modules/hosts.nix @@ -0,0 +1,25 @@ +{ config, pkgs, ... }: + +{ +  networking.extraHosts = +    '' +      192.168.1.1 wrt.gg23 wrt +      192.168.1.11 mors.gg23 +      192.168.1.12 uriel.gg23 +      192.168.1.23 raspi.gg23 raspi +      192.168.1.37 wu.gg23 +      192.168.1.110 nomic.gg23 +      192.168.1.124 schnabeldrucker.gg23 schnabeldrucker + +      127.0.0.1  dev.zalora.sg www.dev.zalora.sg bob.dev.zalora.sg static.dev.zalora.sg +      127.0.0.1  dev.zalora.com.my www.dev.zalora.com.my bob.dev.zalora.com.my static.dev.zalora.com.my +      127.0.0.1  dev.zalora.com.ph www.dev.zalora.com.ph bob.dev.zalora.com.ph static.dev.zalora.com.ph +      127.0.0.1  dev.zalora.vn www.dev.zalora.vn bob.dev.zalora.vn static.dev.zalora.vn +      127.0.0.1  dev.zalora.co.id www.dev.zalora.co.id bob.dev.zalora.co.id static.dev.zalora.co.id +      127.0.0.1  dev.zalora.co.th www.dev.zalora.co.th bob.dev.zalora.co.th static.dev.zalora.co.th +      127.0.0.1  dev.zalora.com.hk www.dev.zalora.com.hk bob.dev.zalora.com.hk static.dev.zalora.com.hk + +      54.93.104.95 eu-dev.hk.zalora.net www.eu-dev.hk.zalora.net bob.eu-dev.hk.zalora.net static.eu-dev.hk.zalora.net +      54.93.104.95 eu-dev.sg.zalora.net www.eu-dev.sg.zalora.net bob.eu-dev.sg.zalora.net static.eu-dev.sg.zalora.net +    ''; +} diff --git a/modules/iptables.nix b/modules/iptables.nix new file mode 100644 index 0000000..ee40343 --- /dev/null +++ b/modules/iptables.nix @@ -0,0 +1,69 @@ +{ config, pkgs, ... }: + +{ +  # +  # iptables +  # +  networking.firewall.enable = false; +  system.activationScripts.iptables = +    let +      log = false; +      when = c: f: if c then f else ""; +    in +      '' +        ip4tables() { ${pkgs.iptables}/sbin/iptables "$@"; } +        ip6tables() { ${pkgs.iptables}/sbin/ip6tables "$@"; } +        ipXtables() { ip4tables "$@"; ip6tables "$@"; } + +        # +        # nat +        # + +        # reset tables +        ipXtables -t nat -F +        ipXtables -t nat -X + +        # +        ipXtables -t nat -A PREROUTING -j REDIRECT ! -i retiolum -p tcp --dport ssh --to-ports 0 +        ipXtables -t nat -A PREROUTING -j REDIRECT -p tcp --dport 11423 --to-ports ssh + +        # +        # filter +        # + +        # reset tables +        ipXtables -P INPUT DROP +        ipXtables -P FORWARD DROP +        ipXtables -F +        ipXtables -X + +        # create custom chains +        ipXtables -N Retiolum + +        # INPUT +        ipXtables -A INPUT -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED +        ipXtables -A INPUT -j ACCEPT -i lo +        ipXtables -A INPUT -j ACCEPT -p tcp --dport ssh -m conntrack --ctstate NEW +        ipXtables -A INPUT -j ACCEPT -p tcp --dport http -m conntrack --ctstate NEW +        ipXtables -A INPUT -j ACCEPT -p tcp --dport tinc -m conntrack --ctstate NEW +        ipXtables -A INPUT -j ACCEPT -p tcp --dport smtp -m conntrack --ctstate NEW +        ipXtables -A INPUT -j Retiolum -i retiolum +        ${when log "ipXtables -A INPUT -j LOG --log-level info --log-prefix 'INPUT DROP '"} + +        # FORWARD +        ${when log "ipXtables -A FORWARD -j LOG --log-level info --log-prefix 'FORWARD DROP '"} + +        # Retiolum +        ip4tables -A Retiolum -j ACCEPT -p icmp --icmp-type echo-request +        ip6tables -A Retiolum -j ACCEPT -p ipv6-icmp -m icmp6 --icmpv6-type echo-request + + +        ${when log "ipXtables -A Retiolum -j LOG --log-level info --log-prefix 'REJECT '"} +        ipXtables -A Retiolum -j REJECT -p tcp --reject-with tcp-reset +        ip4tables -A Retiolum -j REJECT -p udp --reject-with icmp-port-unreachable +        ip4tables -A Retiolum -j REJECT        --reject-with icmp-proto-unreachable +        ip6tables -A Retiolum -j REJECT -p udp --reject-with icmp6-port-unreachable +        ip6tables -A Retiolum -j REJECT + +      ''; +} diff --git a/modules/nginx.nix b/modules/nginx.nix new file mode 100644 index 0000000..8b42061 --- /dev/null +++ b/modules/nginx.nix @@ -0,0 +1,30 @@ +{ config, pkgs, ... }: + +{ +  services.nginx = +    let +      name = config.networking.hostName; +      qname = "${name}.retiolum"; +    in +      { +        enable = true; +        httpConfig = '' +          sendfile  on; +          server { +            listen      80; +            server_name ${name} ${qname} localhost; +            root /srv/http/${name}; +            location ~ ^/~(.+?)(/.*)?$ { +              alias /home/$1/public_html$2; +            } +          } +          types { +            text/css css; +            text/html html; +            image/svg+xml svg; +          } +          default_type text/html; +          charset utf-8; +        ''; +      }; +} diff --git a/modules/retiolum.nix b/modules/retiolum.nix new file mode 100644 index 0000000..4011216 --- /dev/null +++ b/modules/retiolum.nix @@ -0,0 +1,224 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + +  ###### interface + +  options = { +    services.retiolum = { + +      enable = mkOption { +        type = types.bool; +        default = false; +        description = "Enable tinc daemon for Retiolum."; +      }; + +      name = mkOption { +        type = types.string; +        default = config.networking.hostName; +        # Description stolen from tinc.conf(5). +        description = '' +          This is the name which identifies this tinc daemon.  It must +          be unique for the virtual private network this daemon will +          connect to.  The Name may only consist of alphanumeric and +          underscore characters.  If Name starts with a $, then the +          contents of the environment variable that follows will be +          used.  In that case, invalid characters will be converted to +          underscores.  If Name is $HOST, but no such environment +          variable exist, the hostname will be read using the +          gethostnname() system call This is the name which identifies +          the this tinc daemon. +        ''; +      }; + +      generateEtcHosts = mkOption { +        type = types.string; +        default = "both"; +        description = '' +          If set to <literal>short</literal>, <literal>long</literal>, or <literal>both</literal>, +          then generate entries in <filename>/etc/hosts</filename> from subnets. +        ''; +      }; + +      network = mkOption { +        type = types.string; +        default = "retiolum"; +        description = '' +          The tinc network name. +          It is used to generate long host entries, +          derive the name of the user account under which tincd runs, +          and name the TUN device. +        ''; +      }; + +      tincPackage = mkOption { +        type = types.package; +        default = pkgs.tinc; +        description = "Tincd package to use."; +      }; + +      hosts = mkOption { +        default = null; +        description = '' +          Hosts package or path to use. +          If a path is given, then it will be used to generate an ad-hoc package. +        ''; +      }; + +      iproutePackage = mkOption { +        type = types.package; +        default = pkgs.iproute; +        description = "Iproute2 package to use."; +      }; + + +      privateKeyFile = mkOption { +        # TODO if it's types.path then it gets copied to /nix/store with +        #      bad unsafe permissions... +        type = types.string; +        default = "/etc/tinc/retiolum/rsa_key.priv"; +        description = "Generate file with <literal>tincd -K</literal>."; +      }; + +      connectTo = mkOption { +        type = types.listOf types.string; +        default = [ "fastpoke" "pigstarter" "kheurop" ]; +        description = "TODO describe me"; +      }; + +    }; +  }; + + +  ###### implementation + +  config = +    let +      cfg = config.services.retiolum; +      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 +                sed -En ' +                  s|^ *Subnet *= *([^ /]*)(/[0-9]*)? *$|\1  '"$(hostnames $i)"'|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 + +      mkIf cfg.enable { +        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"; +          }; +          restartIfChanged = true; +        }; + +        users.extraUsers = singleton { +          name = user; +          uid = 42; # TODO config.ids.uids.retiolum +        }; + +      }; + +} diff --git a/modules/tools.nix b/modules/tools.nix new file mode 100644 index 0000000..4be84a6 --- /dev/null +++ b/modules/tools.nix @@ -0,0 +1,101 @@ +{ config, pkgs, ... }: + +let +  inherit (pkgs) lib stdenv; +  inherit (lib.strings) concatStringsSep stringAsChars; +  inherit (lib.attrsets) attrValues mapAttrs; +  inherit (lib) makeSearchPath; +  inherit (import ../lib { inherit pkgs; }) shell-escape; + + +  # TODO make these scripts available in an maintenance shell + + +  scripts = { + +    # just so we don't reboot accidentally +    reboot = +      '' +        echo no reboot >&2 +        exit 23 +      ''; + +    rebuild = +      '' +        nixpkgs=''${nixpkgs-/home/tv/src/nixpkgs} +        nixos-rebuild \ +            --show-trace \ +            -I nixpkgs="$nixpkgs" \ +            switch \ +            2>&1 \ +          | sed ${shell-escape '' +              s|"\(/home/tv/src/config/[^":]*\)"|[31;1m\1[m| +              s|^trace:\s*\(.*\)|[35;1m\1[m| +          ''} +      ''; + +  }; + +  wrap = script: +    '' +      #! /bin/sh +      set -euf +      ${script} +    ''; +      #lib=$lib +      #export PATH=$bin:${makeSearchPath "bin" buildInputs} + +  buildScript = name: script: +    builtins.trace "building ${name}" +    '' +      echo ${shell-escape script} > $bin/${shell-escape name} +      chmod +x $bin/${shell-escape name} +    ''; + + + +  tools = pkgs.stdenv.mkDerivation rec { +    name = "tools"; +    src = /var/empty; + +    buildInputs = []; + + +    buildPhase = +      '' +        mkdir $out + +        bin=$out/bin +        mkdir $bin + +        ${concatStringsSep "\n" (attrValues (mapAttrs buildScript scripts))} + +      ''; +      #'' +      #mkdir $out + +      #lib=$out/lib +      #cp -r lib $lib + +      #bin=$out/bin +      #mkdir $bin +      #${concatStringsSep "\n" (attrValues (mapAttrs (name: script: +      #    '' +      #    { +      #      echo '#! /bin/sh' +      #      echo 'set -euf' +      #      echo "lib=$lib" +      #      echo "export PATH=$bin:${makeSearchPath "bin" buildInputs}" +      #      echo ${shell-escape script} +      #    } > $bin/${name} +      #    chmod +x $bin/${name} +      #    '') scripts))} +      #''; +    installPhase = ":"; +  }; + +in + +{ +  environment.systemPackages = [ tools ]; +} diff --git a/modules/urxvt.nix b/modules/urxvt.nix new file mode 100644 index 0000000..a975812 --- /dev/null +++ b/modules/urxvt.nix @@ -0,0 +1,24 @@ +{ pkgs, ... }: + + with builtins; + +let +  users = [ "tv" ]; +  urxvt = pkgs.rxvt_unicode; +  mkService = user: { +    description = "urxvt terminal daemon"; +    wantedBy = [ "multi-user.target" ]; +    restartIfChanged = false; +    serviceConfig = { +      Restart = "always"; +      User = user; +      ExecStart = "${urxvt}/bin/urxvtd"; +    }; +  }; + +in + +{ +  environment.systemPackages = [ urxvt ]; +  systemd.services = listToAttrs (map (u: { name = "${u}-urxvtd"; value = mkService u; }) users); +} diff --git a/modules/users.nix b/modules/users.nix new file mode 100644 index 0000000..eec1def --- /dev/null +++ b/modules/users.nix @@ -0,0 +1,226 @@ +{ config, pkgs, ... }: + +let +  inherit (builtins) attrValues; +  inherit (pkgs.lib) concatMap filterAttrs mapAttrs concatStringsSep; + + +  users = { +    tv = { +      uid = 1337; +      group = "users"; +      extraGroups = [ +        "audio" +        "video" +        "wheel" +      ]; +    }; + +    ff = { +      uid = 13378001; +      group = "tv-sub"; +      extraGroups = [ +        "audio" +        "video" +      ]; +    }; + +    cr = { +      uid = 13378002; +      group = "tv-sub"; +      extraGroups = [ +        "audio" +        "video" +        "bumblebee" +      ]; +    }; + +    vimb = { +      uid = 13378003; +      group = "tv-sub"; +      extraGroups = [ +        "audio" +        "video" +        "bumblebee" +      ]; +    }; + +    fa = { +      uid = 2300001; +      group = "tv-sub"; +    }; + +    rl = { +      uid = 2300002; +      group = "tv-sub"; +    }; + +    btc-bitcoind = { +      uid = 2301001; +      group = "tv-sub"; +    }; + +    btc-electrum = { +      uid = 2301002; +      group = "tv-sub"; +    }; + +    ltc-litecoind = { +      uid = 2301101; +      group = "tv-sub"; +    }; + +    eth = { +      uid = 2302001; +      group = "tv-sub"; +    }; + +    emse-hsdb = { +      uid = 4200101; +      group = "tv-sub"; +    }; + +    wine = { +      uid = 13370400; +      group = "tv-sub"; +      extraGroups = [ +        "audio" +        "video" +        "bumblebee" +      ]; +    }; + +    # dwarffortress +    df = { +      uid = 13370401; +      group = "tv-sub"; +      extraGroups = [ +        "audio" +        "video" +        "bumblebee" +      ]; +    }; + +    # XXX visudo: Warning: Runas_Alias `FTL' referenced but not defined +    FTL = { +      uid = 13370402; +      #group = "tv-sub"; +      extraGroups = [ +        "audio" +        "video" +        "bumblebee" +      ]; +    }; + +    freeciv = { +      uid = 13370403; +      group = "tv-sub"; +    }; + +    xr = { +      uid = 13370061; +      group = "tv-sub"; +      extraGroups = [ +        "audio" +        "video" +      ]; +    }; + +    "23" = { +      uid = 13370023; +      group = "tv-sub"; +    }; + +    electrum = { +      uid = 13370102; +      group = "tv-sub"; +    }; + +    Reaktor = { +      uid = 4230010; +      group = "tv-sub"; +    }; + +    gitolite = { +      uid = 7700; +    }; + +    skype = { +      uid = 6660001; +      group = "tv-sub"; +      extraGroups = [ +        "audio" +      ]; +    }; + +    onion = { +      uid = 6660010; +      group = "tv-sub"; +    }; + +    zalora = { +      uid = 1000301; +      group = "tv-sub"; +      extraGroups = [ +        "audio" +        # TODO remove vboxusers when hardening is active +        "vboxusers" +        "video" +      ]; +    }; + +  }; + + +  extraUsers = +    mapAttrs (name: user: user // { +      inherit name; +      home = "/home/${name}"; +      createHome = true; +      useDefaultShell = true; +    }) users; + + +  extraGroups = { +    tv-sub.gid = 1337; +  }; + + +  sudoers = +    let +      inherit (builtins) filter hasAttr; +      inherit (import ../lib { inherit pkgs; }) concat isSuffixOf removeSuffix setToList; + +      hasMaster = { group ? "", ... }: +        isSuffixOf "-sub" group; + +      masterOf = user : removeSuffix "-sub" user.group; +    in +    concatStringsSep "\n" +      (map (u: "${masterOf u} ALL=(${u.name}) NOPASSWD: ALL") +           (filter hasMaster (attrValues extraUsers))); + +in + + +{ +  imports = [ +    <secrets/hashedPasswords.nix> +  ]; + +  users.defaultUserShell = "/run/current-system/sw/bin/bash"; +  users.extraGroups = extraGroups; +  users.extraUsers = extraUsers; +  users.mutableUsers = false; + +  #security.sudo.configFile = sudoers config.users.extraUsers; +  security.sudo.configFile = +    with builtins; trace +    '' +      OK +    '' +    sudoers; +  security.sudo.extraConfig = '' +    Defaults mailto="tv@wu.retiolum" +  ''; +} diff --git a/modules/xserver.nix b/modules/xserver.nix new file mode 100644 index 0000000..c652018 --- /dev/null +++ b/modules/xserver.nix @@ -0,0 +1,51 @@ +{ config, pkgs, ... }: + +{ +  services.xserver.enable = true; + + +  #fonts.enableFontConfig = true; +  #fonts.enableFontDir = true; +  fonts.fonts = [ +    pkgs.xlibs.fontschumachermisc +  ]; +  #services.xfs.enable = true; +  #services.xserver.useXFS = "unix/:7100"; + +  services.xserver.displayManager.desktopManagerHandlesLidAndPower = true; + +  #services.xserver.display = 11; +  #services.xserver.tty = 11; +  # services.xserver.layout = "us"; +  # services.xserver.xkbOptions = "eurosign:e"; + +  # TODO this is host specific +  services.xserver.synaptics = { +    enable = true; +    twoFingerScroll = true; +    accelFactor = "0.035"; +    additionalOptions = '' +      Option "FingerHigh" "60" +      Option "FingerLow"  "60" +    ''; +  }; + +  #services.xserver.multitouch.enable = true; + +  services.xserver.windowManager.xmonad.extraPackages = hspkgs: with hspkgs; [ +    X11-xshape +  ]; +  services.xserver.windowManager.xmonad.enable = true; +  services.xserver.windowManager.xmonad.enableContribAndExtras = true; +  services.xserver.windowManager.default = "xmonad"; +  services.xserver.desktopManager.default = "none"; +  services.xserver.desktopManager.xterm.enable = false; + +  services.xserver.displayManager.slim.enable = true; +  #services.xserver.displayManager.auto.enable = true; +  #services.xserver.displayManager.auto.user = "tv"; +  #services.xserver.displayManager.job.logsXsession = true; + + +  services.xserver.vaapiDrivers = [ pkgs.vaapiIntel ]; +} @@ -0,0 +1,457 @@ +{ config, pkgs, ... }: + +with (import ./lib { inherit pkgs; }); + +{ +  imports = [ +    ./modules/base.nix +    ./modules/retiolum.nix +    ./modules/urxvt.nix +    ./modules/iptables.nix +    ./modules/users.nix +    ./modules/tools.nix +    ./modules/hosts.nix +    ./modules/xserver.nix +    ./modules/exim.nix +    ./modules/nginx.nix +  ]; + +  services.udev.extraRules = '' +    SUBSYSTEM=="net", ATTR{address}=="00:90:f5:da:aa:c3", NAME="en0" +    SUBSYSTEM=="net", ATTR{address}=="a0:88:b4:1b:ae:6c", NAME="wl0" + +    # for jack +    KERNEL=="rtc0", GROUP="audio" +    KERNEL=="hpet", GROUP="audio" +  ''; + +  #services.virtualbox.enable = true; +  #services.virtualboxGuest.enable = false; +  services.virtualboxHost.enable = true; +  #services.virtualboxHost.addNetworkInterface = false; +  #systemd.services.vboxnet = +  #  let +  #    remove_vboxnets = '' +  #      for i in $(cd /sys/class/net && ls | grep ^vboxnet); do +  #        VBoxManage hostonlyif remove $i +  #      done +  #    ''; +  #  in { +  #    wantedBy = [ "multi-user.target" ]; +  #    requires = [ "dev-vboxnetctl.device" ]; +  #    after = [ "dev-vboxnetctl.device" ]; +  #    path = with pkgs; [ +  #      linuxPackages.virtualbox +  #      nettools +  #    ]; +  #    postStop = remove_vboxnets; +  #    script = '' +  #      ${remove_vboxnets} # just in case... +  #      VBoxManage hostonlyif create # vboxnet0 +  #      ifconfig vboxnet0 up 169.254.13.37/16 +  #    ''; +  #    serviceConfig = { +  #      Type = "oneshot"; +  #      PrivateTmp = true; +  #      RemainAfterExit = "yes"; +  #    }; +  #    environment.VBOX_USER_HOME = "/tmp"; +  #  }; + + +  services.bitlbee.enable = true; + +  #services.rabbitmq = { +  #  enable = true; +  #  cookie = "f00f"; +  #  plugins = [ +  #    "rabbitmq_management" +  #  ]; +  #}; + + +  #services.elasticsearch.enable = true; + +  #services.cgserver = { +  #  enable = true; +  #  httpPort = 8003; +  #  #flushLog = false; +  #  #cgroupRoot = "/sys/fs/cgroup"; +  #  #user = "zalora"; +  #}; + + + + +  #services.tlsdated = { +  #  enable = true; +  #  extraOptions = "-p"; +  #}; + +  services.tor.enable = true; +  services.tor.client.enable = true; + + + +  # hardware configuration +  boot.initrd.luks.devices = [ +    { name = "home"; device = "/dev/vg840/enchome"; preLVM = false; } +  ]; +  boot.initrd.luks.cryptoModules = [ "aes" "sha512" "xts" ]; +  boot.initrd.availableKernelModules = [ "ahci" ]; +  #boot.kernelParams = [ +  #  "intel_pstate=enable" +  #]; +  boot.kernelModules = [ "kvm-intel" ]; +  boot.extraModulePackages = [ ]; + +  # 2014-12-17 pkgs.linuxPackages_3_14 is known good +  boot.kernelPackages = pkgs.linuxPackages_3_18; + +  boot.kernel.sysctl = { +    # Enable IPv6 Privacy Extensions +    "net.ipv6.conf.all.use_tempaddr" = 2; +    "net.ipv6.conf.default.use_tempaddr" = 2; +  }; + +  boot.extraModprobeConfig = '' +    options kvm_intel nested=1 +  ''; + +  fileSyst | 
