{ config, pkgs, ... }: let trivmixService = opts: (pkgs.callPackage ./custom/trivmix-service.nix opts).out; thermoprint-servant = (pkgs.callPackage ./custom/thermoprint {}).thermoprint-servant; inherit (pkgs) lib; in rec { imports = [ ./musnix ./bragi/hw.nix ./custom/zsh.nix ./users.nix ./custom/unit-status-mail.nix ]; boot.loader.grub.enable = true; boot.loader.grub.version = 2; boot.kernelModules = [ "usblp" ]; boot.tmpOnTmpfs = true; boot.supportedFilesystems = [ "cifs" ]; networking.hostName = "bragi"; networking.hostId = "2af11085"; networking.wireless.enable = true; nixpkgs.config.packageOverrides = pkgs: rec { haskellPackages = pkgs.recurseIntoAttrs ( pkgs.haskellPackages.override { overrides = self: super: let callPackage = pkgs.lib.callPackageWith ( pkgs // self ); in lib.mapAttrs (name: pkg: pkgs.haskell.lib.dontCheck pkg) (super // { trivmix = callPackage ./custom/trivmix {}; inherit (pkgs.callPackage ./custom/thermoprint { extraPackages = (p: with p; [ persistent-postgresql ]); }) thermoprint-spec thermoprint-bbcode thermoprint-client thermoprint-server thermoprint-webgui tprint bbcode; }); } ); jack2Full = pkgs.jack2Full.override { dbus = null; }; mpd = pkgs.mpd.override { gmeSupport = false; pulseaudioSupport = false; }; inherit (haskellPackages) trivmix thermoprint-server thermoprint-webgui tprint; }; nixpkgs.config.allowUnfree = true; environment.systemPackages = with pkgs; [ git mosh rsync tmux nfs-utils jack2Full trivmix zsh tprint samba ]; # List services that you want to enable: services.openssh = { enable = true; }; services.fcron = { enable = true; systab = '' %weekly * * nix-collect-garbage --delete-older-than '7d' ''; }; systemd.automounts = [ { wantedBy = [ "multi-user.target" ]; where = "/media/odin"; } { wantedBy = [ "multi-user.target" ]; where = "/media/dellingr"; automountConfig.TimoutIdleSec = "30s"; } { wantedBy = [ "multi-user.target" ]; where = "/media/vali"; automountConfig.TimoutIdleSec = "5min"; } ]; systemd.mounts = [ { what = "odin.asgard.yggdrasil:/srv/media"; where = "/media/odin"; type = "nfs"; options = "ro"; } { what = "/dev/disk/by-uuid/6436-3432"; where = "/media/dellingr"; type = "vfat"; } { what = "//VALI/Public"; where = "/media/vali"; type = "cifs"; options = "guest,dir_mode=0777,file_mode=0666,nounix,iocharset=utf8,sec=none"; } ]; systemd.globalEnvironment = { JACK_PROMISCUOUS_SERVER = "1"; }; environment.sessionVariables = { JACK_PROMISCUOUS_SERVER = "1"; }; musnix = { enable = true; alsaSeq.enable = false; kernel = { packages = with pkgs; linuxPackages_latest_rt; optimize = true; realtime = true; }; }; systemd.services.jack = { wantedBy = [ "sound.target" ]; serviceConfig = { Type = "simple"; ExecStart = "${pkgs.jack2Full}/bin/jackd -d alsa -d 'hw:1' -M -H -r 96000"; ExecStartPost = "${pkgs.jack2Full}/bin/jack_wait -w -t 5"; User = "jack"; Group = "audio"; UMask = "0000"; Nice = "-15"; LimitRTPRIO = "95:95"; LimitMEMLOCK = "infinity"; }; }; systemd.services."mpdmix0" = trivmixService { name = "mpdmix0"; connectOut = "outnode0:in"; group = "mpd"; initial = "-35dB"; }; systemd.services."mpdmix1" = trivmixService { name = "mpdmix1"; connectOut = "outnode1:in"; group = "mpd"; initial = "-35dB"; }; systemd.services."passmix0" = trivmixService { name = "passmix0"; connectOut = "outnode0:in"; connectIn = "system:capture_5"; group = "vali_out"; initial = "-5dB"; }; systemd.services."passmix1" = trivmixService { name = "passmix1"; connectOut = "outnode1:in"; connectIn = "system:capture_6"; group = "vali_out"; initial = "-5dB"; }; systemd.services."passmix2" = trivmixService { name = "passmix2"; connectOut = "system:playback_5"; connectIn = "system:capture_1"; group = "mic_out"; initial = "1"; }; systemd.services."passmix3" = trivmixService { name = "passmix3"; connectOut = "system:playback_6"; connectIn = "system:capture_1"; group = "mic_out"; initial = "1"; }; systemd.services."passmix4" = trivmixService { name = "passmix4"; connectOut = "outnode0:in"; connectIn = "system:capture_7"; group = "hel_out"; initial = "-5dB"; }; systemd.services."passmix5" = trivmixService { name = "passmix5"; connectOut = "outnode1:in"; connectIn = "system:capture_8"; group = "hel_out"; initial = "-5dB"; }; systemd.services."outnode0" = trivmixService { name = "outnode0"; initial = "1"; }; systemd.services."outnode1" = trivmixService { name = "outnode1"; initial = "1"; }; systemd.services."headphones0" = trivmixService { name = "heaphones0"; connectOut = "system:playback_3"; connectIn = "outnode0:out"; group = "headphones"; initial = "1"; }; systemd.services."headphones1" = trivmixService { name = "heaphones1"; connectOut = "system:playback_4"; connectIn = "outnode1:out"; group = "headphones"; initial = "1"; }; systemd.services."speakers0" = trivmixService { name = "speakers0"; connectOut = "system:playback_7"; connectIn = "outnode0:out"; group = "speakers"; initial = "0"; }; systemd.services."speakers1" = trivmixService { name = "speakers1"; connectOut = "system:playback_8"; connectIn = "outnode1:out"; group = "speakers"; initial = "0"; }; services.mpd = { enable = true; musicDirectory = "/media/odin/music"; network.listenAddress = "any"; # Just so the module won't produce a bind_to_adress line extraConfig = '' bind_to_address "bragi.bragisheimr.yggdrasil" bind_to_address "bragi.asgard.yggdrasil" bind_to_address "localhost" bind_to_address "/var/lib/mpd/socket" audio_output { name "JACK" type "jack" client_name "mpd" destination_ports "mpdmix0:in,mpdmix1:in" } ''; user = "mpd"; group = "audio"; }; systemd.services."mpd".requires = [ "jack.service" "media-odin.mount" ]; systemd.services."mpd".serviceConfig = { LimitMEMLOCK = "infinity"; Nice = "-5"; LimitRTPRIO = lib.mkForce "95:95"; UMask = "0000"; }; users.extraUsers.jack = { name = "jack"; isSystemUser = true; group = "audio"; }; security.wrappers = { "mount.nfs".source = "${pkgs.nfs-utils}/bin/mount.nfs"; }; programs.bash.promptInit = '' PROMPT_COLOR="1;31m" return $UID && PROMPT_COLOR="1;32m" case "$TERM" in xterm*|rxvt*|kterm|aterm|gnome*) # Others can go here. PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] " if test "$TERM" = "xterm"; then PS1="\[\033]2;\h:\u:\w\007\]$PS1" fi ;; *) PS1="[\u@\h:\w]$ " ;; esac ''; networking.interfaces = { "enp1s0" = { useDHCP = false; ipAddress = "10.141.4.1"; prefixLength = 24; }; }; networking.nat = { enable = true; externalIP = "10.141.1.5"; externalInterface = "wlp4s0"; internalIPs = [ "10.141.4.0/24" ]; internalInterfaces = [ "enp1s0" ]; }; networking.firewall = { enable = true; allowPing = true; allowedTCPPorts = [ 22 # SSH 80 # HTTP 5432 # PostgreSQL 6600 # MPD 139 445 # SAMBA ]; allowedUDPPorts = [ 137 138 ]; # SAMBA allowedUDPPortRanges = [ { from = 60000; to = 61000; } # mosh ]; extraCommands = '' iptables -t nat -A POSTROUTING -o wlp4s0 -j MASQUERADE #iptables -A FORWARD -i wlp4s0 -o enp1s0 -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i wlp4s0 -o enp1s0 -j ACCEPT iptables -A FORWARD -i enp1s0 -o wlp4s0 -j ACCEPT ''; }; networking.defaultMailServer = { directDelivery = true; hostName = "ymir.niflheim.yggdrasil"; useSTARTTLS = true; setSendmail = true; }; networking.search = [ "bragisheimr.yggdrasil" "asgard.yggdrasil" ]; services.dhcpd4 = { enable = true; interfaces = [ "enp1s0" ]; extraConfig = '' option subnet-mask 255.255.255.0; option domain-name-servers 10.141.1.1, 8.8.8.8, 8.8.4.4; option domain-name "bragisheimr.yggdrasil"; option routers 10.141.4.1; subnet 10.141.4.0 netmask 255.255.255.0 { range 10.141.4.100 10.141.4.254; } group { use-host-decl-names on; host vali { hardware ethernet e0:cb:4e:f7:10:3d; fixed-address vali.bragisheimr.yggdrasil; } host printer { hardware ethernet 30:cd:a7:b0:55:8d; fixed-address printer.bragisheimr.yggdrasil; } } ''; }; services.samba = { enable = true; }; users.extraUsers.root = let template = (import users/gkleen.nix); in { inherit (template) shell; openssh.authorizedKeys.keyFiles = template.openssh.authorizedKeys.keyFiles; }; users.extraUsers."thermoprint" = { name = "thermoprint"; group = "lp"; isSystemUser = true; createHome = true; home = "/var/lib/thermoprint"; }; systemd.services."thermoprint" = { environment = { THERMOPRINT_CONFIG = ./bragi/thermoprint-server; THERMOPRINT_CACHE = ''${users.extraUsers."thermoprint".home}/dyre''; }; requires = [ "postgresql.service" ]; wantedBy = [ "default.target" ]; serviceConfig = { Type = "simple"; ExecStart = ''${pkgs.thermoprint-server}/bin/thermoprint-server --force-reconf''; User = users.extraUsers."thermoprint".name; Group = users.extraUsers."thermoprint".group; WorkingDirectory = "~"; }; }; systemd.services."thermoprint-webgui" = { wantedBy = [ "default.target" ]; serviceConfig = { Type = "simple"; ExecStart = ''${pkgs.thermoprint-webgui}/bin/thermoprint-webgui -P 80 -A localhost -F /thermoprint/api/ -a "localhost" -p 8081''; User = users.extraUsers."thermoprint".name; Group = users.extraUsers."thermoprint".group; WorkingDirectory = "~"; }; }; users.extraUsers."bar" = { name = "bar"; group = "nogroup"; isSystemUser = true; createHome = true; home = "/var/lib/bar"; }; systemd.services."bar" = let ghc = pkgs.haskellPackages.ghcWithPackages (p: with p; [yesod persistent-postgresql]); in { environment = { PORT = "8082"; HOST = "::1"; TPRINT_BASEURL = "http://localhost:80/thermoprint/api"; APPROOT = "/bar"; IP_FROM_HEADER = "true"; }; requires = [ "postgresql.service" ]; wantedBy = [ "default.target" ]; serviceConfig = { Type = "notify"; ExecStart = '' ${pkgs.callPackage ./bragi/bar {}}/bin/bar ''; User = users.extraUsers."bar".name; Group = users.extraUsers."bar".group; WorkingDirectory = "~"; }; }; services.nginx = { enable = true; httpConfig = '' default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $bytes_sent ' '"$http_referer" "$http_user_agent" ' '"$gzip_ratio"'; client_header_timeout 10m; client_body_timeout 10m; send_timeout 10m; connection_pool_size 256; client_header_buffer_size 1k; large_client_header_buffers 4 2k; request_pool_size 4k; gzip on; gzip_min_length 1100; gzip_buffers 4 8k; gzip_types text/plain; output_buffers 1 32k; postpone_output 1460; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 75 20; ignore_invalid_headers on; access_log stderr; error_log stderr; server { listen *:80; server_name _; location /thermoprint/api/ { proxy_pass http://[::1]:8080/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /thermoprint/ { proxy_pass http://localhost:8081/; } location /bar/ { proxy_pass http://[::1]:8082/; } } ''; }; services.postgresql = { enable = true; enableTCPIP = true; authentication = lib.mkForce '' local all all peer host all all 10.141.0.0/16 md5 ''; initialScript = pkgs.writeText "schema.sql" '' CREATE USER thermoprint; CREATE DATABASE thermoprint WITH OWNER = thermoprint; GRANT ALL ON DATABASE thermoprint TO thermoprint; CREATE USER bar; CREATE DATABASE bar WITH OWNER = bar; GRANT ALL ON DATABASE bar TO bar; ''; }; nix = { daemonIONiceLevel = 3; daemonNiceLevel = 10; gc = { automatic = true; }; autoOptimiseStore = true; }; system.autoUpgrade.enable = true; system.stateVersion = "16.09"; systemd.services."nixos-upgrade".path = with pkgs; [ git ]; systemd.services."nixos-upgrade".preStart = '' git -C /etc/nixos pull git -C /etc/nixos submodule update ''; systemd.status-mail = { recipient = "root@yggdrasil.li"; onFailure = [ "nixos-upgrade" ]; }; }