# Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). { config, pkgs, lib, ... }: { imports = [ # Include the results of the hardware scan. ./odin/hw.nix ./users.nix ./custom/uucp.nix ./custom/uucp-mediaserver.nix ./custom/borgbackup.nix ./custom/motion.nix ./custom/unit-status-mail.nix ./custom/zsh.nix ./custom/bar-service.nix ./custom/thermoprint-service.nix ./utils/nix/module.nix ]; # Use the GRUB 2 boot loader. boot.loader.grub.enable = true; boot.loader.grub.version = 2; # Define on which hard drive you want to install Grub. boot.loader.grub.device = "/dev/disk/by-id/ata-MKNSSDCR60GB_MK130619AS1031770"; boot.loader.grub.extraConfig = "serial; terminal_output.serial"; boot.kernelParams = [ "console=ttyS0,115200" ]; boot.extraTTYs = [ "tty7" ]; boot.initrd.network = { enable = true; ssh = { enable = true; authorizedKeys = [ (builtins.readFile ./users/keys/gkleen-hel-rsa.pub) ]; }; }; networking.hostName = "odin"; # Define your hostname. # Select internationalisation properties. i18n = { consoleKeyMap = "dvp"; defaultLocale = "en_US.UTF-8"; }; # Set your time zone. time.timeZone = "Europe/Berlin"; environment.systemPackages = with pkgs; [ tmux mosh quota git samba ntfs3g rebuild-system monitor-uucp ]; services.openssh = { enable = true; passwordAuthentication = false; challengeResponseAuthentication = false; extraConfig = '' AllowGroups ssh ''; }; users.groups."ssh" = { members = ["uucp" "root" "gitolite"]; }; networking.firewall = { enable = true; allowPing = true; allowedTCPPorts = [ 22 # ssh 80 443 # http 139 445 # samba 2010 2011 # notmuch-tcp 5001 # iperf 8022 # CSS VM ]; allowedUDPPorts = [ 137 138 # samba ]; allowedUDPPortRanges = [ { from = 60000; to = 61000; } # mosh ]; allowedTCPPortRanges = [ { from = 5900; to = 5910; } # VNC ]; }; users.extraUsers.root = let template = import ./users/gkleen.nix; in { inherit (template) shell; openssh.authorizedKeys.keyFiles = template.openssh.authorizedKeys.keyFiles; }; services.journald = { rateLimitBurst = 0; console = "/dev/tty7"; extraConfig = '' SystemMaxUse=1G ''; }; services.haveged.enable = true; services.uucp = { enable = true; nodeName = "odin"; remoteNodes = { "ymir" = { publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGANj+LJ4CI6VrAgBRocKCGq74kZnwD1PdKr/gdlfVr1 uucp@ymir"]; hostnames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"]; commands = ["rmail"]; }; "hel" = { publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKD8ycFGfVkBL9wjA5Kc33cl6Qt5K2505G/38oH8Cy/e uucp@hel"]; hostnames = ["hel.asgard.yggdrasil" "hel.faraday.asgard.yggdrasil" "hel.midgard.yggdrasil"]; commands = ["rmail" "recv"]; }; }; media-server = { enable = true; remoteNodes = [ "hel" ]; }; commandPath = [ "${pkgs.rmail}/bin" config.security.wrapperDir ]; }; programs.recv.enable = true; users.groups."media" = { members = [ "uucp" ]; }; services.postfix = { enable = true; enableSmtp = false; enableSubmission = false; setSendmail = true; networksStyle = "host"; hostname = "odin.asgard.yggdrasil"; recipientDelimiter = "+"; postmasterAlias = "gkleen"; rootAlias = "gkleen"; extraAliases = '' uucp: gkleen ''; virtual = '' @hel gkleen ''; destination = [ ''regexp:${pkgs.writeText "destination" '' /\.?localdomain$/ ACCEPT /^localhost$/ ACCEPT /\.?odin(\.asgard\.yggdrasil)?$/ ACCEPT ''} '' ]; config = { default_transport = "uucp:ymir"; message_size_limit = "0"; mailbox_size_limit = "0"; mail_spool_directory = "/srv/mail"; luser_relay = ''postmaster''${recipient_delimiter}''${local:unknown}''; }; masterConfig = { uucp = { type = "unix"; private = true; privileged = true; chroot = false; command = "pipe"; args = [ "flags=Fqhu" "user=uucp" ''argv=${config.security.wrapperDir}/uux -z -a $sender - $nexthop!rmail ($recipient)'' ]; }; }; networks = ["127.0.0.0/8" "[::ffff:127.0.0.0]/104" "[::1]/128" "10.141.0.0/16"]; }; services.borgbackup = { snapshots = "lvm"; prefix = "yggdrasil.asgard.odin."; targets = { "munin" = { repo = "borg.munin:borg"; paths = [ { VG = "raid6"; LV = "mail"; } { VG = "raid6"; LV = "home"; } { VG = "raid6"; LV = "media"; } { VG = "raid6"; LV = "root"; } { VG = "raid6"; LV = "git"; } { VG = "ssd-raid1"; LV = "root"; } ]; prune = lib.genAttrs [ "raid6-mail" "raid6-home" "raid6-media" "raid6-root" "raid6-git" "ssd-raid1-root" "home" "media" "mail" "root" # legacy ] (name: [ "--keep-within" "24H" "--keep-daily" "31" "--keep-monthly" "12" "--keep-yearly" "-1" ]); }; }; }; services.samba = { enable = true; shares = { homes = { comment = "Home Directories"; browseable = true; "valid users" = "%S"; writable = true; }; eos = { comment = "Disk image of eos"; browseable = true; "valid users" = "mherold"; writable = true; path = "/srv/eos"; }; media = { browseable = true; writable = false; path = "/srv/media"; "guest ok" = true; "guest only" = true; }; }; extraConfig = '' domain master = yes workgroup = ASGARD load printers = no printing = bsd printcap name = /dev/null disable spoolss = yes guest account = nobody ''; }; fileSystems."/srv/eos.lower" = { device = "/dev/disk/by-uuid/2A3052E73052BA11"; fsType = "ntfs-3g"; options = ["ro" "uid=1001" "gid=100" "fmask=0177" "dmask=0077" "permissions"]; }; systemd.mounts = [ { wantedBy = [ "samba-smbd.service" ]; before = [ "samba-smbd.service" ]; where = "/srv/eos"; what = "overlay"; type = "overlay"; options = lib.concatStringsSep "," [ "lowerdir=/srv/eos.lower" "upperdir=/home/mherold/.eos.upper" "workdir=/home/mherold/.eos.work" ]; unitConfig = { RequiresMountsFor = [ "/srv/eos.lower" "/home/mherold/.eos.upper" "/home/mherold/.eos.work" ]; }; } ]; services.motion = { cameras = [ { extraConfig = '' camera_name cat-food netcam_url mjpeg://ipcam01.hlidskjalf.yggdrasil:80/mjpeg.cgi netcam_keepalive on width 640 height 480 stream_port 8080 stream_localhost on despeckle_filter EedDl threshold_tune on noise_tune on lightswitch 50 minimum_motion_frames 5 ''; configFiles = [ "/etc/motion/cat-food.secret" ]; } { extraConfig = '' camera_name living-room netcam_url rtsp://ipcam02.hlidskjalf.yggdrasil:554/live1.sdp width 1920 height 1080 stream_port 8081 stream_localhost on stream_maxrate 1 text_double on despeckle_filter EedDl threshold 250 noise_tune on lightswitch 50 minimum_motion_frames 5 ''; configFiles = [ "/etc/motion/living-room.secret" ]; } ]; extraConfig = '' text_left "%$\n%F %T %Z" text_right "" text_changes off event_gap 20 output_pictures off ffmpeg_output_movies on ffmpeg_video_codec mkv ffmpeg_bps 500000 max_movie_time 600 target_dir /srv/hlidskjalf movie_filename %Y-%m-%d/%H-%M-%S.%$ stream_localhost off stream_auth_method 1 stream_quality 80 stream_maxrate 100 stream_motion on webcontrol_port 0 ipv6_enabled on ''; configFiles = [ "/etc/motion/motion.secret" ]; }; users.groups."hlidskjalf" = { members = [ "motion" "uucp" ]; }; virtualisation.libvirtd = { enable = true; }; services.rollingDirectories = [ { path = "/srv/hlidskjalf"; maxSize = "20Gi"; minSleep = 300; monitorTimeout = 3600; } ]; security.polkit = { enable = true; extraConfig = '' polkit.addRule(function(action, subject) { if ( action.id == "org.freedesktop.systemd1.manage-units" && subject.isInGroup("wheel") ) { return polkit.Result.YES; } }); ''; }; programs.ssh = { startAgent = true; agentTimeout = "1h"; }; nix = { daemonIONiceLevel = 3; daemonNiceLevel = 10; gc = { automatic = true; options = "--delete-older-than 21d"; }; autoOptimiseStore = true; }; services.smartd = { enable = true; autodetect = false; devices = map (id: { device = "/dev/disk/by-id/" + id; }) [ "ata-MKNSSDCR60GB_MK130620AS1032639" "ata-MKNSSDCR60GB_MK130619AS1031770" "ata-WDC_WD20EFRX-68AX9N0_WD-WMC301206808" "ata-WDC_WD20EFRX-68AX9N0_WD-WMC300900004" "ata-WDC_WD20EZRX-00D8PB0_WD-WMC4M0FA7MUY" "ata-WDC_WD20EARX-00PASB0_WD-WCAZA8424566" "ata-ST2000VN000-1HJ164_W7201QX1" "nvme-KINGSTON_SKC1000240G_50026B728204C4FC" ]; notifications = { mail.enable = true; wall.enable = true; }; defaults.monitored = "-a -n standby,10 -o on -s (S/../.././02|L/../../7/04)"; extraOptions = [ "--interval=600" "-A" "/var/log/smart/" "-s" "/var/lib/smart/" ]; }; systemd.services."iperf-tcp" = { wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.iperf2}/bin/iperf -sV"; }; }; systemd.services."iperf-udp" = { wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.iperf2}/bin/iperf -suV"; }; }; services.gitolite = { enable = true; adminPubkey = builtins.readFile (builtins.head (import ./users/gkleen.nix).openssh.authorizedKeys.keyFiles); dataDir = "/srv/git"; user = "gitolite"; group = "git"; enableGitAnnex = true; extraGitoliteRc = '' $RC{GIT_CONFIG_KEYS} = 'gitweb\.(owner|description|category)'; $RC{LOG_DEST} = 'syslog'; $RC{ROLES}{AUTHORS} = 1; $RC{GROUPLIST_PGM} = 'printf "@self-key-managers"'; $RC{HOSTNAME} = '${config.networking.hostName}'; $RC{LOCAL_CODE} = "$rc{GL_ADMIN_BASE}/local"; push(@{$RC{ENABLE}}, qw(create fork sskm D macros creator config fork option sudo writable update-description-file)); ''; }; services.postgresql = { enable = true; package = with pkgs; postgresql_11; enableTCPIP = true; authentication = lib.mkForce '' local all all peer host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256 host all all 10.141.0.0/16 scram-sha-256 ''; initialScript = pkgs.writeText "schema.sql" '' CREATE USER bar; CREATE DATABASE bar WITH OWNER = bar; GRANT ALL ON DATABASE bar TO bar; ''; }; # services.bar = { # enable = true; # port = 8082; # approot = "/bar"; # ipFromHeader = true; # }; services.nginx = { enable = true; recommendedOptimisation = true; recommendedGzipSettings = true; recommendedProxySettings = true; virtualHosts."odin.asgard.yggdrasil" = { serverAliases = [ "odin" "10.141.1.2" ]; forceSSL = true; sslCertificate = /var/lib/ssl/self-signed-cert.pem; sslCertificateKey = /var/lib/ssl/self-signed-key.pem; locations = { # "/bar".proxyPass = "http://bar/"; "/".extraConfig = '' return 302 /grafana/; ''; "/motion/cat-food.mjpeg".proxyPass = "http://localhost:8080/"; "/motion/living-room.mjpeg".proxyPass = "http://localhost:8081/"; "/prometheus" = { extraConfig = '' auth_basic "Yggdrasil"; auth_basic_user_file /etc/yggdrasil.htpasswd; ''; proxyPass = "http://prometheus"; }; "= /grafana".extraConfig = "return 302 /grafana/;"; "/grafana/".proxyPass = "http://grafana/"; }; }; upstreams = { # "bar" = { # servers."localhost:${toString config.services.bar.port}"= {}; # }; "prometheus" = { servers."${config.services.prometheus.listenAddress}" = {}; }; "grafana" = { servers."localhost:${toString config.services.grafana.port}" = {}; }; }; }; users.groups.ssl = {}; users.users.nginx.extraGroups = ["ssl"]; services.prometheus = { enable = true; webExternalUrl = "http://odin.asgard.yggdrasil/prometheus"; listenAddress = "localhost:9090"; exporters = { node = { enable = true; listenAddress = "localhost"; enabledCollectors = [ "logind" "systemd" "processes" ]; }; }; globalConfig = { scrape_interval = "5s"; scrape_timeout = "5s"; }; scrapeConfigs = [ { job_name = "router"; static_configs = [ { targets = [ "heimdallr:9133" ]; } ]; } { job_name = "odin"; static_configs = [ { targets = [ "localhost:9100" ]; } ]; } { job_name = "prometheus"; metrics_path = "/prometheus/metrics"; static_configs = [ { targets = [ "localhost:9090" ]; } ]; } ]; }; services.grafana = { enable = true; addr = "localhost"; domain = "odin.asgard.yggdrasil"; port = 9089; protocol = "http"; rootUrl = "%(protocol)s://%(domain)s:%(http_port)s/grafana"; smtp = { enable = true; fromAddress = "grafana@odin.asgard.yggdrasil"; }; }; systemd.status-mail = { recipient = "root@odin.asgard.yggdrasil"; onFailure = [ "nixos-upgrade" "smartd" ]; }; system.autoUpgrade.enable = true; system.stateVersion = "18.09"; systemd.services."nixos-upgrade" = { path = with pkgs; [ git ]; preStart = '' git -C /etc/nixos pull --recurse-submodules ''; }; }