diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..87a30187 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +result +*.qcow2 diff --git a/.gitmodules b/.gitmodules index 176bb4c7..706acf36 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,9 @@ -[submodule "pkgs/home-manager"] - path = pkgs/home-manager - url = https://github.com/rycee/home-manager - branch = release-17.09 +[submodule "secret"] + path = secret + url = ../config-secret +[submodule "nixpkgs"] + path = nixpkgs + url = git@github.com:kierdavis/nixpkgs.git +[submodule "kak/thirdparty/fzf.kak"] + path = kak/thirdparty/fzf.kak + url = git@github.com:andreyorst/fzf.kak diff --git a/bash_profile b/bash_profile new file mode 100644 index 00000000..03e77eaa --- /dev/null +++ b/bash_profile @@ -0,0 +1,63 @@ +alias g='git' + +alias ga='git add' +alias gaa='git add --all' +alias gapa='git add --patch' +alias gau='git add --update' +alias gav='git add --verbose' +alias gap='git apply' + +alias gb='git branch' +alias gba='git branch -a' +alias gbd='git branch -d' +alias gbda='git branch --no-color --merged | command grep -vE "^(\*|\s*(master|develop|dev)\s*$)" | command xargs -n 1 git branch -d' +alias gbD='git branch -D' +alias gbl='git blame -b -w' +alias gbnm='git branch --no-merged' +alias gbr='git branch --remote' +alias gbs='git bisect' +alias gbsb='git bisect bad' +alias gbsg='git bisect good' +alias gbsr='git bisect reset' +alias gbss='git bisect start' + +alias gc='git commit -v' +alias gc!='git commit -v --amend' +alias gcn!='git commit -v --no-edit --amend' +alias gca='git commit -v -a' +alias gca!='git commit -v -a --amend' +alias gcan!='git commit -v -a --no-edit --amend' +alias gcans!='git commit -v -a -s --no-edit --amend' +alias gcam='git commit -a -m' +alias gcsm='git commit -s -m' +alias gcb='git checkout -b' +alias gcf='git config --list' +alias gcl='git clone --recurse-submodules' +alias gclean='git clean -id' +alias gpristine='git reset --hard && git clean -dfx' +alias gcm='git checkout master' +alias gcd='git checkout develop' +alias gcmsg='git commit -m' +alias gco='git checkout' +alias gcount='git shortlog -sn' +alias gcp='git cherry-pick' +alias gcpa='git cherry-pick --abort' +alias gcpc='git cherry-pick --continue' +alias gcs='git commit -S' + +alias gd='git diff' +alias gdca='git diff --cached' +alias gdcw='git diff --cached --word-diff' +alias gdct='git describe --tags $(git rev-list --tags --max-count=1)' +alias gds='git diff --staged' +alias gdt='git diff-tree --no-commit-id --name-only -r' +alias gdw='git diff --word-diff' + +alias gf='git fetch' +alias gfa='git fetch --all --prune' +alias gfo='git fetch origin' + +alias gfg='git ls-files | grep' + +alias gg='git gui citool' +alias gga='git gui citool --amend' diff --git a/beets b/beets index 4f6427ab..09d00fbd 100644 --- a/beets +++ b/beets @@ -1,7 +1,7 @@ # order same as in docs (http://beets.readthedocs.io/en/v1.4.1/reference/config.html) -library: /mnt/nocturn/music/beets/database.db -directory: /mnt/nocturn/music/library -plugins: convert edit embedart fetchart play replaygain +library: /srv/beets/database.db +directory: /data/music/library +plugins: convert edit embedart fetchart replaygain asciify_paths: no # explicit done in path formats instead import: write: yes @@ -13,11 +13,11 @@ import: quiet_fallback: skip none_rec_action: ask timid: yes - log: /mnt/nocturn/music/beets/import.log + log: /srv/beets/import.log default_action: apply languages: [en] detail: yes - group_albums: yes + group_albums: no autotag: yes duplicate_action: ask musicbrainz: @@ -34,7 +34,8 @@ edit: ## fetchart plugin fetchart: - auto: no + auto: yes + cautious: yes ## play plugin play: diff --git a/git b/git index daa0a89b..83391b3f 100644 --- a/git +++ b/git @@ -1,8 +1,19 @@ [user] - email = kierdavis@gmail.com + email = me@kierdavis.com name = Kier Davis - signingkey = E9EFA7E77400759DA6ADB9E08139C5FCEDA73ABF + signingKey = 66378DA35FF9F0FA! [commit] gpgSign = true [gpg] - program = /run/current-system/sw/bin/gpg2 + program = gpg +[core] + editor = /run/current-system/sw/bin/kak + excludesfile = /home/kier/.gitignore +[merge] + conflictStyle = diff3 +[pull] + rebase = true +[diff] + algorithm = minimal +[init] + defaultBranch = main diff --git a/gitignore b/gitignore new file mode 100644 index 00000000..1d1e70ec --- /dev/null +++ b/gitignore @@ -0,0 +1 @@ +*.nogit diff --git a/hist.nix b/hist.nix new file mode 100644 index 00000000..b6819efe --- /dev/null +++ b/hist.nix @@ -0,0 +1,95 @@ +let + lib = import ; + + withCIDR6 = network: network // { + cidr = "${network.prefix}::/${builtins.toString network.prefixLength}"; + }; + withCIDR4 = network: network // { + cidr = "${network.prefix}.0/${builtins.toString network.prefixLength}"; + }; + +in rec { + wgPort = 9509; + upstreamNameServers = [ "1.1.1.1" "1.0.0.1" ]; + + networks = { + lan = withCIDR4 { + prefix = "192.168.178"; + prefixLength = 24; + mask = "255.255.255.0"; # TODO: easy way to compute this from prefixLength? + }; + wg = withCIDR6 { + prefix = "fdec:affb:e11e:1"; + prefixLength = 64; + }; + ptolemyGuests = withCIDR6 { + prefix = "fdec:affb:e11e:2"; + prefixLength = 64; + }; + ptolemyGuests4 = withCIDR4 rec { + prefix = "192.168.102"; + prefixLength = 24; + mask = "255.255.255.0"; # TODO: easy way to compute this from prefixLength? + dhcp = { + first = "${prefix}.20"; + last = "${prefix}.254"; + }; + }; + pointToPoint = withCIDR4 rec { + prefix = "192.168.103"; + prefixLength = 24; + mask = "255.255.255.0"; # TODO: easy way to compute this from prefixLength? + }; + }; + + hosts = { + ptolemy = { + addresses = rec { + wg = "${networks.wg.prefix}::1"; + ptolemyGuests = "${networks.ptolemyGuests.prefix}::1"; + ptolemyGuests4 = "${networks.ptolemyGuests4.prefix}.1"; + default.public = "192.168.1.27"; # Hack until installed in DC. + default.private = wg; + }; + wgGatewayTo = [ + networks.ptolemyGuests.cidr + networks.ptolemyGuests4.cidr + ]; + publicKey = "fUn4jHh1QLmuGZ1qNMI0nPMXAfqos7xMMTzFQHDw/0Q="; + }; + fingerbib = { + addresses = rec { + lan = "${networks.lan.prefix}.3"; + wg = "${networks.wg.prefix}::3"; + default.public = lan; + default.private = wg; + }; + publicKey = "s3AsWEhK5Zp+YIoWYIm/p2ESquPS7h3OSKQ7SXeIElg="; + virtualHosts = [ "fingerbib-icinga" "media" "printing" "torrents" ]; + }; + coloris = { + addresses = rec { + wg = "${networks.wg.prefix}::2"; + default.private = wg; + }; + publicKey = "1cxw/cG2D/+VDtb65q/R3H5XfIQr/k820+8Uz4Vqvz8="; + }; + saelli = { + addresses = rec { + wg = "${networks.wg.prefix}::4"; + default.private = wg; + }; + publicKey = "mjplz2S5i8HvSFOVSyYpn6SLLipMWMGGf08Ld1VP3U8="; + }; + }; + + dns = let + defaultEntryForHost = hostName: hostData: [{ name = hostName; address = hostData.addresses.default.private; }]; + virtualEntriesForHost = hostName: hostData: builtins.map (name: { inherit name; address = hostData.addresses.default.private; }) (hostData.virtualHosts or []); + interfaceEntriesForHost = hostName: hostData: lib.mapAttrsToList (intfName: address: { name = "${intfName}.${hostName}"; inherit address; }) (removeAttrs hostData.addresses ["default"]); + entriesForHost = hostName: hostData: lib.concatMap (fun: fun hostName hostData) [defaultEntryForHost virtualEntriesForHost interfaceEntriesForHost]; + entriesForHosts = lib.flatten (lib.mapAttrsToList entriesForHost hosts); + entries = entriesForHosts; + appendDomain = entry: entry // { name = "${entry.name}.hist"; }; + in lib.concatMap (entry: [(appendDomain entry) entry]) entries; +} diff --git a/i3 b/i3 index 564d4162..d01c9575 100644 --- a/i3 +++ b/i3 @@ -97,6 +97,8 @@ bindsym $mod+7 workspace 7 bindsym $mod+8 workspace 8 bindsym $mod+9 workspace 9 bindsym $mod+0 workspace 10 +bindsym $mod+Ctrl+Left workspace prev +bindsym $mod+Ctrl+Right workspace next # move focused container to workspace bindsym $mod+Shift+1 move container to workspace 1 @@ -117,10 +119,7 @@ bindsym $mod+Shift+r restart # exit i3 (logs you out of your X session) #bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" -bindsym Print exec /run/current-system/sw/bin/screenshot -bindsym XF86AudioRaiseVolume exec pactl set-sink-volume alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.iec958-stereo +5% -bindsym XF86AudioLowerVolume exec pactl set-sink-volume alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.iec958-stereo -5% -bindsym XF86AudioMute exec pactl set-sink-mute alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.iec958-stereo toggle +bindsym $mod+Print exec /run/current-system/sw/bin/screenshot bindsym $mod+l exec i3lock @@ -168,12 +167,12 @@ mode $POWERMODE { set $APPMODE "Web Editor Irc Signal Music Volume_control | cancel(Q)" bindsym $mod+q mode $APPMODE mode $APPMODE { - bindsym w exec chromium, mode default + bindsym w exec google-chrome-stable, mode default bindsym $mod+w exec chromium --incognito, mode default bindsym e exec sublime, mode default bindsym $mod+e exec sublime --new-window, mode default bindsym i exec quasselclient, mode default - bindsym s exec chromium --profile-directory=Default --app-id=bikioccmkafdpakkkcpdbppfkghcmihk, mode default + bindsym s exec signal-desktop, mode default bindsym m exec terminator, mode default bindsym v exec pavucontrol, mode default bindsym q mode default diff --git a/k8s-ca.pem b/k8s-ca.pem new file mode 100644 index 00000000..de1afa93 --- /dev/null +++ b/k8s-ca.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICyDCCAbCgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl +cm5ldGVzMB4XDTE5MDkyNzE2MzI0OVoXDTI5MDkyNDE2MzI0OVowFTETMBEGA1UE +AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANEO +S5zBwgT1rZjJc4o/lFsjNkqfgW/pDtZcUo0Lq69sSa35TZKj45qdWyrszjLVcp8o +jVuRf/WK37tchW/F+9f2fo0BE4ASinWH4vTkufBHjDxCTi+9dVygzBLZ/6zVKetz +Od5yoiBWCwlskOBeSN1yMZ8W9nRkgRU23Kg7x511b941q4VYV5xKivmdQygI/L5O +dF1Rml8Y2cprs6G35lBl1JhT1oqb3hHAbzwbau3oVsLxx+RabWFGQSGhiHIIZlS1 +E7eXTy8cfcHpMrt2VFG5WMfM15jH69mlz4sV/YB/JN3Vbsy6lu8BId9Yq4cT+sWS +yZ0uxKDe8rpzoRyb1lsCAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKb656+5wJN5OgA46zTYRKCz2jC5 +cFnlN/VQHCW/wle9ezytZzm2MnH3hu4N/lmeFD7skxmtwk4fxbp5rJs22UbOPjPq +EzcXMco412i+QIgz/rd/TXHwysiIbsRRHiVIPJWHAmrkgt7w00ts4H6hMq/+EzoO +oS/RnRAThc/ZkAjdGnDw0Su2x4gim49oaPibDlhd6vfIk9BSZ7sjVcMxIjHoIG3j +f72Uu6OnvlyNZVi122vR8qrZ4byihp5qqSOzv6NLHJ3LM635oPOEqX6mi5M3MS8p +NGRl10+ZWonV9mz5HiCUTSt5nrROnB1ocXNaoaTpixYekMq2xcsrz+Jgems= +-----END CERTIFICATE----- diff --git a/k8s-secret-generator.nix b/k8s-secret-generator.nix new file mode 100644 index 00000000..e463dd6b --- /dev/null +++ b/k8s-secret-generator.nix @@ -0,0 +1,69 @@ +with import {}; + +let + network = import ./network.nix; + passwords = import ./secret/passwords.nix; + + mkYamlVal = value: if value ? fromFile then + "$(base64 --wrap=0 <${value.fromFile})" + else + abort "secret value must define fromFile"; + + mkYaml = { name, namespace, entries }: runCommand "${namespace}.${name}.yaml" {} '' + cat >$out <> $out + echo '---' >> $out + done + ''; + + syncScript = writeShellScript "sync-k8s-secrets" '' + exec ${kubectl}/bin/kubectl apply -f ${combinedYaml} + ''; + }; + +in things.syncScript // things diff --git a/kak/kakrc b/kak/kakrc new file mode 100644 index 00000000..e7968b76 --- /dev/null +++ b/kak/kakrc @@ -0,0 +1,37 @@ +hook global InsertChar \t %{ try %{ + execute-keys -draft "h\A\h+\z;%opt{indentwidth}@" +}} +hook global InsertDelete ' ' %{ try %{ + execute-keys -draft 'h\A\h+\zi' +}} +hook global InsertCompletionShow .* %{ + try %{ + # this command temporarily removes cursors preceded by whitespace; + # if there are no cursors left, it raises an error, does not + # continue to execute the mapping commands, and the error is eaten + # by the `try` command so no warning appears. + execute-keys -draft 'h\h' + map window insert + map window insert + } +} +hook global InsertCompletionHide .* %{ + unmap window insert + unmap window insert +} +set-option global indentwidth 2 + +source "%val{config}/thirdparty/fzf.kak/rc/fzf.kak" +source "%val{config}/thirdparty/fzf.kak/rc/modules/fzf-file.kak" +source "%val{config}/thirdparty/fzf.kak/rc/modules/fzf-buffer.kak" +source "%val{config}/thirdparty/fzf.kak/rc/modules/fzf-search.kak" +source "%val{config}/thirdparty/fzf.kak/rc/modules/fzf-cd.kak" +map global normal ': fzf-mode' + +hook global BufCreate .*[.](pyi) %{ + set-option buffer filetype python +} + +hook global WinSetOption filetype=lua %{ + remove-hooks window lua-insert +} diff --git a/kak/thirdparty/fzf.kak b/kak/thirdparty/fzf.kak new file mode 160000 index 00000000..b2aeb264 --- /dev/null +++ b/kak/thirdparty/fzf.kak @@ -0,0 +1 @@ +Subproject commit b2aeb26473962ab0bf3b51ba5c81c50c1d8253d3 diff --git a/network.nix b/network.nix new file mode 100644 index 00000000..30aef8fb --- /dev/null +++ b/network.nix @@ -0,0 +1,30 @@ +let + lib = (import {}).lib; + + mkA = name: address: { type = "A"; inherit name address; }; + mkAAAA = name: address: { type = "AAAA"; inherit name address; }; + mkCNAME = name: targetName: { type = "CNAME"; inherit name targetName; }; + mkNet = name: address: prefixLength: { + type = "net"; + inherit name address prefixLength; + cidr = "${address}/${builtins.toString prefixLength}"; + }; + +in rec { + records = [ + # Public address space + (mkA "pub4.beagle2.cascade" "176.9.121.81") + + # Kubenetes VPN address space + (mkNet "k8s.network.cascade" "172.27.0.0" 16) + (mkA "k8s.beagle2.cascade" "172.27.0.1") + (mkA "k8s.saelli.cascade" "172.27.128.1") + (mkA "k8s.coloris.cascade" "172.27.128.2") + (mkA "k8s.pixel4-202007.cascade" "172.27.128.3") + (mkA "k8s.coloris-win.cascade" "172.27.128.4") + + # Aliases to default interfaces. + ]; + + byName = builtins.listToAttrs (map (record: { name = record.name; value = record; }) records); +} diff --git a/nixos/.gitignore b/nixos/.gitignore deleted file mode 100644 index 89b3a77d..00000000 --- a/nixos/.gitignore +++ /dev/null @@ -1 +0,0 @@ -secrets.nix diff --git a/nixos/common/apps.nix b/nixos/common/apps.nix index b4331628..e0ab5479 100644 --- a/nixos/common/apps.nix +++ b/nixos/common/apps.nix @@ -1,57 +1,106 @@ { config, lib, pkgs, ... }: let - localPkgs = import ../../pkgs pkgs; - - mkWake = name: mac: localPkgs.writeScriptBin "wake-${name}" '' - #!${localPkgs.stdenv.shell} - ${localPkgs.wakelan}/bin/wakelan ${mac} + nixos-rebuild-remote = pkgs.writeShellScriptBin "nixos-rebuild-remote" '' + set -o errexit -o nounset -o pipefail + host="$1" + shift + ping -c1 "$host" + ssh_dir=/home/kier/.ssh + ssh_key=$ssh_dir/$(ls $ssh_dir | grep -E '^id_(rsa|ed25519)$') + exec nixos-rebuild --builders "ssh://nixremotebuild@$host - $ssh_key 4 - big-parallel" --max-jobs 0 "$@" ''; in { - # sudo - security.sudo.enable = true; - security.sudo.wheelNeedsPassword = true; - - # tmux - programs.tmux.enable = true; - # bash completion programs.bash.enableCompletion = true; - # NixOS manual - services.nixosManual.enable = true; + # documentation + documentation = { + enable = true; + nixos.enable = lib.mkOverride 500 true; + dev.enable = false; + + # Types of documentation + man.enable = true; + info.enable = true; + doc.enable = false; # anything that doesn't fall into the above two categories + }; + + programs.tmux = { + enable = true; + escapeTime = 0; + extraConfig = '' + # There was some issue with Home and End keys not working properly, and this fixed it: + bind-key -n Home send Escape "OH" + bind-key -n End send Escape "OF" - environment.systemPackages = with localPkgs; [ + # When creating new panes or windows, use the same working directory as the currently selected pane instead of defaulting to $HOME. + bind '"' split-window -c "#{pane_current_path}" + bind % split-window -h -c "#{pane_current_path}" + bind c new-window # -c "#{pane_current_path}" + + # This key did something really annoying (move current pane into its own window, perhaps) and I kept hitting it by mistake: + unbind ! + ''; + }; + + # other programs + programs.iotop.enable = true; + programs.less.enable = true; + programs.traceroute.enable = true; + environment.systemPackages = with pkgs; [ + # Utilities bc - beets file + fzf git - gnupg - htop + gptfdisk + jq + kakoune manpages mountext - nmap - pass - passchars + ncdu + nixos-rebuild-remote pbzip2 pigz - publish + psmisc # provides killall pv - python27Packages.youtube-dl - soton-mount - soton-umount + ripgrep + screen + sshfs + tree umountext - usbutils # lsusb unzip wget zip - (mkWake "coloris" "34:97:f6:34:19:3f") - (mkWake "nocturn" "00:26:b9:bf:1f:52") - (mkWake "htpc" "d4:3d:7e:ef:5c:e5") + # System diagnostics + dnsutils # dig + fping + htop + lshw + lsof + nmap + pciutils # lspci + sysstat # iostat + tcpdump + usbutils # lsusb + + # Security + gnupg + pass + passchars + pinentry-curses ]; - environment.variables.PKGS = "/nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/top-level/all-packages.nix"; - environment.variables.MY_GPG_KEY = "E9EFA7E77400759DA6ADB9E08139C5FCEDA73ABF"; + programs.command-not-found = { + enable = true; + dbPath = pkgs.runCommandLocal "programs.sqlite" { + channelTarball = builtins.fetchurl "https://nixos.org/channels/nixos-unstable/nixexprs.tar.xz"; + } '' + tar --wildcards -xJf $channelTarball '*/programs.sqlite' + install -m 0644 */programs.sqlite $out + ''; + }; } diff --git a/nixos/common/boot.nix b/nixos/common/boot.nix index f278a9e7..1025bdcf 100644 --- a/nixos/common/boot.nix +++ b/nixos/common/boot.nix @@ -2,12 +2,11 @@ { boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; - hardware.enableAllFirmware = true; - - # Plymouth splash screen. - boot.plymouth.enable = false; + hardware.enableAllFirmware = false; # Microcode updates hardware.cpu.intel.updateMicrocode = config.machine.cpu.intel; + + # Enable all magic sysrq keys (by default, only sync is enabled). + boot.kernel.sysctl."kernel.sysrq" = 1; } diff --git a/nixos/common/bugfixes.nix b/nixos/common/bugfixes.nix new file mode 100644 index 00000000..bce3cad6 --- /dev/null +++ b/nixos/common/bugfixes.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, ... }: + +let + pkgs1 = import (pkgs.fetchFromGitHub { + owner = "NixOS"; + repo = "nixpkgs"; + rev = "eb7e1ef185f6c990cda5f71fdc4fb02e76ab06d5"; + hash = "sha256:1ibz204c41g7baqga2iaj11yz9l75cfdylkiqjnk5igm81ivivxg"; + }) {}; +in + +{ + nixpkgs.overlays = [(self: super: { + # Doesn't work in current release. + inherit (pkgs1) freecad; + + # Set cwd for boincmgr to the boinc data dir, so that it has no trouble finding the gui rpc password file. + boinc = super.boinc.overrideDerivation (oldAttrs: { + nativeBuildInputs = (if oldAttrs ? nativeBuildInputs then oldAttrs.nativeBuildInputs else []) ++ [ self.makeWrapper ]; + preFixup = '' + ${if oldAttrs ? preFixup then oldAttrs.preFixup else ""} + if [[ -e $out/bin/boincmgr ]]; then + wrapProgram $out/bin/boincmgr --run 'cd ''${BOINC_DATA_DIR:-${config.services.boinc.dataDir}}' + fi + ''; + # Hide warnings when compiling. + NIX_CFLAGS_COMPILE = (if oldAttrs ? NIX_CFLAGS_COMPILE then oldAttrs.NIX_CFLAGS_COMPILE else []) ++ [ "-w" ]; + }); + + # Fix hardcoded filenames, and expectation of xinit being on PATH. + tigervnc = super.tigervnc.overrideDerivation (oldAttrs: { + preFixup = '' + substituteInPlace $out/bin/.vncserver-wrapped \ + --replace /etc/X11/xinit/Xsession '$ENV{XSESSION}' \ + --replace /usr/share/xsessions '$ENV{XSESSIONS_DIR}' \ + --replace '$vncUserDir/config' '$ENV{CONFIG}' + wrapProgram $out/bin/.vncserver-wrapped \ + --prefix PATH : ${lib.makeBinPath [pkgs.xorg.xinit]} \ + --set-default XSESSION ${config.services.xserver.displayManager.sessionData.wrapper} \ + --set-default XSESSIONS_DIR /usr/share/xsessions \ + --set-default CONFIG '$HOME/.vnc/config' + ${oldAttrs.preFixup or ""} + ''; + }); + + # --podman isn't available in any release yet. + x11docker = super.x11docker.overrideDerivation (oldAttrs: { + version = "6.6.2-unstable"; + src = self.fetchFromGitHub { + owner = "mviereck"; + repo = "x11docker"; + rev = "0d5537c31d4e5202cd6d57565fc234541659fdc2"; + sha256 = "0fjh5c7fiwmfav2x7lxs5gpql97ad0annh93w00qdqjpik0yvwif"; + }; + }); + })]; + + # If podman detects its storage is backed by zfs, it will try to use the + # zfs admin commands to manage container volumes. These aren't in + # podman's PATH by default. + virtualisation.podman.extraPackages = lib.optional (builtins.elem "zfs" config.boot.supportedFilesystems) pkgs.zfs; + + # The intention of restartIfChanged=false is to avoid killing user sessions when restarting the service. + # But, xrdp-sesman already handles this safely - upon receiving SIGINT it waits for all sessions to be terminated before exiting. + systemd.services.xrdp-sesman.restartIfChanged = lib.mkForce true; +} diff --git a/nixos/common/default.nix b/nixos/common/default.nix index 0666c8d6..7987ebe7 100644 --- a/nixos/common/default.nix +++ b/nixos/common/default.nix @@ -2,16 +2,21 @@ imports = [ ./apps.nix ./boot.nix + ./bugfixes.nix + ./env.nix ./fs.nix + ./hardware.nix ./locale.nix ./net.nix ./nix.nix ./options.nix - ./print.nix ./services.nix ./users.nix ]; # The NixOS release to be compatible with for stateful data such as databases. - system.stateVersion = "16.09"; + system.stateVersion = "18.09"; + + # Root SSL cert. + security.pki.certificateFiles = [ ../../ssl-ca.pem ]; } diff --git a/nixos/common/env.nix b/nixos/common/env.nix new file mode 100644 index 00000000..81ca6b21 --- /dev/null +++ b/nixos/common/env.nix @@ -0,0 +1,14 @@ +{ config, lib, pkgs, ... }: + +{ + environment.variables = { + GPG_MASTER_KEY = "8139C5FCEDA73ABF"; + GPG_ENCRYPTION_KEY = "DFDCA524B0742D62"; + GPG_GIT_SIGNING_KEY = "66378DA35FF9F0FA"; + GPG_BACKUP_SIGNING_KEY = "EC1301FD757E43F7"; + + TMUX_TMPDIR = lib.mkForce "/tmp"; + + EDITOR = "kak"; + }; +} diff --git a/nixos/common/fs.nix b/nixos/common/fs.nix index 362d42b4..b135f474 100644 --- a/nixos/common/fs.nix +++ b/nixos/common/fs.nix @@ -1,21 +1,15 @@ { config, lib, pkgs, ... }: { - fileSystems."/" = { - device = config.machine.fsdevices.root; - fsType = "ext4"; - options = ["noatime" "nodiratime"]; - }; - - swapDevices = - [ { device = config.machine.fsdevices.swap; } - ]; - # mount a tmpfs on /tmp - boot.tmpOnTmpfs = true; + boot.tmpOnTmpfs = lib.mkDefault true; - # Don't forcibly import non-root ZFS pools during boot. - boot.zfs.forceImportAll = false; + # Don't forcibly import ZFS pools during boot. + boot.zfs = { + forceImportAll = false; + forceImportRoot = false; + }; + boot.loader.grub.zfsSupport = true; # # ZFS auto-snapshotting # services.zfs.autoSnapshot = { @@ -39,9 +33,11 @@ # See 'man hdparm'. # Generally, -S n means n*5 seconds. services.udev.extraRules = '' - KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", RUN+="${pkgs.hdparm}/bin/hdparm -B 200 -S 60 /dev/%k" + KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", RUN+="${pkgs.hdparm}/bin/hdparm -B 254 -S 0 /dev/%k" ''; # By default this is in /etc, which is not very NixOS-friendly. environment.variables.LVM_SYSTEM_DIR = "/var/lvm"; + + # boot.supportedFilesystems = ["nfs"]; } diff --git a/nixos/common/hardware.nix b/nixos/common/hardware.nix new file mode 100644 index 00000000..d3e102e5 --- /dev/null +++ b/nixos/common/hardware.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, ... }: + +{ + services.udev.extraRules = '' + # Teensy stuff from https://www.pjrc.com/teensy/00-teensy.rules + ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04*", ENV{ID_MM_DEVICE_IGNORE}="1", ENV{ID_MM_PORT_IGNORE}="1" + ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789a]*", ENV{MTP_NO_PROBE}="1" + KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04*", RUN:="${pkgs.coreutils}/bin/stty -F /dev/%k raw -echo" + + # 3D printer + ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="geeetech-prusa-i3" + ''; +} diff --git a/nixos/common/locale.nix b/nixos/common/locale.nix index 53fcd62a..cc7b2d72 100644 --- a/nixos/common/locale.nix +++ b/nixos/common/locale.nix @@ -5,12 +5,18 @@ i18n.defaultLocale = "en_GB.UTF-8"; # Console font. - i18n.consoleFont = "Lat2-Terminus16"; + console.font = "Lat2-Terminus16"; # Keyboard layout. - i18n.consoleKeyMap = "uk"; + console.keyMap = "uk"; services.xserver.layout = "gb"; # Time zone. time.timeZone = "Europe/London"; + + # Location (used by redshift). + location = { + latitude = 50.92; + longitude = -1.39; + }; } diff --git a/nixos/common/net.nix b/nixos/common/net.nix index 4abf5e4e..995f6865 100644 --- a/nixos/common/net.nix +++ b/nixos/common/net.nix @@ -1,23 +1,73 @@ -{ config, ... }: +{ config, pkgs, lib, ... }: + +let + hist = import ../../hist.nix; + passwords = import ../../secret/passwords.nix; +in { networking.hostName = config.machine.name; - networking.hostId = config.machine.hostId; # Necessary for ZFS. This is just a random 32-bit integer. + networking.domain = "hist"; + + networking.iproute2.enable = true; # Firewall - networking.firewall.enable = true; + networking.firewall.enable = lib.mkDefault true; networking.firewall.allowPing = true; + # Debugging: + networking.firewall.logReversePathDrops = true; + # Allow the 'gre' (Generic Routing Encapsulation) IP protocol. # The Windows PPTP VPN client uses this; if it is run in a VM, its traffic will still need to go through this firewall. #networking.firewall.extraCommands = "ip46tables -A nixos-fw -p gre -j nixos-fw-accept"; # Bluetooth - hardware.bluetooth.enable = config.machine.bluetooth; + # bluetoothctl doesn't seem to work properly on any of my machines... + hardware.bluetooth.enable = false; + + # When forwarding a port from a host to a container using systemd-nspawn, this setting is + # required in order to make the port accessible from other machine's on the host's network. + # https://docs.docker.com/v17.09/engine/userguide/networking/default_network/container-communication/#communicating-to-the-outside-world + boot.kernel.sysctl."net.ipv4.conf.all.forwarding" = true; + + # Local DNS server. + #services.unbound = { + # enable = true; + # interfaces = [ "127.0.0.1" "::1" ]; + # allowedAccess = [ "127.0.0.1/32" "::1/128" ]; + # forwardAddresses = network.upstreamNameservers; + # extraConfig = let + # serialiseRecord = record: if record.type == "A" || record.type == "AAAA" + # then ''local-data: "${record.name}. IN ${record.type} ${record.address}"'' + # else if record.type == "CNAME" + # then ''local-sata: "${record.name}. IN CNAME ${record.targetName}"'' + # else ""; + # in '' + # local-zone: "cascade." static + # ${lib.concatStringsSep "\n" (map serialiseRecord network.records)} + # ''; + #}; + #networking.nameservers = [ "::1" ]; + + networking.wireguard = { + enable = true; + interfaces.wg-hist = let + localAddr = hist.hosts."${config.machine.name}".addresses.wg; + prefixLength = hist.networks.wg.prefixLength; + in { + ips = ["${localAddr}/${builtins.toString prefixLength}"]; + listenPort = hist.wgPort; + privateKeyFile = "/etc/wg-hist.key"; + peers = lib.mapAttrsToList (peerName: peer: { + inherit (peer) publicKey; + allowedIPs = ["${peer.addresses.wg}/128"] ++ (peer.wgGatewayTo or []); + endpoint = if peer ? addresses.default.public then "${peer.addresses.default.public}:${builtins.toString hist.wgPort}" else null; + persistentKeepalive = 25; + }) (lib.filterAttrs (peerName: peerInfo: peerName != config.machine.name && peerInfo ? addresses.wg) hist.hosts); + }; + }; + networking.firewall.allowedUDPPorts = [ hist.wgPort ]; - # /etc/hosts - networking.extraHosts = '' - 176.9.121.81 beagle2 - 81.106.244.140 soton - ''; + networking.hosts = lib.groupBy' (names: entry: names ++ [entry.name]) [] (entry: entry.address) hist.dns; } diff --git a/nixos/common/nix.nix b/nixos/common/nix.nix index e701415c..2d2f39e5 100644 --- a/nixos/common/nix.nix +++ b/nixos/common/nix.nix @@ -1,26 +1,38 @@ { config, lib, pkgs, ... }: -let - secrets = import ../secrets.nix; - -in { +{ + nix.useSandbox = true; nix.buildCores = config.machine.cpu.cores; + # If there is more than one job running and they're all running make -j$buildCores -l$buildCores, + # then system load will likely be higher than $buildCores and so each job ends up only using one core each. + # So we might as well spawn one job per core. + nix.maxJobs = config.machine.cpu.cores; nixpkgs.config.allowUnfree = true; # Shared signing key. environment.etc."nix/signing-key.pub" = { - text = secrets.keyPairs.nixSigning.public; + source = ../../secret/nix-signing-key.pub; }; environment.etc."nix/signing-key.sec" = { - mode = "0400"; - text = secrets.keyPairs.nixSigning.private; + source = ../../secret/nix-signing-key.priv; }; + nix.binaryCachePublicKeys = [ + (builtins.readFile ../../secret/nix-signing-key.pub) + ]; + environment.variables.NIX_SECRET_KEY_FILE = "/etc/nix/signing-key.sec"; nix.gc = { - automatic = true; - dates = "Mon 19:00"; + automatic = lib.mkDefault true; + dates = "Sat 03:00"; options = "--delete-older-than 14d"; }; systemd.timers.nix-gc.timerConfig.Persistent = true; + + nix.nixPath = [ + "nixpkgs=/home/kier/config/nixpkgs" + "nixos-config=/home/kier/config/nixos/machines/${config.machine.name}.nix" + ]; + + nixpkgs.overlays = [(import ../../pkgs/overlay.nix)]; } diff --git a/nixos/common/options.nix b/nixos/common/options.nix index ecd47eeb..7ed421b3 100644 --- a/nixos/common/options.nix +++ b/nixos/common/options.nix @@ -5,28 +5,15 @@ with lib; { options = { machine.name = mkOption { - type = types.string; + type = types.str; description = ''The machine's hostname.''; }; - machine.hostId = mkOption { - type = types.string; - description = ''The value of "networking.hostId", necessary for ZFS.''; - }; - - machine.vboxHost = mkOption { - type = types.bool; - description = ''Whether to enable VirtualBox host tools.''; - }; - - machine.wifi = mkOption { + machine.ipv6-internet = mkOption { type = types.bool; - description = ''Whether to enable wireless networking.''; - }; - - machine.bluetooth = mkOption { - type = types.bool; - description = ''Whether to enable Bluetooth.''; + default = true; + example = false; + description = ''Whether the machine has access to the Internet over IPv6 as well as IPv4.''; }; machine.cpu.cores = mkOption { @@ -36,45 +23,40 @@ with lib; machine.cpu.intel = mkOption { type = types.bool; + default = false; description = ''Whether the machine has an Intel CPU, and so should enable Intel microcode updates.''; }; - machine.fsdevices.root = mkOption { - type = types.string; - description = ''Device in /dev holding the root filesystem.''; - }; - - machine.fsdevices.efi = mkOption { - type = types.string; - description = ''Device in /dev holding the EFI system filesystem.''; - }; - - machine.fsdevices.grub = mkOption { - type = types.string; - description = ''Device in /dev holding the disk (not partition!) on which the GRUB bootloader is installed.''; - }; - - machine.fsdevices.swap = mkOption { - type = types.string; - description = ''Device in /dev holding the swap partition.''; + machine.gpu.nvidia = mkOption { + type = types.bool; + default = false; + example = true; + description = ''Whether the machine has an NVIDIA graphics card, and so should enable the corresponding graphics driver.''; }; machine.i3blocks.cpuThermalZone = mkOption { - type = types.string; + type = types.str; example = "thermal_zone2"; description = ''Subdirectory of /sys/class/thermal representing the CPU temperature sensor.''; }; machine.i3blocks.ethInterface = mkOption { - type = types.string; + type = types.str; example = "enp4s0"; description = ''Name of the Ethernet network interface.''; }; machine.i3blocks.wlanInterface = mkOption { - type = types.string; + type = types.str; example = "wlp3s0"; description = ''Name of the WiFi network interface.''; }; + + machine.i3blocks.batteries = mkOption { + type = types.listOf types.str; + default = []; + example = ''[ "BAT0" "BAT1" ]''; + description = ''Subdirectories of /sys/class/power_supply representing batteries whose charge level should be displayed.''; + }; }; } diff --git a/nixos/common/print.nix b/nixos/common/print.nix deleted file mode 100644 index 35565067..00000000 --- a/nixos/common/print.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - services.printing = { - enable = true; - drivers = [ - pkgs.gutenprint - pkgs.samsung-unified-linux-driver_4_01_17 - ]; - }; - - environment.variables.PRINTER = "woodside"; -} diff --git a/nixos/common/services.nix b/nixos/common/services.nix index 36660fdd..780e4278 100644 --- a/nixos/common/services.nix +++ b/nixos/common/services.nix @@ -1,9 +1,21 @@ { config, lib, pkgs, ... }: -{ +let + hist = import ../../hist.nix; + + syncthingListenAddr = hist.hosts."${config.machine.name}".addresses.default.private; + syncthingListenPort = 8384; + +in { # use timesyncd instead of ntpd + # Explicit lower-than-usual priority of 150 is needed + # so that + # can override this setting at the default priority of 100. services.ntp.enable = false; - services.timesyncd.enable = true; + services.timesyncd.enable = lib.mkOverride 150 true; + + # enable atd (a one-shot command scheduler) + services.atd.enable = true; # ssh server services.openssh = { @@ -11,4 +23,36 @@ passwordAuthentication = true; permitRootLogin = "without-password"; }; + + # Mail relay + services.nullmailer = { + enable = false; + setSendmail = true; + config = { + me = config.machine.name; + adminaddr = "me@kierdavis.com"; # All mail to localhost is redirected to this address. + defaultdomain = ""; + remotes = '' + aspmx.l.google.com smtp port=25 starttls + ''; + }; + }; + + # syncthing + services.syncthing = { + enable = true; + dataDir = "/home/kier/.syncthing"; + systemService = true; + user = "kier"; + group = config.users.users.kier.group; + guiAddress = "[${syncthingListenAddr}]:${builtins.toString syncthingListenPort}"; + }; + systemd.services.syncthing = lib.optionalAttrs (lib.hasPrefix "${hist.networks.wg.prefix}:" syncthingListenAddr) { + requires = ["wireguard-wg-hist.service"]; + after = ["wireguard-wg-hist.service"]; + }; + networking.firewall.interfaces.wg-hist.allowedTCPPorts = [ 22000 syncthingListenPort ]; + networking.firewall.interfaces.wg-hist.allowedUDPPorts = [ 21027 ]; + + programs.gnupg.agent.enable = true; } diff --git a/nixos/common/users.nix b/nixos/common/users.nix index 7e878ba4..fdfd9630 100644 --- a/nixos/common/users.nix +++ b/nixos/common/users.nix @@ -1,7 +1,7 @@ { config, lib, pkgs, ... }: let - secrets = import ../secrets.nix; + passwords = import ../../secret/passwords.nix; in { # Force live user info to match what's declared in this file. @@ -9,19 +9,59 @@ in { users.users.root = { # TODO: remove this - hashedPassword = secrets.hashedUserPasswords.root; + hashedPassword = passwords.user.root.hashed; openssh.authorizedKeys.keyFiles = [ ../../ssh-keys ]; }; users.users.kier = { - createHome = true; + createHome = false; # so that other users can read ~kier/config/nixpkgs description = "Kier Davis"; - extraGroups = ["wheel" "networkmanager"]; - hashedPassword = secrets.hashedUserPasswords.kier; + extraGroups = [ + "audio" # Permission to use audio devices e.g. /dev/snd/... + "dialout" # Permission to use USB serial devices (e.g. /dev/ttyACM0) + "networkmanager" # Permission to control NetworkManager + "tty" # Permission to operate any tty + "wheel" # Permission to 'sudo' as root + "video" # Permission to access video devices (including hardware acceleration of video processing) + ]; + hashedPassword = passwords.user.kier.hashed; home = "/home/kier"; isNormalUser = true; name = "kier"; openssh.authorizedKeys.keyFiles = [ ../../ssh-keys ]; + uid = 1001; useDefaultShell = true; }; + + users.users.nixremotebuild = { + description = "Nix remote build user"; + isNormalUser = false; + isSystemUser = true; + openssh.authorizedKeys.keyFiles = [ ../../ssh-keys ]; + useDefaultShell = true; + }; + + # Allow access to USB devices without requiring root permissions + services.udev.extraRules = '' + # SR V4 power board + SUBSYSTEM=="usb", ATTR{idVendor}=="1bda", ATTR{idProduct}=="0010", GROUP="dialout", MODE="0666" + # SR V4 servo board + SUBSYSTEM=="usb", ATTR{idVendor}=="1bda", ATTR{idProduct}=="0011", GROUP="dialout", MODE="0666" + # Altera "USB Blaster" JTAG cable + SUBSYSTEM=="usb", ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", GROUP="dialout", MODE="0666" + # Teensy + KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04*", GROUP="dialout", MODE="0666" + KERNEL=="hidraw*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04*", GROUP="dialout", MODE="0666" + SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04*", GROUP="dialout", MODE="0666" + KERNEL=="hidraw*", ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="013*", GROUP="dialout", MODE="0666" + SUBSYSTEMS=="usb", ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="013*", GROUP="dialout", MODE="0666" + ''; + + nix.trustedUsers = [ "root" "kier" "nixremotebuild" ]; + + # sudo + security.sudo = { + enable = true; + wheelNeedsPassword = false; + }; } diff --git a/nixos/default.nix b/nixos/default.nix index 21815719..236742f6 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -3,24 +3,31 @@ let nixos = import ; in rec { - machines = { - coloris = (nixos { - configuration = machines/coloris.nix; - system = "x86_64-linux"; - }).system; + coloris = nixos { + configuration = machines/coloris.nix; + system = "x86_64-linux"; + }; + + # Hint: + # nix-build -A coloris-win.system.build.tarball + # wsl --import DISTRO_NAME FS_IMAGE_DIR result/tarball/*.tar.gz --version 2 + coloris-win = nixos { + configuration = machines/coloris-win.nix; + system = "x86_64-linux"; + }; - ouroboros = (nixos { - configuration = machines/ouroboros.nix; - system = "x86_64-linux"; - }).system; + saelli = nixos { + configuration = machines/saelli.nix; + system = "x86_64-linux"; + }; - nocturn = (nixos { - configuration = machines/nocturn.nix; - system = "x86_64-linux"; - }).system; + ptolemy = nixos { + configuration = machines/ptolemy.nix; + system = "x86_64-linux"; }; - all = { - inherit (machines) coloris ouroboros nocturn; + fingerbib = nixos { + configuration = machines/fingerbib.nix; + system = "x86_64-linux"; }; } diff --git a/nixos/deploy.sh b/nixos/deploy.sh deleted file mode 100755 index 8b2984ff..00000000 --- a/nixos/deploy.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -set -eu - -attrs="" - -for arg in $*; do - attrs="$attrs -A $arg" -done - -if [ -z "$attrs" ]; then - echo "no attributes supplied (try '$0 all')" - exit 2 -fi - -config=/home/kier/config -log=/tmp/nix-build.log -cache=/mnt/nocturn/nix-cache -secret_key=/etc/nix/nix-cache.sec - -nix-build -Q --no-out-link $config/nixos $attrs | tee $log - -paths=$(tail $log | grep '^/nix/store') - -echo "**************************" -echo "Deploying roots:" -for path in $paths; do - echo " $path" -done -echo "**************************" - -nix-push --dest $cache --bzip2 --key-file $secret_key $paths - -rm -f $log diff --git a/nixos/extras/desktop/audio.nix b/nixos/extras/audio.nix similarity index 96% rename from nixos/extras/desktop/audio.nix rename to nixos/extras/audio.nix index 9b4d6b47..cbce10bf 100644 --- a/nixos/extras/desktop/audio.nix +++ b/nixos/extras/audio.nix @@ -8,6 +8,7 @@ let in { # Enable pulseaudio. + sound.enable = true; hardware.pulseaudio.enable = true; hardware.pulseaudio.support32Bit = true; # Might be necessary for some Steam games. hardware.pulseaudio.configFile = pulseConfig; diff --git a/nixos/extras/boinc.nix b/nixos/extras/boinc.nix index b23248b2..1b378f2d 100644 --- a/nixos/extras/boinc.nix +++ b/nixos/extras/boinc.nix @@ -1,25 +1,23 @@ { config, lib, pkgs, ... }: let - boincDir = "/var/lib/boinc"; + nvidia_x11 = pkgs.linuxPackages.nvidia_x11.override { libsOnly = true; }; in { - imports = [ ../lib/boinc-fhs.nix ]; - - fileSystems.boinc = { - mountPoint = boincDir; - device = "/dev/hdd/boinc"; - fsType = "ext4"; - options = ["noatime" "nodiratime"]; - }; - - services.boinc-fhs = { + services.boinc = { enable = true; - dataDir = boincDir; + dataDir = "/var/lib/boinc"; allowRemoteGuiRpc = true; extraEnvPackages = [ - pkgs.virtualbox + # pkgs.virtualbox pkgs.ocl-icd - (pkgs.linuxPackages.nvidia_x11.override { libsOnly = true; }) - ]; + ] ++ lib.optional config.machine.gpu.nvidia nvidia_x11; }; + + environment.systemPackages = [ + pkgs.boincgpuctl + ]; + + environment.variables.BOINC_DATA_DIR = config.services.boinc.dataDir; + + networking.firewall.interfaces.wg-hist.allowedTCPPorts = [ 31416 ]; } diff --git a/nixos/extras/clickpad.nix b/nixos/extras/clickpad.nix new file mode 100644 index 00000000..7b3d860b --- /dev/null +++ b/nixos/extras/clickpad.nix @@ -0,0 +1,42 @@ +# synaptics config for ThinkPad clickpad +# http://www.thinkwiki.org/wiki/Buttonless_Touchpad + +{ config, lib, pkgs, ... }: + +{ + services.xserver.synaptics = { + enable = true; + additionalOptions = '' + Option "SoftButtonAreas" "60% 0 0 2400 40% 60% 0 2400" + Option "AreaTopEdge" "2400" + + Option "VertHysteresis" "50" + Option "HorizHysteresis" "50" + + Option "LockedDrags" "1" + + Option "FingerLow" "50" + Option "FingerHigh" "55" + + Option "AccelerationProfile" "2" + Option "ConstantDeceleration" "4" + ''; + + tapButtons = false; + #fingersMap = [ 1 3 2 ]; + + horizontalScroll = true; + vertEdgeScroll = true; + horizEdgeScroll = true; + vertTwoFingerScroll = false; + horizTwoFingerScroll = false; + scrollDelta = 30; + + palmDetect = true; + palmMinWidth = 5; + palmMinZ = 40; + + minSpeed = "0.2"; + maxSpeed = "1.5"; + }; +} diff --git a/nixos/extras/desktop/apps.nix b/nixos/extras/desktop/apps.nix index cfbd148e..96f24171 100644 --- a/nixos/extras/desktop/apps.nix +++ b/nixos/extras/desktop/apps.nix @@ -1,38 +1,58 @@ { config, lib, pkgs, ... }: let - localPkgs = import ../../../pkgs pkgs; + hostname = config.machine.name; + print3dPassword = (import ../../../secret/passwords.nix).user.fingerbib-3dprint.plain; + print3dScript = pkgs.writeShellScriptBin "3dprint" '' + exec ${pkgs.freerdp}/bin/xfreerdp /v:fingerbib /u:3dprint /p:${print3dPassword} /drive:${hostname},/ + ''; in { - # VirtualBox - virtualisation.virtualbox.host.enable = config.machine.vboxHost; + # redshift (adjusts colour temperature of displays at night) + services.redshift.enable = true; - environment.systemPackages = with localPkgs; [ - chromium + # Backlight control + programs.light.enable = true; + + # Other programs + programs.adb.enable = false; + programs.steam.enable = true; + virtualisation.virtualbox.host.enable = true; + environment.systemPackages = with pkgs; [ + citrix_workspace + cups # client dmenu evince - ftb-launcher - geda gimp gnome3.eog i3blocks i3blocks-scripts i3lock - lock - logisim - multimc - networkmanagerapplet pavucontrol - pcb - pysolfc - quasselClient + pinentry-gnome screenshot - skype - soton-rdp - #spotify - steam - sublime3 + signal-desktop + spotify terminator + tor-browser-bundle-bin vlc + zoom-us + + # Development + freecad + geda + kicad + pcb + print3dScript + quartus ]; + + # For spotify to sync local files to other devices on the LAN via uPnP: + networking.firewall = { + allowedTCPPorts = [ 57621 ]; + allowedUDPPorts = [ 57621 ]; + }; + + environment.variables.CUPS_SERVER = "printing.hist:80"; + environment.variables.PRINTER = "HP_Envy_5640"; } diff --git a/nixos/extras/desktop/default.nix b/nixos/extras/desktop/default.nix index 2a76f0bd..4015ad9d 100644 --- a/nixos/extras/desktop/default.nix +++ b/nixos/extras/desktop/default.nix @@ -3,10 +3,17 @@ { imports = [ ./apps.nix - ./audio.nix - ./etc.nix + ./google-chrome.nix + ./i3blocks-config.nix ./x11.nix ]; - networking.networkmanager.enable = true; + # Plymouth splash screen during boot. + boot.plymouth.enable = true; + + # required for fluidsynth + security.pam.loginLimits = [ + { domain = "@audio"; type = "-"; item = "rtprio"; value = "90"; } + { domain = "@audio"; type = "-"; item = "memlock"; value = "unlimited"; } + ]; } diff --git a/nixos/extras/desktop/google-chrome.nix b/nixos/extras/desktop/google-chrome.nix new file mode 100644 index 00000000..e5e4d37d --- /dev/null +++ b/nixos/extras/desktop/google-chrome.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: { + programs.chromium.enable = true; + environment.systemPackages = [ pkgs.google-chrome ]; + + # Google Chrome ignore /etc/hosts, so provide hist domains using a local DNS server instead. + environment.etc."resolv.conf".text = "nameserver 127.0.0.1"; + services.coredns.enable = true; + services.coredns.config = '' + hist { + bind 127.0.0.1 + errors + log + reload + cancel + loop + hosts + } + . { + bind 127.0.0.1 + errors + log + reload + cancel + loop + forward . /etc/resolv.conf.upstream + } + ''; + networking.resolvconf.extraConfig = "resolv_conf=/etc/resolv.conf.upstream"; + + # Hack to make Google Chrome send DNS AAAA queries in addition to A queries even if the machine has no IPv6 internet connection. + networking.interfaces.lo.ipv6.routes = lib.optional (!config.machine.ipv6-internet) { + address = "2001:4860:4860::8888"; + prefixLength = 128; + }; +} diff --git a/nixos/extras/desktop/etc.nix b/nixos/extras/desktop/i3blocks-config.nix similarity index 65% rename from nixos/extras/desktop/etc.nix rename to nixos/extras/desktop/i3blocks-config.nix index 1e828517..f449f7e2 100644 --- a/nixos/extras/desktop/etc.nix +++ b/nixos/extras/desktop/i3blocks-config.nix @@ -1,7 +1,22 @@ { config, lib, pkgs, ... }: -{ - environment.etc."i3blocks.conf".text = '' +let + nvidiaGpuConfig = if config.machine.gpu.nvidia then '' + [vram] + interval=5 + + [gpu] + interval=5 + '' else ""; + + batteryConfig = lib.concatMapStrings (name: '' + [bat] + interval=5 + instance=${name} + '') config.machine.i3blocks.batteries; + +in { + environment.etc."xdg/i3blocks/config".text = '' command=/run/current-system/sw/bin/i3blocks-$BLOCK_NAME [disk] @@ -26,15 +41,13 @@ [swap] interval=5 - [vram] - interval=5 - [cpu] interval=5 instance=${config.machine.i3blocks.cpuThermalZone} - [gpu] - interval=5 + ${nvidiaGpuConfig} + + ${batteryConfig} [load] interval=5 diff --git a/nixos/extras/desktop/x11.nix b/nixos/extras/desktop/x11.nix index 02f16128..5e283397 100644 --- a/nixos/extras/desktop/x11.nix +++ b/nixos/extras/desktop/x11.nix @@ -3,18 +3,20 @@ { services.xserver.enable = true; services.xserver.windowManager.i3.enable = true; + services.xserver.windowManager.openbox.enable = true; services.xserver.desktopManager.xterm.enable = false; # creates unnecessary session types "xterm" and "xterm + i3" - services.xserver.videoDrivers = ["nvidia"]; - hardware.opengl.extraPackages = lib.optional config.machine.cpu.intel pkgs.intel-ocl; - # Allow support for Direct Rendering for 32-bit applications e.g. Wine - hardware.opengl.driSupport32Bit = true; - - services.xserver.displayManager.sessionCommands = '' - ${pkgs.networkmanagerapplet}/bin/nm-applet & - ''; + services.xserver.displayManager.defaultSession = "none+i3"; + services.xserver.videoDrivers = lib.optional config.machine.gpu.nvidia "nvidia"; + #hardware.opengl.extraPackages = lib.optional config.machine.cpu.intel pkgs.intel-ocl; fonts.fontconfig.enable = true; fonts.fontconfig.dpi = 84; - users.users.kier.extraGroups = ["video"]; + # SSH X11 forwarding + services.openssh.forwardX11 = true; + + environment.systemPackages = [ pkgs.gnome3.dconf ]; + + # Fixes android-studio not being able to find the vulkan icd.d directory. + environment.sessionVariables.XDG_DATA_DIRS = ["/run/opengl-driver/share"]; } diff --git a/nixos/extras/devel.nix b/nixos/extras/devel.nix new file mode 100644 index 00000000..b0f444fc --- /dev/null +++ b/nixos/extras/devel.nix @@ -0,0 +1,34 @@ +{ config, lib, pkgs, ... }: + +let + kubesh = pkgs.writeShellScriptBin "kubesh" '' + exec ${pkgs.kubectl}/bin/kubectl --namespace kier-dev run --rm --stdin --tty --image=nixos/nix --restart=Never kubesh -- /bin/sh + ''; + +in { + virtualisation.podman.enable = true; + + environment.systemPackages = with pkgs; [ + # Software + cargo + modd + (python3.withPackages (pyPkgs: with pyPkgs; [ virtualenv ])) + rustfmt + + # Kubernetes/containers + buildah + kubectl + kubesh + kubernetes-helm + + # Other + duplicity + fina + keybase + sr-tools + ]; + + services.keybase.enable = true; + + documentation.dev.enable = lib.mkOverride 500 true; +} diff --git a/nixos/extras/headless.nix b/nixos/extras/headless.nix index e5ba754f..8c84a7b7 100644 --- a/nixos/extras/headless.nix +++ b/nixos/extras/headless.nix @@ -1,26 +1,167 @@ { config, lib, pkgs, ... }: -{ - networking.wireless.enable = config.machine.wifi; +let + mkLowPriority = lib.mkOverride 200; # 100 is the default priority - #environment.noXlibs = true; - boot.vesa = false; - fonts.fontconfig.enable = false; - hardware.pulseaudio.enable = false; - programs.ssh.setXAuthLocation = false; - security.pam.services.su.forwardXAuth = lib.mkForce false; - services.xserver.enable = false; - sound.enable = false; + refuse = name: (pkgs.runCommand "refuse-${name}" {} '' + echo >&2 "If you're seeing this, your system has a dependency on ${name}, please remove it." + exit 1 + '') // { + dev = refuse "${name}.dev"; + }; - # Don't start a tty on the serial consoles. - systemd.services."serial-getty@ttyS0".enable = false; - systemd.services."serial-getty@hvc0".enable = false; - systemd.services."getty@tty1".enable = false; - systemd.services."autovt@".enable = false; + dummy = name: pkgs.runCommand "dummy-${name}" {} '' + mkdir -p $out + ''; - # Since we can't manually respond to a panic, just reboot. - boot.kernelParams = [ "panic=1" "boot.panic_on_fail" ]; +in { + #environment.noXlibs = mkLowPriority true; + boot.vesa = mkLowPriority false; + fonts.fontconfig.enable = mkLowPriority false; + hardware.pulseaudio.enable = mkLowPriority false; + programs.ssh.setXAuthLocation = mkLowPriority false; + security.pam.services.su.forwardXAuth = lib.mkForce false; + services.xserver.enable = mkLowPriority false; + sound.enable = mkLowPriority false; # Being headless, we don't need a GRUB splash image. boot.loader.grub.splashImage = null; + + # Disable optional features of some packages to reduce dependency on graphics libraries. + nixpkgs.overlays = [(self: super: { + beets = super.beets.override { + enableKeyfinder = false; # pulls in mesa-noglu + }; + boinc = (super.boinc.override { + libGL = null; + libGLU = null; + libXmu = null; + libXi = null; + freeglut = null; + libjpeg = null; + wxGTK30 = null; + xcbutil = null; + gtk2 = null; + libXScrnSaver = null; + libX11 = null; + libxcb = null; + }).overrideDerivation (superAttrs: { + NIX_LDFLAGS = ""; + configureFlags = ["--disable-manager"]; + }); + cairo = super.cairo.override { + x11Support = false; + }; + dbus = super.dbus.override { + x11Support = false; + }; + ghostscript = super.ghostscript.override { + x11Support = false; + }; + git = super.git.override { + guiSupport = false; + }; + gnupg22 = super.gnupg22.override { + # 'true' removes gpg-agent, which breaks password-store. + enableMinimal = false; + # This option's name isn't very descriptive of what it actually does. + # When true, gnupg uses "third-party" pinentry rather than an internal one. + # This is fine since we configure "third-party" pinentry to build without GUI flavours. + guiSupport = true; + }; + ffmpeg = super.ffmpeg.override { + sdlSupport = false; + vdpauSupport = false; + }; + gobject-introspection = super.gobject-introspection.override { + x11Support = false; + }; + gpgme = super.gpgme.override { + qtbase = null; + }; + gtk2 = refuse "gtk2"; + gtk2-x11 = refuse "gtk2-x11"; + gtk3 = refuse "gtk3"; + gtk3-x11 = refuse "gtk3-x11"; + hplip = super.hplip.override { + withQt5 = false; + }; + imagemagick = super.imagemagick.override { + libX11 = null; + libXext = null; + libXt = null; + }; + libva = (super.libva.override { minimal = true; }).overrideAttrs (superAttrs: { + nativeBuildInputs = with self; [ meson pkg-config ninja ]; + }); + mupdf = super.mupdf.override { + enableGL = false; + enableX11 = false; + }; + net-snmp = super.net-snmp.override { + perlPackages = self.perlPackages // { + Tk = null; + }; + }; + openjdk = super.openjdk.override { headless = true; }; + openjdk8 = super.openjdk8.override { headless = true; }; + oepnjdk11 = super.openjdk11.override { headless = true; }; + openjdk14 = super.openjdk14.override { headless = true; }; + pango = (super.pango.override { + x11Support = false; + }).overrideAttrs (superAttrs: { + # docs fail to build when x11Support=false. + mesonFlags = (lib.lists.remove "-Dgtk_doc=true" superAttrs.mesonFlags) ++ ["-Dgtk_doc=false"]; + outputs = lib.lists.remove "devdoc" superAttrs.outputs; + postInstall = ""; + }); + pass = super.pass.override { + qrencode = null; + x11Support = false; + waylandSupport = false; + }; + perlPackages = super.perlPackages // { + Tk = refuse "perlPackages.Tk"; + }; + pinentry = super.pinentry.override { + enabledFlavors = [ "curses" "tty" ]; + }; + # python3Packages = self.python3.pkgs; + # python3 = super.python3.override { + # packageOverrides = pythonSelf: pythonSuper: { + # }; + # }; + qemu = super.qemu.override { + gtkSupport = false; + sdlSupport = false; + spiceSupport = false; + }; + qemu_kvm = super.qemu_kvm.override { + gtkSupport = false; + sdlSupport = false; + spiceSupport = false; + }; + qtbase = refuse "qtbase"; + SDL2 = super.SDL2.override { + x11Support = false; + }; + virtualbox = (super.virtualbox.override { + headless = true; + pulseSupport = false; + xorgproto = null; + libX11 = null; + libXext = null; + libXcursor = null; + libXmu = null; + libGL = null; + # Not strictly needed for headless, but makes the dependency tree simpler. + javaBindings = false; + }).overrideAttrs (superAttrs: { + configureFlags = [ "--build-headless" ]; + }); + wayland = refuse "wayland"; + xorg = super.xorg // { + libX11 = refuse "libX11"; + }; + })]; } diff --git a/nixos/extras/low-power.nix b/nixos/extras/low-power.nix new file mode 100644 index 00000000..219a46a9 --- /dev/null +++ b/nixos/extras/low-power.nix @@ -0,0 +1,60 @@ +# https://wiki.archlinux.org/index.php/Power_management#Power_saving +# http://www.thinkwiki.org/wiki/How_to_reduce_power_consumption + +{ config, pkgs, lib, ... }: + +{ + boot.extraModprobeConfig = '' + # Put audio hardware to sleep after 1 second of inactivity (Intel hardware). + options snd_hda_intel power_save=1 + + # Wi-fi power saving (Intel hardware). + options iwlwifi power_save=1 d0i3_disable=0 uapsd_disable=0 + options iwldvm force_cam=0 + ''; + + boot.kernel.sysctl = { + # Disable NMI watchdog (generates lots of interrupts, mainly a debugging feature). + "kernel.nmi_watchdog" = 0; + + # Increase dirty virtual memory writeback time. + # (commented out because vm.laptop_mode also sets this) + #"vm.dirty_writeback_centisecs" = 6000; + + # https://www.kernel.org/doc/Documentation/laptops/laptop-mode.txt + "vm.laptop_mode" = 5; + }; + + services.udev.extraRules = '' + # PCI runtime power management. + ACTION=="add", SUBSYSTEM=="pci", ATTR(power/control)="auto" + + # USB autosuspend blacklist + # Tecknet wireless mouse + ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="062a", ATTR{idProduct}=="5918", GOTO="power_usb_rules_end" + # Corsair Strafe keyboard + ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="1b1c", ATTR{idProduct}=="1b15", GOTO="power_usb_rules_end" + # Moto G5 phone + ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", ATTR{idProduct}=="2e82", GOTO="power_usb_rules_end" + + # Enable USB autosuspend by default for all other devices. + #ACTION=="add", SUBSYSTEM=="usb", TEST=="power/control", ATTR{power/control}="auto" + LABEL="power_usb_rules_end" + ''; + + services.xserver.displayManager.sessionCommands = '' + # Turn off display after 5 minutes of idling. + xset +dpms + xset dpms 0 0 300 + ''; + + services.xserver.deviceSection = '' + # Disable DRI (graphics acceleration). + Option "NoDRI" + ''; + + # TODO: check bluetooth, btusb unloaded + + # Install powertop + environment.systemPackages = with pkgs; [ powertop ]; +} diff --git a/nixos/extras/boot-efi.nix b/nixos/extras/platform/efi.nix similarity index 88% rename from nixos/extras/boot-efi.nix rename to nixos/extras/platform/efi.nix index 7c2905a1..c8698cb8 100644 --- a/nixos/extras/boot-efi.nix +++ b/nixos/extras/platform/efi.nix @@ -7,8 +7,9 @@ fileSystems.efi = { mountPoint = config.boot.loader.efi.efiSysMountPoint; - device = config.machine.fsdevices.efi; fsType = "vfat"; options = ["noatime" "nodiratime"]; }; + + # fileSystems.efi.device = ...; } diff --git a/nixos/extras/boot-grub.nix b/nixos/extras/platform/grub.nix similarity index 62% rename from nixos/extras/boot-grub.nix rename to nixos/extras/platform/grub.nix index 8b14a10c..0bad382b 100644 --- a/nixos/extras/boot-grub.nix +++ b/nixos/extras/platform/grub.nix @@ -3,5 +3,5 @@ { boot.loader.grub.enable = true; boot.loader.grub.version = 2; - boot.loader.grub.device = config.machine.fsdevices.grub; + # boot.loader.grub.device = ...; } diff --git a/nixos/extras/platform/hp.nix b/nixos/extras/platform/hp.nix new file mode 100644 index 00000000..f9d6c1b7 --- /dev/null +++ b/nixos/extras/platform/hp.nix @@ -0,0 +1,131 @@ +# Add baseline from URL: http://downloads.linux.hpe.com/SDR/repo/spp-gen8/2017.04.0/hp/swpackages/bp002933.xml + +{ config, lib, pkgs, ... }: let + packages = [ + (pkgs.fetchurl { + url = "https://cbs.centos.org/kojifiles/packages/dumb-init/1.1.3/17.el7/x86_64/dumb-init-1.1.3-17.el7.x86_64.rpm"; + hash = "sha256:0d8wszhyi5x9gj8lc7bkrvlcah8b2hm2zh8jvdby4wjgfr930fzx"; + }) + (pkgs.fetchurl { + url = "mirror://centos/7.9.2009/updates/x86_64/Packages/dmidecode-3.2-5.el7_9.1.x86_64.rpm"; + hash = "sha256:0p79qfmxcwb9gx5d6ippz9xlxwxbz9f7q7y3fzjc4dkgfsbjr0bv"; + }) + (pkgs.fetchurl { + url = "mirror://centos/7.9.2009/os/x86_64/Packages/hwdata-0.252-9.7.el7.x86_64.rpm"; + hash = "sha256:1n8xrxjxgmdvq08jw2g9zry3yb6pnp0fwvmnr1c8rai0wf0kg3sg"; + }) + (pkgs.fetchurl { + url = "mirror://centos/7.9.2009/os/x86_64/Packages/libxslt-1.1.28-6.el7.x86_64.rpm"; + hash = "sha256:0hvm2mxd6phvrccs7h7mrqbsx10xafcfpsm30sl6i5lkg82nd1ln"; + }) + (pkgs.fetchurl { + url = "mirror://centos/7.9.2009/os/x86_64/Packages/pciutils-3.5.1-3.el7.x86_64.rpm"; + hash = "sha256:1zlxphrpghsn80f8rzzh3ldgdn2zw3cg1qn3nh1ak16vmbr4jny4"; + }) + (pkgs.fetchurl { + url = "mirror://centos/7.9.2009/os/x86_64/Packages/pciutils-libs-3.5.1-3.el7.x86_64.rpm"; + hash = "sha256:0k03w821wdwd758p3qanada2x9kp58zgvz3l0m5j4mfajdf3kw9m"; + }) + (pkgs.fetchurl { + url = "mirror://centos/7.9.2009/os/x86_64/Packages/unzip-6.0-21.el7.x86_64.rpm"; + hash = "sha256:1av1j0cciqm3caja6rc381pg04wx76flyb3p2bilfvsabj4b8aql"; + }) + (pkgs.fetchurl { + url = "mirror://centos/7.9.2009/os/x86_64/Packages/which-2.20-7.el7.x86_64.rpm"; + hash = "sha256:0hjpv5wmf5lzsvp80q95mmvyzycg1cc31pmda1wchji7id1q7wvc"; + }) + (pkgs.fetchurl { + # https://support.hpe.com/hpesc/public/swd/detail?swItemId=MTX_846d6e6dad2441488ce102cb9a + url = "https://downloads.hpe.com/pub/softlib2/software1/pubsw-linux/p1216536599/v133810/rhel7/x86_64/sum-8.1.0-14.rhel7.x86_64.rpm"; + hash = "sha256:164bd4a13ce39bd9f461ef7b6e1b1b6b909cf95db77731bf8b86602ef8a18b01"; + }) + ]; + image = pkgs.dockerTools.buildImage { + name = "hpsum"; + tag = "latest"; + fromImage = pkgs.dockerTools.pullImage { + imageName = "docker.io/library/centos"; + imageDigest = "sha256:e4ca2ed0202e76be184e75fb26d14bf974193579039d5573fb2348664deef76e"; + sha256 = "1f0nri9aggnjgcr1ik1ca1n6al0wyjw087lfcqi8nxaylph88x97"; + }; + runAsRoot = '' + yum install --assumeyes ${builtins.concatStringsSep " " packages} + ln -s /bin/true /bin/firefox + ''; + config = { + Entrypoint = ["/bin/dumb-init"]; + Cmd = ["/bin/bash"]; + }; + }; + # baseline = pkgs.fetchzip { + # # https://support.hpe.com/hpesc/public/swd/detail?swItemId=MTX_f9e98ba6a3b9460d987095831d + # url = "https://downloads.hpe.com/pub/softlib2/software1/supportpack-generic/p157293194/v123101/supspp-2016.10.rhel7.3.en.tar.gz"; + # hash = "sha256:1njg0imr0vwi3z8iax4xvqj6aksk652mdv825nhlnimpx47kirxv"; + # stripRoot = false; + # }; + # components = pkgs.linkFarm "components" (builtins.map (pkg: { inherit (pkg) name; path = pkg; }) [ + # (pkgs.fetchurl { + # # https://support.hpe.com/hpesc/public/swd/detail?swItemId=MTX_7add8906345a4e7f982bd39f31 + # url = "https://downloads.hpe.com/pub/softlib2/software1/sc-linux-fw-sys/p244945965/v167882/RPMS/i386/firmware-system-p73-2019.05.24-1.1.i386.rpm"; + # hash = "sha256:0w8zd8g3jmzkxi0i52yfnxiib7rm9yic3hrqdj6377i07hdpzc6j"; + # }) + # ]); + cfg = config.services.hpsum; +in { + options = with lib; { + services.hpsum = { + bindAddress = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Address on which HP Smart Update Manager should listen for connections. This must be an IP address, not a hostname."; + }; + ports = { + http = mkOption { + type = types.int; + default = 63001; + description = "Port on which HP Smart Update Manager should listen for HTTP connections."; + }; + https = mkOption { + type = types.int; + default = 63002; + description = "Port on which HP Smart Update Manager should listen for HTTPS connections."; + }; + }; + }; + }; + config = { + virtualisation.oci-containers.containers.hpsum = { + image = image.imageName; + imageFile = image; + workdir = "/opt/sum/bin"; + cmd = [ + "/opt/sum/bin/smartupdate" + "--port" (builtins.toString cfg.ports.http) + "--ssl_port" (builtins.toString cfg.ports.https) + ]; + volumes = [ + "/var/lib/sum/baseline:/opt/sum/baseline:rw" + "/var/log/sum:/var/log/sum:rw" + # "${baseline}:/opt/sum/baseline:ro" + # "${components}:/opt/sum/components:ro" + ]; + ports = [ + "${cfg.bindAddress}:${builtins.toString cfg.ports.http}:${builtins.toString cfg.ports.http}" + "${cfg.bindAddress}:${builtins.toString cfg.ports.https}:${builtins.toString cfg.ports.https}" + ]; + extraOptions = [ "--privileged" ]; + }; + systemd.services."${config.virtualisation.oci-containers.backend}-hpsum" = { + description = "HP Smart Update Manager"; + serviceConfig = { + StandardOutput = lib.mkForce "journal"; + StandardError = lib.mkForce "journal"; + TimeoutStopSec = lib.mkForce 10; + }; + }; + systemd.tmpfiles.rules = [ + "d /var/lib/sum 0755 root root - -" + "d /var/log/sum 0755 root root - -" + ]; + }; +} diff --git a/nixos/extras/platform/linode.nix b/nixos/extras/platform/linode.nix new file mode 100644 index 00000000..083b837e --- /dev/null +++ b/nixos/extras/platform/linode.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ + + ]; + + # Configure serial port for LISH. + boot.kernelParams = [ "console=ttyS0,19200n8" ]; + boot.loader.grub.extraConfig = '' + serial --speed=19200 --unit=0 --word=8 --parity=no --stop=1; + terminal_input serial; + terminal_output serial + ''; + + # Configure compatiblity with host GRUB. + boot.loader.grub.device = "nodev"; + boot.loader.timeout = 10; + + # Tools commonly used by Linode support to debug issues. + environment.systemPackages = with pkgs; [ + inetutils + mtr + sysstat + ]; +} diff --git a/nixos/extras/platform/proxmox-ct.nix b/nixos/extras/platform/proxmox-ct.nix new file mode 100644 index 00000000..6d0af780 --- /dev/null +++ b/nixos/extras/platform/proxmox-ct.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ + + ]; + + # Fix multiple agetty instances being spawned on the same terminal. + systemd.services."getty@".unitConfig = { + ConditionVirtualization = "!lxc"; + }; + + # Fix "unable to make '/' private mount: Permission denied" + nix.useSandbox = lib.mkForce false; + + # Fix device nodes being unavailable. + boot.postBootCommands = '' + # /dev/net/tun + # https://vroomtech.io/enable-tuntap-in-a-proxmox-lxc-container/ + if [ ! -c /dev/net/tun ]; then + mkdir -p /dev/net + mknod -m 666 /dev/net/tun c 10 200 + fi + + # /dev/fuse + # https://forum.proxmox.com/threads/kernel-module-fuse-for-lxc.24855/ + if [ ! -c /dev/fuse ]; then + mknod -m 666 /dev/fuse c 10 229 + fi + ''; +} diff --git a/nixos/extras/platform/proxmox-vm.nix b/nixos/extras/platform/proxmox-vm.nix new file mode 100644 index 00000000..42efa3fd --- /dev/null +++ b/nixos/extras/platform/proxmox-vm.nix @@ -0,0 +1,6 @@ +{ config, lib, pkgs, ...}: { + imports = [ + + ./grub.nix + ]; +} diff --git a/nixos/extras/platform/raspberry-pi-2.nix b/nixos/extras/platform/raspberry-pi-2.nix new file mode 100644 index 00000000..64ad470e --- /dev/null +++ b/nixos/extras/platform/raspberry-pi-2.nix @@ -0,0 +1,27 @@ +# OUT OF DATE! + +{ config, pkgs, lib, ... }: + +{ + # NixOS wants to enable GRUB by default + boot.loader.grub.enable = false; + # Enables the generation of /boot/extlinux/extlinux.conf + boot.loader.generic-extlinux-compatible.enable = true; + + boot.kernelPackages = pkgs.linuxPackages_latest; + + # !!! This is only for ARMv6 / ARMv7. Don't enable this on AArch64, cache.nixos.org works there. + nix.binaryCaches = lib.mkForce [ "http://nixos-arm.dezgeg.me/channel" ]; + nix.binaryCachePublicKeys = [ "nixos-arm.dezgeg.me-1:xBaUKS3n17BZPKeyxL4JfbTqECsT+ysbDJz29kLFRW0=%" ]; + + fileSystems."/boot" = { + device = config.machine.fsdevices.boot; + fsType = "vfat"; + }; + + boot.tmpOnTmpfs = lib.mkForce false; + fileSystems."/tmp" = { + device = config.machine.fsdevices.tmp; + fsType = "ext4"; + }; +} diff --git a/nixos/extras/platform/raspberry-pi-3.nix b/nixos/extras/platform/raspberry-pi-3.nix new file mode 100644 index 00000000..aaf06783 --- /dev/null +++ b/nixos/extras/platform/raspberry-pi-3.nix @@ -0,0 +1,78 @@ +{ config, pkgs, lib, ... }: + +let + bootConfig = pkgs.writeTextFile { + name = "config.txt"; + text = '' + # managed by NixOS + + kernel=u-boot-rpi3.bin + + # Boot in 64-bit mode. + arm_control=0x200 + + # U-Boot used to need this to work, regardless of whether UART is actually used or not. + # TODO: check when/if this can be removed. + enable_uart=1 + + # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel + # when attempting to show low-voltage or overtemperature warnings. + avoid_warnings=1 + ''; + }; + +in { + options = with lib; { + raspberryPi = { + firmwareFS = { + device = mkOption { + type = types.path; + default = "/dev/mmcblk0p1"; + description = ''Device containing the firmware filesystem.''; + }; + }; + }; + }; + + config = { + # NixOS wants to enable GRUB by default + boot.loader.grub.enable = false; + # Enables the generation of /boot/extlinux/extlinux.conf + boot.loader.generic-extlinux-compatible.enable = true; + # Run the latest kernel (for some reason). + boot.kernelPackages = pkgs.linuxPackages_latest; + # We have a pitiful amount of RAM, so don't waste it on something that could instead by backed by disk. + boot.tmpOnTmpfs = lib.mkForce false; + # Only pull in the needed xorg video driver (otherwise it tries to add irrelevant drivers e.g. VMware, which fails to build). + services.xserver.videoDrivers = ["fbdev"]; + # nixos manpages take forever to build, and they're not essential. + documentation.nixos.enable = false; + # Building things takes so long - don't throw build products away unnecessarily. + nix.gc.automatic = false; + # Fixes '[drm:vc4_bo_create [vc4]] *ERROR* Failed to allocate from CMA:' error when using VC4 hardware acceleration stack. + # https://salsa.debian.org/raspi-team/image-specs/issues/1 + boot.kernelParams = [ "cma=128M" ]; + + hardware.firmware = [ + pkgs.raspberrypiWirelessFirmware + ]; + + fileSystems."/boot/fw" = { + device = config.raspberryPi.firmwareFS.device; + fsType = "vfat"; + }; + + systemd.services.bootloader-config = { + description = "Bootloader configuration"; + wantedBy = [ "basic.target" ]; + requires = [ "boot-fw.mount" ]; + after = [ "boot-fw.mount" ]; + serviceConfig = { + Type = "oneshot"; + }; + script = '' + cp -L ${bootConfig} /boot/fw/config.txt + ''; + }; + }; +} diff --git a/nixos/extras/platform/wsl2/default.nix b/nixos/extras/platform/wsl2/default.nix new file mode 100644 index 00000000..a14df4ec --- /dev/null +++ b/nixos/extras/platform/wsl2/default.nix @@ -0,0 +1,55 @@ +{ lib, pkgs, config, modulesPath, ... }: + +with lib; +let + defaultUser = "kier"; + syschdemd = import ./syschdemd.nix { inherit lib pkgs config defaultUser; }; +in +{ + imports = [ + "${modulesPath}/profiles/minimal.nix" + ]; + + # WSL is closer to a container than anything else + boot.isContainer = true; + + environment.etc.hosts.enable = false; + environment.etc."wsl.conf".text = '' + [network] + generateResolvConf = false + ''; + + networking.dhcpcd.enable = false; + + users.users.root = { + shell = "${syschdemd}/bin/syschdemd"; + # Otherwise WSL fails to login as root with "initgroups failed 5" + extraGroups = [ "root" ]; + }; + + # Disable systemd units that don't make sense on WSL + systemd.services."serial-getty@ttyS0".enable = false; + systemd.services."serial-getty@hvc0".enable = false; + systemd.services."getty@tty1".enable = false; + systemd.services."autovt@".enable = false; + + networking.firewall.enable = false; + systemd.services.firewall.enable = false; + systemd.services.systemd-udevd.enable = false; + + # Don't allow emergency mode, because we don't have a console. + systemd.enableEmergencyMode = false; + + # seccomp not supported. + nix.extraOptions = "filter-syscalls = false"; + + # Avoid warnings from Perl when running nixos activation script on first login. + system.activationScripts = { + locale.text = '' + export LOCALE_ARCHIVE=${config.i18n.glibcLocales}/lib/locale/locale-archive + export LANG=${config.i18n.defaultLocale} + ''; + etc.deps = [ "locale" ]; + users.deps = [ "locale" ]; + }; +} diff --git a/nixos/extras/platform/wsl2/syschdemd.nix b/nixos/extras/platform/wsl2/syschdemd.nix new file mode 100644 index 00000000..29b7817f --- /dev/null +++ b/nixos/extras/platform/wsl2/syschdemd.nix @@ -0,0 +1,15 @@ +{ lib, pkgs, config, defaultUser, ... }: + +pkgs.substituteAll { + name = "syschdemd"; + src = ./syschdemd.sh; + dir = "bin"; + isExecutable = true; + + buildInputs = with pkgs; [ daemonize ]; + + inherit (pkgs) daemonize; + inherit defaultUser; + inherit (config.security) wrapperDir; + fsPackagesPath = lib.makeBinPath config.system.fsPackages; +} diff --git a/nixos/extras/platform/wsl2/syschdemd.sh b/nixos/extras/platform/wsl2/syschdemd.sh new file mode 100644 index 00000000..4082a82d --- /dev/null +++ b/nixos/extras/platform/wsl2/syschdemd.sh @@ -0,0 +1,33 @@ +#! @shell@ + +set -e + +sw="/nix/var/nix/profiles/system/sw/bin" +systemPath=`${sw}/readlink -f /nix/var/nix/profiles/system` + +# Needs root to work +if [[ $EUID -ne 0 ]]; then + echo "[ERROR] Requires root! :( Make sure the WSL default user is set to root" + exit 1 +fi + +if [ ! -e "/run/current-system" ]; then + /nix/var/nix/profiles/system/activate +fi + +if [ ! -e "/run/systemd.pid" ]; then + PATH=/run/current-system/systemd/lib/systemd:@fsPackagesPath@ \ + LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive \ + @daemonize@/bin/daemonize /run/current-system/sw/bin/unshare -fp --mount-proc systemd + /run/current-system/sw/bin/pgrep -xf systemd > /run/systemd.pid +fi + +$sw/chown @defaultUser@:tty $($sw/tty) || true + +workdir="$PWD" +if [ "$($sw/basename "$workdir")" = system32 ]; then + workdir=$($sw/getent passwd @defaultUser@ | $sw/cut -d: -f6) +fi + +userShell=$($sw/getent passwd @defaultUser@ | $sw/cut -d: -f7) +exec $sw/nsenter -t $(< /run/systemd.pid) -p -m --wd="$workdir" -- @wrapperDir@/su -s $userShell @defaultUser@ "$@" diff --git a/nixos/extras/tiny.nix b/nixos/extras/tiny.nix new file mode 100644 index 00000000..c182d491 --- /dev/null +++ b/nixos/extras/tiny.nix @@ -0,0 +1,43 @@ +{ config, pkgs, lib, ... }: { + boot.plymouth.enable = lib.mkForce false; + fonts.fontconfig.enable = lib.mkForce false; + programs.command-not-found.enable = lib.mkForce false; + services.udisks2.enable = lib.mkForce false; + services.timesyncd.enable = lib.mkForce false; + services.atd.enable = lib.mkForce false; + services.syncthing.enable = lib.mkForce false; + security.pam.services.su.forwardXAuth = lib.mkForce false; + xdg.mime.enable = lib.mkForce false; + nix.gc.automatic = lib.mkForce false; + documentation = { + enable = lib.mkForce false; + nixos.enable = lib.mkForce false; + dev.enable = lib.mkForce false; + man.enable = lib.mkForce false; + info.enable = lib.mkForce false; + doc.enable = lib.mkForce false; + }; + + # Disable optional features of some packages. + nixpkgs.overlays = [(self: super: { + gnupg = super.gnupg.override { + libusb1 = null; + openldap = null; + pcsclite = null; + }; + nix = super.nix.override { + withLibseccomp = false; + withAWS = false; + }; + rng-tools = super.rng-tools.override { + withPkcs11 = false; + }; + udisks = super.udisks.override { + xfsprogs = null; + f2fs-tools = null; + btrfs-progs = null; + nilfs-utils = null; + ntfs3g = null; + }; + })]; +} diff --git a/nixos/extras/wifi.nix b/nixos/extras/wifi.nix new file mode 100644 index 00000000..e5c4bae7 --- /dev/null +++ b/nixos/extras/wifi.nix @@ -0,0 +1,10 @@ +{ config, pkgs, lib, ... }: + +{ + networking.wireless = { + enable = true; + userControlled.enable = true; + networks = import ../../secret/wifi-networks.nix; + }; + environment.systemPackages = [ pkgs.wpa_supplicant_gui ]; +} diff --git a/nixos/lib/boinc-fhs.nix b/nixos/lib/boinc-fhs.nix deleted file mode 100644 index 6a812fc6..00000000 --- a/nixos/lib/boinc-fhs.nix +++ /dev/null @@ -1,125 +0,0 @@ -{config, lib, pkgs, ...}: - -with lib; - -let - cfg = config.services.boinc-fhs; - allowRemoteGuiRpcFlag = optionalString cfg.allowRemoteGuiRpc "--allow_remote_gui_rpc"; - - fhsEnv = pkgs.buildFHSUserEnv { - name = "boinc-fhs-env"; - targetPkgs = _: [ cfg.package ] ++ cfg.extraEnvPackages; - runScript = "/bin/boinc_client"; - }; - fhsEnvExecutable = "${fhsEnv}/bin/${fhsEnv.name}"; - -in - { - options.services.boinc-fhs = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable the BOINC distributed computing client. If this - option is set to true, the boinc_client daemon will be run as a - background service. The boinccmd command can be used to control the - daemon. - ''; - }; - - package = mkOption { - type = types.package; - default = pkgs.boinc; - defaultText = "pkgs.boinc"; - description = '' - Which BOINC package to use. - ''; - }; - - dataDir = mkOption { - type = types.path; - default = "/var/lib/boinc"; - description = '' - The directory in which to store BOINC's configuration and data files. - ''; - }; - - allowRemoteGuiRpc = mkOption { - type = types.bool; - default = false; - description = '' - If set to true, any remote host can connect to and control this BOINC - client (subject to password authentication). If instead set to false, - only the hosts listed in dataDir/remote_hosts.cfg will be allowed to - connect. - - See also: - ''; - }; - - extraEnvPackages = mkOption { - type = types.listOf types.package; - default = []; - example = "[ pkgs.virtualbox ]"; - description = '' - Additional packages to make available in the environment in which - BOINC will run. Common choices are: - - - pkgs.virtualbox: - The VirtualBox virtual machine framework. Required by some BOINC - projects, such as ATLAS@home. - - - pkgs.ocl-icd: - OpenCL infrastructure library. Required by BOINC projects that use - OpenCL, in addition to a device-specific OpenCL driver. - - - pkgs.linuxPackages.nvidia_x11: - Provides CUDA libraries. Required by BOINC projects that use - CUDA. Note that this requires an NVIDIA graphics device to be - present on the system. - - Additionally, provides OpenCL drivers for NVIDIA GPUs. - pkgs.ocl-icd is needed in addition to this - package when using its OpenCL functionality. - - - ''; - }; - }; - - config = mkIf cfg.enable { - environment.systemPackages = [cfg.package]; - - users.users.boinc = { - createHome = false; - description = "BOINC Client"; - home = cfg.dataDir; - isSystemUser = true; - }; - - systemd.services.boinc = { - description = "BOINC Client"; - after = ["network.target" "local-fs.target"]; - wantedBy = ["multi-user.target"]; - preStart = '' - mkdir -p ${cfg.dataDir} - chown boinc ${cfg.dataDir} - ''; - script = '' - ${fhsEnvExecutable} --dir ${cfg.dataDir} --redirectio ${allowRemoteGuiRpcFlag} - ''; - serviceConfig = { - PermissionsStartOnly = true; # preStart must be run as root - User = "boinc"; - Nice = 10; - }; - }; - }; - - meta = { - maintainers = with lib.maintainers; [kierdavis]; - }; - } diff --git a/nixos/lib/ckb-next-animations-location.patch b/nixos/lib/ckb-next-animations-location.patch deleted file mode 100644 index 8e53685e..00000000 --- a/nixos/lib/ckb-next-animations-location.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/src/ckb/animscript.cpp b/src/ckb/animscript.cpp -index f49a64c..d7a3459 100644 ---- a/src/ckb/animscript.cpp -+++ b/src/ckb/animscript.cpp -@@ -30,7 +30,7 @@ QString AnimScript::path(){ - #ifdef __APPLE__ - return QDir(QApplication::applicationDirPath() + "/../Resources").absoluteFilePath("ckb-animations"); - #else -- return QDir("/usr/lib").absoluteFilePath("ckb-animations"); -+ return QDir(QApplication::applicationDirPath() + "/../libexec").absoluteFilePath("ckb-animations"); - #endif - } diff --git a/nixos/lib/ckb-next.nix b/nixos/lib/ckb-next.nix deleted file mode 100644 index e2742f34..00000000 --- a/nixos/lib/ckb-next.nix +++ /dev/null @@ -1,47 +0,0 @@ -{ stdenv, fetchFromGitHub, libudev, pkgconfig, qtbase, qmakeHook, zlib }: - -stdenv.mkDerivation rec { - version = "0.2.8"; - name = "ckb-next-${version}"; - - src = fetchFromGitHub { - owner = "mattanger"; - repo = "ckb-next"; - rev = "v${version}"; - sha256 = "0b3h1d54mdyfcx46zvsd7dfqf2656h4jjkiw044170gnfdzxjb3w"; - }; - - buildInputs = [ - libudev - qtbase - zlib - ]; - - nativeBuildInputs = [ - pkgconfig - qmakeHook - ]; - - patches = [ - ./ckb-next-animations-location.patch - ]; - - doCheck = false; - - installPhase = '' - runHook preInstall - - install -D --mode 0755 --target-directory $out/bin bin/ckb-daemon bin/ckb - install -D --mode 0755 --target-directory $out/libexec/ckb-animations bin/ckb-animations/* - - runHook postInstall - ''; - - meta = with stdenv.lib; { - description = "Driver and configuration tool for Corsair keyboards and mice"; - homepage = https://github.com/mattanger/ckb-next; - license = licenses.gpl2; - platforms = platforms.linux; - maintainers = with maintainers; [ kierdavis ]; - }; -} diff --git a/nixos/machines/coloris-win.nix b/nixos/machines/coloris-win.nix new file mode 100644 index 00000000..56c9c18c --- /dev/null +++ b/nixos/machines/coloris-win.nix @@ -0,0 +1,28 @@ +# Coloris is my workstation / gaming PC, built in 2016. +# It is named after the album "Coloris" by "she". + +{ config, lib, pkgs, ... }: + +{ + imports = [ + ../common + ../extras/platform/wsl2 + ../extras/devel.nix + ../extras/headless.nix + ]; + + # High-level configuration used by nixos/common/*.nix. + machine = { + name = "coloris"; + cpu = { + cores = 4; + }; + }; + + # Make sure to generate a new ID using: + # head -c4 /dev/urandom | od -A none -t x4 + # if this config is used as a reference for a new host! + networking.hostId = "bd7b28ce"; + + services.syncthing.enable = lib.mkForce false; +} diff --git a/nixos/machines/coloris.nix b/nixos/machines/coloris.nix index 895cce19..6bc8a4d3 100644 --- a/nixos/machines/coloris.nix +++ b/nixos/machines/coloris.nix @@ -1,42 +1,30 @@ -{ config, lib, pkgs, ... }: - -let - localPkgs = import ../../pkgs pkgs; +# Coloris is my workstation / gaming PC, built in 2016. +# It is named after the album "Coloris" by "she". - samba = import ../samba.nix; - sambaClient = samba.client { - host = "soton"; - port = 9092; - }; -in +{ config, lib, pkgs, ... }: { imports = [ ../common - ../extras/boot-efi.nix + ../extras/platform/efi.nix ../extras/boinc.nix ../extras/desktop - sambaClient + ../extras/wifi.nix + ../extras/audio.nix + ../extras/devel.nix ]; + # High-level configuration used by nixos/common/*.nix. machine = { name = "coloris"; - hostId = "db4d501a"; - vboxHost = true; - wifi = true; - bluetooth = true; - + ipv6-internet = false; cpu = { cores = 4; intel = true; }; - - fsdevices = { - root = "/dev/disk/by-uuid/059315e0-e130-475c-9d84-45e4ef750a6b"; - efi = "/dev/disk/by-uuid/6F09-65AE"; - swap = "/dev/disk/by-uuid/afd2e652-b34e-4543-95c3-e2fc5df22201"; + gpu = { + nvidia = true; }; - i3blocks = { cpuThermalZone = "thermal_zone2"; ethInterface = "enp4s0"; @@ -44,31 +32,51 @@ in }; }; - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbcore" "sd_mod" "sr_mod" ]; - powerManagement.cpuFreqGovernor = "ondemand"; - - hardware.ckb.enable = true; - hardware.ckb.package = pkgs.libsForQt5.callPackage ../lib/ckb-next.nix {}; - - # https://github.com/mattanger/ckb-next#linux - boot.kernelParams = [ "usbhid.quirks=0x1B1C:0x1B15:0x20000408,0x1B1C:0x1B2F:0x20000408" ]; - - services.xserver.xrandrHeads = ["DP-0" "HDMI-0"]; - - # Additional filesystems (LVM). + # Filesystems. + fileSystems."/" = { + device = "/dev/disk/by-uuid/059315e0-e130-475c-9d84-45e4ef750a6b"; + fsType = "ext4"; + options = ["noatime" "nodiratime"]; + }; fileSystems."/home" = { device = "/dev/disk/by-uuid/7ea83533-f78b-4deb-94ed-6bef5dbfa8e4"; fsType = "ext4"; options = ["noatime" "nodiratime"]; }; - fileSystems."/data" = { - device = "/dev/disk/by-uuid/c522b9a8-b534-428c-9e4e-6d297ed9dba4"; + fileSystems.boinc = { + mountPoint = config.services.boinc.dataDir; + device = "/dev/disk/by-uuid/f25c297c-46ff-45c6-96f0-d645931b3a67"; fsType = "ext4"; }; + swapDevices = [ { device = "/dev/disk/by-uuid/afd2e652-b34e-4543-95c3-e2fc5df22201"; } ]; + fileSystems.efi.device = "/dev/disk/by-uuid/6F09-65AE"; + systemd.services.boinc.after = [ "var-lib-boinc.mount" ]; + systemd.services.boinc.requires = [ "var-lib-boinc.mount" ]; - environment.systemPackages = [ - localPkgs.boincgpuctl - localPkgs.google-musicmanager - localPkgs.keybase - ]; + # Networking. + networking.wireless.interfaces = [ "wlp3s0" ]; + + # Make sure to generate a new ID using: + # head -c4 /dev/urandom | od -A none -t x4 + # if this config is used as a reference for a new host! + networking.hostId = "db4d501a"; + + # From nixos-generate-config. + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbcore" "sd_mod" "sr_mod" ]; + powerManagement.cpuFreqGovernor = "ondemand"; + + # Keyboard/mouse driver. + hardware.ckb-next.enable = true; + # https://github.com/mattanger/ckb-next#linux + boot.kernelParams = [ "usbhid.quirks=0x1B1C:0x1B15:0x20000408,0x1B1C:0x1B2F:0x20000408" ]; + + systemd.services.komi-server = { + script = "exec ${pkgs.python3}/bin/python -m http.server 9090"; + serviceConfig = { + User = "kier"; + Group = "users"; + WorkingDirectory = "/home/kier/checkouts/komi"; + }; + wantedBy = ["multi-user.target"]; + }; } diff --git a/nixos/machines/fingerbib.nix b/nixos/machines/fingerbib.nix new file mode 100644 index 00000000..4a07959a --- /dev/null +++ b/nixos/machines/fingerbib.nix @@ -0,0 +1,330 @@ +let + hist = import ../../hist.nix; + + torrentClient = { config, lib, pkgs, ... }: { + options.torrentClient = with lib; { + hostAddress = mkOption { type = types.str; }; + containerAddress = mkOption { type = types.str; }; + httpPort = mkOption { type = types.int; default = 8000; }; + vpn.configFile = mkOption { type = types.path; }; + vpn.username = mkOption { type = types.str; }; + vpn.password = mkOption { type = types.str; }; + vpn.hostName = mkOption { type = types.str; default = "vpn"; }; + }; + config = let + cfg = config.torrentClient; + vpnEndpoint = import (pkgs.runCommand "nordvpn-endpoint.nix" {} '' + echo "{" >> $out + awk '/^remote /{print "address=\""$2"\";port="$3";"}' < ${cfg.vpn.configFile} >> $out + awk '/^proto /{print "protocol=\""$2"\";"}' < ${cfg.vpn.configFile} >> $out + echo "}" >> $out + ''); + in { + networking.hosts."${vpnEndpoint.address}" = [cfg.vpn.hostName]; + containers.transmission = { + autoStart = true; + ephemeral = true; + privateNetwork = true; + enableTun = true; + hostAddress = cfg.hostAddress; + localAddress = cfg.containerAddress; + bindMounts."/downloads" = { + hostPath = "/data/media/torrents"; + isReadOnly = false; + }; + bindMounts."/var/lib/transmission" = { + hostPath = "/var/lib/transmission"; + isReadOnly = false; + }; + config = { + imports = [ + ../common/apps.nix + ../common/bugfixes.nix + ../common/env.nix + ../common/locale.nix + ../common/nix.nix + ../common/options.nix + ]; + machine.name = "transmission"; + machine.cpu.cores = 8; + networking.useDHCP = false; + networking.defaultGateway = { + address = cfg.hostAddress; + interface = "eth0"; + }; + networking.nameservers = hist.upstreamNameServers; + networking.hosts."${vpnEndpoint.address}" = [cfg.vpn.hostName]; + networking.firewall.enable = true; + networking.firewall.interfaces.eth0.allowedTCPPorts = [ cfg.httpPort ]; + services.openvpn.servers.vpn = { + config = '' + config "${cfg.vpn.configFile}" + dev tun-vpn + ''; + authUserPass = { inherit (cfg.vpn) username password; }; + }; + users.groups.media = config.users.groups.media; + services.transmission = { + enable = true; + home = "/var/lib/transmission"; + user = "transmission"; + group = "media"; + settings = { + download-dir = "/downloads"; + incomplete-dir-enabled = false; + rename-partial-files = true; + start-added-torrents = true; + trash-original-torrent-files = false; + watch-dir-enabled = false; + dht-enabled = true; + lpd-enabled = true; + pex-enabled = true; + utp-enabled = true; + encryption = 2; + speed-limit-up = 2000; + speed-limit-up-enabled = true; + speed-limit-down = 2000; + speed-limit-down-enabled = true; + alt-speed-up = 200; + alt-speed-down = 200; + alt-speed-enabled = false; # "turtle" mode + rpc-enabled = true; + rpc-bind-address = cfg.containerAddress; + rpc-port = cfg.httpPort; + rpc-whitelist-enabled = false; + rpc-authentication-required = false; + prefetch-enabled = true; + cache-size-mb = 100; + download-queue-enabled = false; + umask = 18; # decimal equiv of octal 022 + }; + }; + }; + }; + networking.firewall.extraCommands = '' + ip46tables --flush transmission-egress || ip46tables --new-chain transmission-egress + iptables --append transmission-egress --protocol ${vpnEndpoint.protocol} --destination ${vpnEndpoint.address} --destination-port ${builtins.toString vpnEndpoint.port} --jump ACCEPT + iptables --append transmission-egress --protocol icmp --icmp-type 8 --destination ${vpnEndpoint.address} --jump ACCEPT + ip46tables --append transmission-egress --jump REJECT + ip46tables --append FORWARD --in-interface ve-transmission --jump transmission-egress + ''; + networking.nat.internalInterfaces = [ "ve-transmission" ]; + hist.local.webServer.virtualHosts.torrents.locations."/".proxyPass = "http://${cfg.containerAddress}:${builtins.toString cfg.httpPort}/"; + }; + }; + + webServer = { config, lib, pkgs, ... }: let + cfg = config.hist.local.webServer; + defaultVirtualHost = name: { + listen = [ { addr = "[${hist.hosts.fingerbib.addresses.wg}]"; port = 80; } ]; + serverAliases = [ "${name}.hist" ]; + }; + in { + options.hist.local.webServer = with lib; { + virtualHosts = mkOption { type = types.attrsOf types.attrs; default = {}; }; + }; + config = { + services.nginx = { + enable = true; + virtualHosts = lib.mapAttrs (name: vh: defaultVirtualHost name // vh) cfg.virtualHosts; + }; + hist.local.webServer.virtualHosts.default = { + default = true; + locations."/".return = ''404 "no such virtual host"''; + }; + networking.firewall.interfaces.wg-hist.allowedTCPPorts = [ 80 ]; + }; + }; + + mediaServer = { config, lib, pkgs, ... }: { + services.jellyfin.enable = true; + hist.local.webServer.virtualHosts.media.locations."/".proxyPass = "http://localhost:8096/"; + hist.local.webServer.virtualHosts.media-lan = { + listen = [ { addr = "${hist.hosts.fingerbib.addresses.lan}"; port = 80; } ]; + serverName = "media"; + serverAliases = [ "media.fritz.box" ]; + default = true; + locations."/".proxyPass = "http://localhost:8096/"; + }; + networking.firewall.interfaces.br-lan.allowedTCPPorts = [ 80 ]; + }; + + /* + icinga = { config, lib, pkgs, ... }: { + services.icingaweb2 = { + enable = true; + virtualHost = "fingerbib-icinga"; + authentications.autologin.backend = "external"; + modules.monitoring.enable = true; + }; + services.nginx.virtualHosts."fingerbib-icinga" = { + listen = config.services.nginx.virtualHosts.default.listen; + locations."~ ^/index.php(.*)$".extraConfig = lib.mkAfter "fastcgi_param REMOTE_USER kier;"; + }; + }; + */ + + printServer = { config, lib, pkgs, ... }: { + config = { + services.printing = { + enable = true; + listenAddresses = ["localhost:631"]; + drivers = [ + pkgs.gutenprint + # pkgs.cups-brother-hl1110 + pkgs.hplip + ]; + }; + hist.local.webServer.virtualHosts.printing.locations."/".proxyPass = "http://localhost:631/"; + }; + }; + + print3dServer = { config, lib, pkgs, ... }: let + openboxConfig = pkgs.writeText "openbox-rc.xml" '' + + + + + + ${pkgs.xterm}/bin/xterm + + + + + yes + + + + + ''; + startupScript = pkgs.writeShellScript "autostart" '' + repetier-host + openbox --exit + ''; + in { + services.xrdp = { + enable = true; + defaultWindowManager = "exec ${pkgs.openbox}/bin/openbox --config-file ${openboxConfig} --startup ${startupScript}"; + }; + networking.firewall.allowedTCPPorts = [ config.services.xrdp.port ]; + hardware.opengl.enable = true; + users.users."3dprint".extraGroups = [ "dialout" ]; + users.users."3dprint".packages = with pkgs; [ + openbox + prusa-slicer + repetier-host + ]; + }; + +in { config, lib, pkgs, ... }: { + imports = [ + ../common + ../extras/boinc.nix + # ../extras/headless.nix + ../extras/platform/grub.nix + torrentClient + webServer + mediaServer + printServer + print3dServer + ]; + + # High-level configuration used by nixos/common/*.nix. + machine = { + name = "fingerbib"; + cpu = { + cores = 8; + intel = true; + }; + }; + # Make sure to generate a new ID using: + # head -c4 /dev/urandom | od -A none -t x4 + # if this config is used as a reference for a new host! + networking.hostId = "74e71470"; + + powerManagement.cpuFreqGovernor = "ondemand"; + + # Need at least kernel 5.8 for container names > 11 characters (needs interface altnames). + boot.kernelPackages = + if builtins.compareVersions pkgs.linuxPackages.kernel.version "5.8" <= 0 + then pkgs.linuxPackages_5_10 + else pkgs.linuxPackages; + + # Filesystems: + boot.supportedFilesystems = ["zfs"]; + fileSystems = { + "/" = { device = "fingerbib/os/root"; fsType = "zfs"; }; + "/boot" = { device = "/dev/disk/by-partlabel/fb_boot1"; fsType = "ext4"; }; + "/data" = { device = "fingerbib/data/data"; fsType = "zfs"; }; + "/data/media" = { device = "fingerbib/data/media"; fsType = "zfs"; }; + "/home" = { device = "fingerbib/data/home"; fsType = "zfs"; }; + "/nix/store" = { device = "fingerbib/os/nix-store"; fsType = "zfs"; }; + "/tmp" = { device = "fingerbib/transient/tmp"; fsType = "zfs"; }; + "/var/cache" = { device = "fingerbib/transient/cache"; fsType = "zfs"; }; + "/var/log" = { device = "fingerbib/os/log"; fsType = "zfs"; }; + }; + boot.loader.grub.device = "/dev/disk/by-id/ata-ST2000DL003-9VT166_5YD5YEPX"; + swapDevices = [ + { device = "/dev/disk/by-partlabel/fb_swap"; } + ]; + boot.tmpOnTmpfs = false; + + # Networking: + networking.useDHCP = false; + services.udev.extraRules = ''ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="44:37:e6:bd:b8:54", NAME="en-lan"''; + networking.bridges.br-lan.interfaces = [ "en-lan" ]; + networking.interfaces.br-lan.ipv4.addresses = [{ + address = hist.hosts.fingerbib.addresses.lan; + prefixLength = hist.networks.lan.prefixLength; + }]; + networking.defaultGateway = { + address = "${hist.networks.lan.prefix}.1"; + interface = "br-lan"; + }; + networking.nameservers = [ config.networking.defaultGateway.address ]; + networking.nat.enable = true; + networking.nat.externalInterface = "br-lan"; + + torrentClient = { + hostAddress = "${hist.networks.pointToPoint.prefix}.1"; + containerAddress = "${hist.networks.pointToPoint.prefix}.2"; + vpn = import ../../secret/nordvpn // { hostName = "nordvpn"; }; + }; + + users.groups.media = { + gid = 398; + }; + users.groups."3dprint" = { + gid = 397; + }; + users.users.kier.extraGroups = ["media" "3dprint"]; + users.users.media = { + description = "Media Services"; + uid = config.users.groups.media.gid; + group = "media"; + home = "/data/media"; + isSystemUser = true; + useDefaultShell = true; + }; + users.users."3dprint" = { + description = "3D Printing Services"; + uid = config.users.groups."3dprint".gid; + group = "3dprint"; + home = "/data/3dprint"; + isSystemUser = true; + useDefaultShell = true; + hashedPassword = (import ../../secret/passwords.nix).user.fingerbib-3dprint.hashed; + }; + users.users.transmission = { + description = "Transmission BitTorrent user"; + uid = config.ids.uids.transmission; + group = "media"; + home = "/data/media/torrents"; + isSystemUser = true; + useDefaultShell = true; + }; + + # Allow media user to create hardlinks to files owned by transmission. + boot.kernel.sysctl."fs.protected_hardlinks" = 0; +} diff --git a/nixos/machines/nocturn.nix b/nixos/machines/nocturn.nix deleted file mode 100644 index cb24f3a8..00000000 --- a/nixos/machines/nocturn.nix +++ /dev/null @@ -1,129 +0,0 @@ -let - samba = import ../samba.nix; - - postgresql = { config, lib, pkgs, ... }: { - services.postgresql = { - enable = true; - dataDir = "/srv/postgresql"; - }; - }; - - quassel = { config, lib, pkgs, ... }: { - networking.firewall.allowedTCPPorts = [ 4242 ]; - - services.quassel = { - enable = true; - dataDir = "/srv/quassel"; - interfaces = [ "0.0.0.0" ]; - portNumber = 4242; - }; - - systemd.services.quassel.after = [ "network.target" "network-online.target" "postgresql.service" ]; - }; - - transmission = { config, lib, pkgs, ... }: { - networking.firewall.allowedTCPPorts = [9091 51413]; - networking.firewall.allowedUDPPorts = [6771 51413]; - - users.users.kier.extraGroups = ["transmission"]; - - services.transmission.enable = true; - services.transmission.port = 9091; # web interface - services.transmission.settings = import ../transmission-settings.nix // { - download-dir = "/shares/torrents"; - }; - - fileSystems."/var/lib/transmission" = { - device = "/srv/transmission"; - options = ["bind"]; - }; - - systemd.services.transmission.serviceConfig.ExecStartPre = lib.mkForce ""; - systemd.services.quassel.after = [ "network.target" "network-online.target" ]; - }; - - http = { config, lib, pkgs, ... }: { - services.httpd = { - enable = true; - adminAddr = "kierdavis@gmail.com"; - documentRoot = "/srv/http"; - listen = [ { ip = "*"; port = 80; } ]; - }; - - networking.firewall.allowedTCPPorts = [ 80 ]; - - users.users.kier.extraGroups = [ "wwwrun" ]; - }; - - hydra = { config, lib, pkgs, ... }: { - services.hydra = { - enable = true; - dbi = "dbi:Pg:dbname=hydra;user=hydra;"; - extraEnv = { - HYDRA_DATA = "/srv/hydra"; - }; - listenHost = "*"; - port = 3000; - hydraURL = "http://soton:9094/"; - notificationSender = "hydra@nocturn"; - }; - - networking.firewall.allowedTCPPorts = [ 3000 ]; - }; - -in - -{ config, lib, pkgs, ... }: - -{ - imports = [ - ../common - ../extras/boot-grub.nix - ../extras/headless.nix - samba.server - postgresql - quassel - transmission - http - hydra - ]; - - machine = { - name = "nocturn"; - hostId = "ee9e88c0"; - vboxHost = false; - wifi = false; - bluetooth = false; - - cpu = { - cores = 2; - intel = true; - }; - - fsdevices = { - root = "/dev/disk/by-uuid/862fe5b3-ab0a-4719-a575-f604c5c1346f"; - grub = "/dev/disk/by-id/wwn-0x50014ee6006f9b4d"; - swap = "/dev/disk/by-uuid/e907b34a-06ff-481b-9bcd-a428fa973db0"; - }; - }; - - boot.initrd.availableKernelModules = [ "ata_generic" "uhci_hcd" "ehci_pci" "ahci" "sd_mod" ]; - powerManagement.cpuFreqGovernor = "ondemand"; - - # Don't go to sleep when lid is closed. - services.logind.extraConfig = "HandleLidSwitch=ignore"; - - # Additional filesystems (LVM). - fileSystems."/home" = { - device = "/dev/disk/by-uuid/d9f15852-c0bc-49a6-8112-ab36b2ab5a8e"; - fsType = "ext4"; - }; - fileSystems."/shares" = { - device = "/dev/disk/by-uuid/876ef70b-0794-49c5-840b-11dcb2cec964"; - fsType = "ext4"; - }; - fileSystems."/srv" = { - device = "/dev/disk/by-uuid/1e20b7fa-e493-404d-bc6c-84f9922a4f0b"; - fsType = "ext4"; - }; -} diff --git a/nixos/machines/ouroboros.nix b/nixos/machines/ouroboros.nix deleted file mode 100644 index 0a12e191..00000000 --- a/nixos/machines/ouroboros.nix +++ /dev/null @@ -1,53 +0,0 @@ -let - samba = import ../samba.nix; - sambaClient = samba.client { - host = "soton"; - port = 9092; - }; -in - -{ config, lib, pkgs, ... }: - -{ - imports = [ - ../common - ../extras/boot-efi.nix - ../extras/desktop - sambaClient - ]; - - machine = { - name = "ouroboros"; - hostId = "8e8cad01"; - vboxHost = true; - wifi = true; - bluetooth = true; - - cpu = { - cores = 4; - intel = true; - }; - - fsdevices = { - root = "/dev/disk/by-uuid/97678c8a-538a-4034-b725-72ced3f0759d"; - efi = "/dev/disk/by-uuid/DBAA-F84C"; - swap = "/dev/disk/by-uuid/09cf9635-7fab-41a1-9abc-32b474bc101d"; - }; - - i3blocks = { - cpuThermalZone = "thermal_zone0"; - ethInterface = "enp4s0"; - wlanInterface = "wlp3s0"; - }; - }; - - boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" "sr_mod" ]; - powerManagement.cpuFreqGovernor = "ondemand"; - - # Additional filesystems (ZFS). - fileSystems."/home" = { - device = "ouroboros_lin_home/home"; - fsType = "zfs"; - options = ["noatime" "nodiratime"]; - }; -} diff --git a/nixos/machines/ptolemy.nix b/nixos/machines/ptolemy.nix new file mode 100644 index 00000000..4ad4b788 --- /dev/null +++ b/nixos/machines/ptolemy.nix @@ -0,0 +1,67 @@ +{ config, lib, pkgs, ... }: { + imports = [ + ../common + ../extras/headless.nix + ../extras/platform/grub.nix + ../extras/platform/hp.nix + ]; + + # High-level configuration used by nixos/common/*.nix. + machine = { + name = "ptolemy"; + cpu = { + cores = 32; + intel = true; + }; + }; + + powerManagement.cpuFreqGovernor = "ondemand"; + + networking = { + # Don't auto-configure unspecified interfaces. + useDHCP = false; + interfaces.eno1 = { + useDHCP = true; + }; + # bridges.guest-bridge = {}; + + # Make sure to generate a new ID using: + # head -c4 /dev/urandom | od -A none -t x4 + # if this config is used as a reference for a new host! + hostId = "0d574bdb"; + }; + + boot.supportedFilesystems = ["zfs"]; + fileSystems = { + "/" = { device = "ptolemy/os/root"; fsType = "zfs"; }; + "/boot" = { device = "/dev/disk/by-partlabel/pto_a_boot"; fsType = "ext4"; }; + "/home" = { device = "ptolemy/data/home"; fsType = "zfs"; }; + "/nix/store" = { device = "ptolemy/os/nix-store"; fsType = "zfs"; }; + "/tmp" = { device = "ptolemy/transient/tmp"; fsType = "zfs"; }; + "/var/cache" = { device = "ptolemy/transient/cache"; fsType = "zfs"; }; + "/var/lib/containers" = { device = "ptolemy/os/containers"; fsType = "zfs"; }; + "/var/lib/sum/baseline" = { device = "ptolemy/transient/hpsum-baseline"; fsType = "zfs"; }; + "/var/log" = { device = "ptolemy/os/log"; fsType = "zfs"; }; + }; + boot.loader.grub.device = "/dev/sda"; + swapDevices = [ + { device = "/dev/disk/by-partlabel/pto_a_swap"; } + { device = "/dev/disk/by-partlabel/pto_b_swap"; } + ]; + boot.tmpOnTmpfs = false; + systemd.services."${config.virtualisation.oci-containers.backend}-hpsum" = { + requires = [ "var-lib-sum-baseline.mount" ]; + after = [ "var-lib-sum-baseline.mount" ]; + }; + + virtualisation.podman.enable = true; + virtualisation.oci-containers.backend = "podman"; + + services.icingaweb2 = { + enable = true; + timezone = config.time.timeZone; + }; + + # TODO TODO TODO + networking.firewall.enable = false; +} diff --git a/nixos/machines/saelli.nix b/nixos/machines/saelli.nix new file mode 100644 index 00000000..1993e124 --- /dev/null +++ b/nixos/machines/saelli.nix @@ -0,0 +1,71 @@ +# Saelli is a Thinkpad T440s, bought second-hand in 2018. +# It is named after the song "Saelli" by "Corpo-Mente". + +let + network = import ../../network.nix; + +in { config, lib, pkgs, ... }: + +{ + imports = [ + ../common + ../extras/platform/efi.nix + ../extras/desktop + ../extras/wifi.nix + ../extras/audio.nix + ../extras/low-power.nix + ../extras/clickpad.nix + ../extras/devel.nix + ]; + + # High-level configuration used by nixos/common/*.nix. + machine = { + name = "saelli"; + ipv6-internet = false; + cpu = { + cores = 4; + intel = true; + }; + i3blocks = { + cpuThermalZone = "thermal_zone0"; + ethInterface = "enp4s25"; + wlanInterface = "wlp3s0"; + batteries = [ "BAT0" "BAT1" ]; + }; + }; + + # Filesystems. + fileSystems."/" = { + device = "/dev/disk/by-uuid/41a55911-8a7e-45f3-8a55-116b9abb4f6e"; + fsType = "ext4"; + options = ["noatime" "nodiratime"]; + }; + fileSystems."/home" = { + device = "/dev/disk/by-uuid/9cba21a0-ced6-4511-bfd2-5e576d02915a"; + fsType = "ext4"; + options = ["noatime" "nodiratime"]; + }; + swapDevices = [ { device = "/dev/disk/by-uuid/d9939f0d-3e6c-439e-a308-e1b40a254b9f"; } ]; + fileSystems.efi.device = "/dev/disk/by-uuid/5036-1CC7"; + + # Networking. + networking.wireless.interfaces = [ "wlp3s0" ]; + + # Make sure to generate a new ID using: + # head -c4 /dev/urandom | od -A none -t x4 + # if this config is used as a reference for a new host! + networking.hostId = "7628944b"; + + # From nixos-generate-config. + boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; + powerManagement.cpuFreqGovernor = "powersave"; + + environment.systemPackages = with pkgs; [ + (writeShellScriptBin "eduroam" '' + set -o errexit -o nounset + sudo ${gnused}/bin/sed -i -E '/${lib.concatStringsSep "|" config.networking.nameservers}/d' /etc/resolv.conf + '') + ]; + + hardware.firmware = with pkgs; [ firmwareLinuxNonfree ]; # wifi driver +} diff --git a/nixos/samba.nix b/nixos/samba.nix deleted file mode 100644 index c27359a6..00000000 --- a/nixos/samba.nix +++ /dev/null @@ -1,75 +0,0 @@ -let - secrets = import ./secrets.nix; - - credentials = { - user = "kier"; - pass = secrets.sambaPassword; - }; -in - -rec { - shares = { - music = { - comment = "Music"; - writeable = true; - }; - documents = { - comment = "Documents"; - writeable = true; - }; - torrents = { - comment = "Torrent downloads"; - writeable = false; - }; - archive = { - comment = "Archive"; - writeable = true; - }; - misc = { - comment = "Miscellaneous"; - writeable = true; - }; - }; - - server = { config, lib, pkgs, ... }: { - networking.firewall.allowedTCPPorts = [ 445 ]; - services.samba = { - enable = true; - shares = lib.mapAttrs (name: share: share // { - path = "/shares/${name}"; - browseable = true; - "valid users" = [credentials.user]; - }) shares; - }; - fileSystems = lib.mapAttrs (name: share: { - mountPoint = "/mnt/nocturn/${name}"; - device = "/shares/${name}"; - options = ["bind"]; - }) shares; - }; - - client = - { host, port, selectedShares ? shares }: - { config, lib, pkgs, ... }: - let - credentialsFile = pkgs.writeText "samba-credentials" '' - username=${credentials.user} - password=${credentials.pass} - domain=WORKGROUP - ''; - in { - fileSystems = lib.mapAttrs (name: share: { - mountPoint = "/mnt/nocturn/${name}"; - device = "//${host}/${name}"; - fsType = "cifs"; - options = [ - "credentials=${credentialsFile}" # file containing the username/password for login - "port=${toString port}" # which port on the host to connect to - "noauto" # don't mount at boot - "x-systemd.automount" # mount automatically when accessed - "x-systemd.idle-timeout=10min" # unmount automatically when not used for 10 minutes - "actimeo=60" # amount of time (seconds) that file metadata is cached on the client before re-requesting it from the server - ]; - }) selectedShares; - }; -} diff --git a/nixos/transmission-settings.nix b/nixos/transmission-settings.nix deleted file mode 100644 index e9edc724..00000000 --- a/nixos/transmission-settings.nix +++ /dev/null @@ -1,86 +0,0 @@ -{ - ### BANDWIDTH ### - alt-speed-enabled = false; - #alt-speed-up # in kB/s, default = 50 - #alt-speed-down # in kB/s, default = 50 - speed-limit-down = 2000; # in kB/s, default = 100 - speed-limit-down-enabled = true; - speed-limit-up = 2000; # in kB/s, default = 100 - speed-limit-up-enabled = true; - #upload-slots-per-torrent # default = 14 - - ### BLOCKLISTS ### - #blocklist-url - blocklist-enabled = false; - - ### FILES AND LOCATIONS ### - #download-dir = "/var/lib/transmission/downloads"; - #incomplete-dir - incomplete-dir-enabled = false; - preallocation = 1; # 0 = Off, 1 = Fast, 2 = Full - rename-partial-files = true; - start-added-torrents = true; - trash-original-torrent-files = false; - #umask - #watch-dir = "/var/lib/transmission/torrents"; - watch-dir-enabled = false; - - ### MISC ### - #cache-size-mb # MB, default = 4 - dht-enabled = true; # Distributed Hash Table - encryption = 2; # 0 = allow, 1 = prefer, 2 = require - #lazy-bitfield-enabled - lpd-enabled = true; - message-level = 2; # 0 = none, 1 = error, 2 = info, 3 = debug - pex-enabled = true; # Peer Exchange - prefetch-enabled = true; - #scrape-paused-torrents-enabled - script-torrent-done-enabled = false; - #script-torrent-done-filename - utp-enabled = true; - - ### PEERS ### - #bind-address-ipv4 - #bind-address-ipv6 - #peer-congestion-algorithm - #peer-id-ttl-hours - peer-limit-global = 300; - peer-limit-per-torrent = 50; - #peer-socket-tos # default, lowcost, throughput, lowdelay, reliability - - ### PEER PORT ### - peer-port = 51413; - #peer-port-random-high - #peer-port-random-low - peer-port-random-on-start = false; - port-forwarding-enabled = true; - - ### QUEUEING ### - download-queue-enabled = false; - download-queue-size = 5; - queue-stalled-enabled = true; - queue-stalled-minutes = 30; - seed-queue-enabled = false; - seed-queue-size = 10; - - ### RPC ### - rpc-authentication-required = true; - rpc-bind-address = "0.0.0.0"; - rpc-enabled = true; - rpc-password = (import ./secrets.nix).transmissionWebPassword; - rpc-port = 9091; - #rpc-url - rpc-username = "kier"; - rpc-whitelist = "127.0.0.1,192.168.*.*"; # comma separated - rpc-whitelist-enabled = false; - - ### SCHEDULING ### - alt-speed-time-enabled = false; - #alt-speed-time-begin - #alt-speed-time-end - #alt-speed-time-day - #idle-seeding-limit - idle-seeding-limit = false; - #ratio-limit - ratio-limit-enabled = false; -} diff --git a/nixpkgs b/nixpkgs new file mode 160000 index 00000000..543d4eca --- /dev/null +++ b/nixpkgs @@ -0,0 +1 @@ +Subproject commit 543d4ecac25e0bd4d24d71a711c8d587803b7b75 diff --git a/pkgs/.gitignore b/pkgs/.gitignore deleted file mode 100644 index b2be92b7..00000000 --- a/pkgs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -result diff --git a/pkgs/admesh/default.nix b/pkgs/admesh/default.nix new file mode 100644 index 00000000..f45436df --- /dev/null +++ b/pkgs/admesh/default.nix @@ -0,0 +1,18 @@ +{ autoreconfHook, fetchFromGitHub, git, stdenv }: + +stdenv.mkDerivation rec { + name = "admesh-${version}"; + version = "0.98.3"; + + src = fetchFromGitHub { + owner = "admesh"; + repo = "admesh"; + rev = "v${version}"; + sha256 = "188jb1g5jyxkhlsv656m3fq0n4aj7y6nx69v0hc2j6rcfg878iqb"; + }; + + nativeBuildInputs = [ autoreconfHook ]; + preBuild = '' + touch AUTHORS ChangeLog + ''; +} diff --git a/pkgs/archiveman/default.nix b/pkgs/archiveman/default.nix deleted file mode 100644 index f08579b3..00000000 --- a/pkgs/archiveman/default.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ python35Packages, udftools }: - -python35Packages.buildPythonApplication rec { - name = "archiveman-${version}"; - version = "0.1"; - - src = ./src; - - propagatedBuildInputs = with python35Packages; [ - docopt - sqlalchemy - udftools - ]; - - doCheck = false; -} diff --git a/pkgs/archiveman/src/archiveman/__init__.py b/pkgs/archiveman/src/archiveman/__init__.py deleted file mode 100644 index 3d411eea..00000000 --- a/pkgs/archiveman/src/archiveman/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from archiveman.main import main diff --git a/pkgs/archiveman/src/archiveman/archivecopy.py b/pkgs/archiveman/src/archiveman/archivecopy.py deleted file mode 100644 index 8eef3e35..00000000 --- a/pkgs/archiveman/src/archiveman/archivecopy.py +++ /dev/null @@ -1,23 +0,0 @@ -class Copy(object): - @classmethod - def enumerate(_, archive, st): - """Return all known copies of an archive.""" - if st.contains(archive): - yield StoreCopy(archive, st) - -class StoreCopy(object): - """A copy of an archive present in the local store.""" - - is_remote = False - - def __init__(self, archive, st): - self.archive = archive - self.st = st - - @property - def is_healthy(self): - return self.st.is_healthy(self.archive) - - @property - def filename(self): - return self.st.filename(self.archive) diff --git a/pkgs/archiveman/src/archiveman/database.py b/pkgs/archiveman/src/archiveman/database.py deleted file mode 100644 index 8d7c044b..00000000 --- a/pkgs/archiveman/src/archiveman/database.py +++ /dev/null @@ -1,12 +0,0 @@ -import logging -from archiveman import models -from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker - -class Database(object): - def __init__(self, location): - self.logger = logging.getLogger("archiveman.database") - self.engine = create_engine(location) - self.make_session = sessionmaker(bind = self.engine) - - models.init(self.engine) diff --git a/pkgs/archiveman/src/archiveman/disc.py b/pkgs/archiveman/src/archiveman/disc.py deleted file mode 100644 index c7012473..00000000 --- a/pkgs/archiveman/src/archiveman/disc.py +++ /dev/null @@ -1,109 +0,0 @@ -import contextlib -import random -from archiveman import models, udflabel, util - -DEFAULT_LVID = "UNTITLED ARCHIVEMAN VOLUME" -VID_PREFIX = "ARCHIVEMAN00." - -def random_vid(): - chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - return VID_PREFIX + "".join(random.choice(chars) for i in range(16)) - -def detect_disc(filename, session): - _, vid = udflabel.parse_udf_labels(filename) - if vid is None: - print("archiveman: failed to extract volume ID from UDF image at {}".format(filename)) - util.abort() - disc = session.query(models.Disc).filter_by(volume_id = vid).first() - if disc is None: - print("archiveman: invalid volume ID in UDF image at {}".format(filename)) - util.abort() - return disc - -@contextlib.contextmanager -def mount(udffile, mountpoint = "/tmp/archiveman-mount"): - util.ensure_dir(mountpoint) - cmd = ["mount", udffile, mountpoint] - with util.execute(cmd): - pass - yield mountpoint - cmd = ["umount", udffile] - with util.execute(cmd): - pass - -def do_create(args, db, st): - session = db.make_session() - - udf_file = args[""] - - if args["--label"]: - lvid = args["--label"] - else: - lvid = DEFAULT_LVID - - if args["--size"]: - size = int(args["--size"]) - else: - size = 25000000000 # 25 GB - - vid = random_vid() - - # 128 byte field, needs space for length (1 byte suffix) and UTF-8 indicator (1 byte prefix). - if len(lvid) > 126: - print("archiveman: disc label must be no longer than 126 characters") - util.abort() - - # 32 byte field, same as above. - assert len(vid) <= 30 - - # Create Disc object in database. - disc = models.Disc(volume_id = vid) - session.add(disc) - - # Create parent directory. - util.ensure_parent_dir(udf_file) - - # Set length of file to desired amount. - cmd = ["truncate", "--size", str(size), udf_file] - with util.execute(cmd): - pass - - # Create UDF filesystem inside file. - cmd = ["mkudffs", "--vid", vid, "--lvid", lvid, udf_file] - with util.execute(cmd): - pass - - session.commit() - -def do_add(args, db, st): - session = db.make_session() - - udffile = args[""] - - if not os.path.exists(udffile): - print("UDF file does not exist: {}".format(udffile)) - util.abort() - - disc = detect_disc(udffile, session) - - archives = [] - for archivename in args[""]: - archive = session.query(models.Archive).filter_by(name = archivename).first() - if archive is None: - print("reference to unknown archive: {}".format(archivename)) - util.abort() - archives.append(archive) - - with mount(udffile) as mountpoint: - for archive in archives: - dest_filename = os.path.join(mountpoint, archive.name) - st.copy_to(archive, dest_filename) - - - -def handle_cmdline(args, db, st): - if args["create"]: - do_create(args, db, st) - else: - logger.error("no operation specified") - util.abort() diff --git a/pkgs/archiveman/src/archiveman/main.py b/pkgs/archiveman/src/archiveman/main.py deleted file mode 100644 index e9a37b9e..00000000 --- a/pkgs/archiveman/src/archiveman/main.py +++ /dev/null @@ -1,113 +0,0 @@ -"""Archive management tool. - -Usage: - archiveman import - archiveman list - archiveman check - archiveman disc create [--label=