diff options
Diffstat (limited to 'ops/nixos')
-rw-r--r-- | ops/nixos/.gitignore | 3 | ||||
-rw-r--r-- | ops/nixos/README.md | 19 | ||||
-rw-r--r-- | ops/nixos/camden/default.nix | 367 | ||||
-rw-r--r-- | ops/nixos/default.nix | 42 | ||||
-rw-r--r-- | ops/nixos/dotfiles/config.fish | 40 | ||||
-rw-r--r-- | ops/nixos/dotfiles/msmtprc | 16 | ||||
-rw-r--r-- | ops/nixos/dotfiles/notmuch-config | 21 | ||||
-rw-r--r-- | ops/nixos/dotfiles/offlineimaprc | 39 | ||||
-rw-r--r-- | ops/nixos/mail.nix | 77 | ||||
-rw-r--r-- | ops/nixos/modules/.skip-subtree | 1 | ||||
-rw-r--r-- | ops/nixos/modules/v4l2loopback.nix | 12 | ||||
-rw-r--r-- | ops/nixos/nugget/default.nix | 262 |
12 files changed, 899 insertions, 0 deletions
diff --git a/ops/nixos/.gitignore b/ops/nixos/.gitignore new file mode 100644 index 000000000000..773fa1667019 --- /dev/null +++ b/ops/nixos/.gitignore @@ -0,0 +1,3 @@ +hardware-configuration.nix +local-configuration.nix +result diff --git a/ops/nixos/README.md b/ops/nixos/README.md new file mode 100644 index 000000000000..9e88193dad7e --- /dev/null +++ b/ops/nixos/README.md @@ -0,0 +1,19 @@ +NixOS configuration +=================== + +My NixOS configuration! It configures most of the packages I require +on my systems, sets up Emacs the way I need and does a bunch of other +interesting things. + +System configuration lives in folders for each machine and a custom +fixed point evaluation (similar to standard NixOS module +configuration) is used to combine configuration together. + +Building `ops.nixos.rebuilder` yields a script that will automatically +build and activate the newest configuration based on the current +hostname. + +## Configured hosts: + +* `nugget` - desktop computer at home +* ~~`urdhva` - T470s~~ (currently with edef) diff --git a/ops/nixos/camden/default.nix b/ops/nixos/camden/default.nix new file mode 100644 index 000000000000..2eb8976da138 --- /dev/null +++ b/ops/nixos/camden/default.nix @@ -0,0 +1,367 @@ +# This file configures camden.tazj.in, my homeserver. +{ depot, pkgs, lib, ... }: + +config: let + nixpkgs = import depot.third_party.nixpkgsSrc { + config.allowUnfree = true; + }; +in lib.fix(self: { + # camden is intended to boot unattended, despite having an encrypted + # root partition. + # + # The below configuration uses an externally connected USB drive + # that contains a LUKS key file to unlock the disk automatically at + # boot. + # + # TODO(tazjin): Configure LUKS unlocking via SSH instead. + boot = { + initrd = { + availableKernelModules = [ + "ahci" "xhci_pci" "usbhid" "usb_storage" "sd_mod" "sdhci_pci" + "rtsx_usb_sdmmc" "r8169" + ]; + + kernelModules = [ "dm-snapshot" ]; + + luks.devices.camden-crypt = { + fallbackToPassword = true; + device = "/dev/disk/by-label/camden-crypt"; + keyFile = "/dev/sdb"; + keyFileSize = 4096; + }; + }; + + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + + cleanTmpDir = true; + }; + + fileSystems = { + "/" = { + device = "/dev/disk/by-label/camden-root"; + fsType = "ext4"; + }; + + "/home" = { + device = "/dev/disk/by-label/camden-home"; + fsType = "ext4"; + }; + + "/boot" = { + device = "/dev/disk/by-label/BOOT"; + fsType = "vfat"; + }; + }; + + nix = { + maxJobs = lib.mkDefault 4; + + nixPath = [ + "depot=/home/tazjin/depot" + "nixpkgs=${depot.third_party.nixpkgsSrc}" + ]; + + trustedUsers = [ "root" "tazjin" ]; + + binaryCaches = [ + "https://tazjin.cachix.org" + ]; + + binaryCachePublicKeys = [ + "tazjin.cachix.org-1:IZkgLeqfOr1kAZjypItHMg1NoBjm4zX9Zzep8oRSh7U=" + ]; + }; + nixpkgs.pkgs = nixpkgs; + + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + + networking = { + hostName = "camden"; + interfaces.enp1s0.useDHCP = true; + interfaces.enp1s0.ipv6.addresses = [ + { + address = "2a01:4b00:821a:ce02::5"; + prefixLength = 64; + } + ]; + + firewall.enable = false; + }; + + time.timeZone = "UTC"; + + # System-wide application setup + programs.fish.enable = true; + programs.mosh.enable = true; + + environment.systemPackages = + # programs from the depot + (with depot; [ + fun.idual.script + fun.idual.setAlarm + third_party.git + third_party.honk + third_party.pounce + ]) ++ + + # programs from nixpkgs + (with nixpkgs; [ + bat + curl + direnv + emacs26-nox + gnupg + htop + jq + pass + pciutils + ripgrep + ]); + + users = { + # Set up my own user for logging in and doing things ... + users.tazjin = { + isNormalUser = true; + uid = 1000; + extraGroups = [ "git" "wheel" ]; + shell = nixpkgs.fish; + }; + + # Set up a user & group for general git shenanigans + groups.git = {}; + users.git = { + group = "git"; + isNormalUser = false; + }; + }; + + # Services setup + services.openssh.enable = true; + services.haveged.enable = true; + + # Join Tailscale into home network + services.tailscale.enable = true; + + # Allow sudo-ing via the forwarded SSH agent. + security.pam.enableSSHAgentAuth = true; + + # Run cgit for the depot. The onion here is nginx(thttpd(cgit)). + systemd.services.cgit = { + wantedBy = [ "multi-user.target" ]; + script = "${depot.web.cgit-taz}/bin/cgit-launch"; + + serviceConfig = { + Restart = "on-failure"; + User = "git"; + Group = "git"; + }; + }; + + # Run honk as the ActivityPub server, using all the fancy systemd + # magic. + systemd.services.honk = { + wantedBy = [ "multi-user.target" ]; + script = lib.concatStringsSep " " [ + "${depot.third_party.honk}/bin/honk" + "-datadir /var/lib/honk" + "-viewdir ${depot.third_party.honk.src}" + ]; + + serviceConfig = { + Restart = "always"; + DynamicUser = true; + StateDirectory = "honk"; + WorkingDirectory = "/var/lib/honk"; + }; + }; + + # NixOS 20.03 broke nginx and I can't be bothered to debug it + # anymore, all solution attempts have failed, so here's a + # brute-force fix. + systemd.services.fix-nginx = { + script = "${nixpkgs.coreutils}/bin/chown -R nginx: /var/spool/nginx"; + + serviceConfig = { + User = "root"; + Type = "oneshot"; + }; + }; + + systemd.timers.fix-nginx = { + wantedBy = [ "multi-user.target" ]; + timerConfig = { + OnCalendar = "minutely"; + }; + }; + + # Provision a TLS certificate outside of nginx to avoid + # nixpkgs#38144 + security.acme = { + acceptTerms = true; + email = "mail@tazj.in"; + + certs."tazj.in" = { + user = "nginx"; + group = "nginx"; + webroot = "/var/lib/acme/acme-challenge"; + extraDomains = { + "git.tazj.in" = null; + "www.tazj.in" = null; + + # Local domains (for this machine only) + "camden.tazj.in" = null; + "git.camden.tazj.in" = null; + }; + postRun = "systemctl reload nginx"; + }; + + certs."tvl.fyi" = { + user = "nginx"; + group = "nginx"; + webroot = "/var/lib/acme/acme-challenge"; + postRun = "systemctl reload nginx"; + }; + }; + + # Forward logs to Google Cloud Platform + services.journaldriver = { + enable = true; + logStream = "home"; + googleCloudProject = "tazjins-infrastructure"; + applicationCredentials = "/etc/gcp/key.json"; + }; + + # serve my website + services.nginx = { + enable = true; + enableReload = true; + package = with nixpkgs; nginx.override { + modules = [ nginxModules.rtmp ]; + }; + + recommendedTlsSettings = true; + recommendedGzipSettings = true; + recommendedProxySettings = true; + + + appendConfig = '' + rtmp_auto_push on; + rtmp { + server { + listen 1935; + chunk_size 4000; + + application tvl { + live on; + + allow publish 88.98.195.213; + allow publish 10.0.1.0/24; + deny publish all; + + allow play all; + } + } + } + ''; + + commonHttpConfig = '' + log_format json_combined escape=json + '{' + '"remote_addr":"$remote_addr",' + '"method":"$request_method",' + '"uri":"$request_uri",' + '"status":$status,' + '"request_size":$request_length,' + '"response_size":$body_bytes_sent,' + '"response_time":$request_time,' + '"referrer":"$http_referer",' + '"user_agent":"$http_user_agent"' + '}'; + + access_log syslog:server=unix:/dev/log,nohostname json_combined; + ''; + + virtualHosts.homepage = { + serverName = "tazj.in"; + serverAliases = [ "camden.tazj.in" ]; + default = true; + useACMEHost = "tazj.in"; + root = depot.web.homepage; + addSSL = true; + + extraConfig = '' + ${depot.web.blog.oldRedirects} + + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + location ~* \.(webp|woff2)$ { + add_header Cache-Control "public, max-age=31536000"; + } + + location /blog/ { + alias ${depot.web.blog.rendered}/; + + if ($request_uri ~ ^/(.*)\.html$) { + return 302 /$1; + } + + try_files $uri $uri.html $uri/ =404; + } + + location /blobs/ { + alias /var/www/blobs/; + } + ''; + }; + + virtualHosts.tvl = { + serverName = "tvl.fyi"; + useACMEHost = "tvl.fyi"; + root = depot.web.tvl; + addSSL = true; + + extraConfig = '' + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + rewrite ^/meet/?$ https://meet.google.com/mng-biyw-xbb last; + + location ~* \.(webp|woff2)$ { + add_header Cache-Control "public, max-age=31536000"; + } + ''; + }; + + virtualHosts.cgit = { + serverName = "git.tazj.in"; + serverAliases = [ "git.camden.tazj.in" ]; + useACMEHost = "tazj.in"; + addSSL = true; + + extraConfig = '' + # Static assets must always hit the root. + location ~ ^/(favicon\.ico|cgit\.(css|png))$ { + proxy_pass http://localhost:2448; + } + + # Everything else hits the depot directly. + location / { + proxy_pass http://localhost:2448/cgit.cgi/depot/; + } + ''; + }; + }; + + # Timer units that can be started with systemd-run to set my alarm. + systemd.user.services.light-alarm = { + script = "${depot.fun.idual.script}/bin/idualctl wakey"; + postStart = "${pkgs.systemd}/bin/systemctl --user stop light-alarm.timer"; + serviceConfig = { + Type = "oneshot"; + }; + }; + + system.stateVersion = "19.09"; +}) diff --git a/ops/nixos/default.nix b/ops/nixos/default.nix new file mode 100644 index 000000000000..040bfeb6e23e --- /dev/null +++ b/ops/nixos/default.nix @@ -0,0 +1,42 @@ +{ depot, lib, ... }: + +let + inherit (builtins) foldl'; + + systemFor = configs: (depot.third_party.nixos { + configuration = lib.fix(config: + foldl' lib.recursiveUpdate {} (map (c: c config) configs) + ); + }).system; + + rebuilder = depot.third_party.writeShellScriptBin "rebuilder" '' + set -ue + if [[ $EUID -ne 0 ]]; then + echo "Oh no! Only root is allowed to rebuild the system!" >&2 + exit 1 + fi + + case $HOSTNAME in + nugget) + echo "Rebuilding NixOS for //ops/nixos/nugget" + system=$(nix-build -E '(import <depot> {}).ops.nixos.nuggetSystem' --no-out-link) + ;; + camden) + echo "Rebuilding NixOS for //ops/nixos/camden" + system=$(nix-build -E '(import <depot> {}).ops.nixos.camdenSystem' --no-out-link) + ;; + *) + echo "$HOSTNAME is not a known NixOS host!" >&2 + exit 1 + ;; + esac + + nix-env -p /nix/var/nix/profiles/system --set $system + $system/bin/switch-to-configuration switch + ''; +in { + inherit rebuilder; + + nuggetSystem = systemFor [ depot.ops.nixos.nugget ]; + camdenSystem = systemFor [ depot.ops.nixos.camden ]; +} diff --git a/ops/nixos/dotfiles/config.fish b/ops/nixos/dotfiles/config.fish new file mode 100644 index 000000000000..de2c99ae6007 --- /dev/null +++ b/ops/nixos/dotfiles/config.fish @@ -0,0 +1,40 @@ +# Configure classic prompt +set fish_color_user --bold blue +set fish_color_cwd --bold white + +# Enable colour hints in VCS prompt: +set __fish_git_prompt_showcolorhints yes +set __fish_git_prompt_color_prefix purple +set __fish_git_prompt_color_suffix purple + +# Fish configuration +set fish_greeting "" +set PATH $HOME/.local/bin $HOME/.cargo/bin $PATH + +# Editor configuration +set -gx EDITOR "emacsclient" +set -gx ALTERNATE_EDITOR "emacs -q -nw" +set -gx VISUAL "emacsclient" + +# Miscellaneous +eval (direnv hook fish) + +# Useful command aliases +alias gpr 'git pull --rebase' +alias gco 'git checkout' +alias gf 'git fetch' +alias gap 'git add -p' +alias pbcopy 'xclip -selection clipboard' +alias edit 'emacsclient -n' +alias servedir 'nix-shell -p haskellPackages.wai-app-static --run warp' + +# Old habits die hard (also ls is just easier to type): +alias ls 'exa' + +# Fix up nix-env & friends for Nix 2.0 +export NIX_REMOTE=daemon + +# Fix display of fish in emacs' term-mode: +function fish_title + true +end diff --git a/ops/nixos/dotfiles/msmtprc b/ops/nixos/dotfiles/msmtprc new file mode 100644 index 000000000000..624b6a77fc4b --- /dev/null +++ b/ops/nixos/dotfiles/msmtprc @@ -0,0 +1,16 @@ +defaults + +port 587 +tls on +tls_trust_file /etc/ssl/certs/ca-certificates.crt + +# Runbox mail +account runbox +from mail@tazj.in +host mail.runbox.com +auth on +user mail@tazj.in +passwordeval pass show general/runbox-tazjin + +# Use Runbox as default +account default : runbox diff --git a/ops/nixos/dotfiles/notmuch-config b/ops/nixos/dotfiles/notmuch-config new file mode 100644 index 000000000000..a490774e635f --- /dev/null +++ b/ops/nixos/dotfiles/notmuch-config @@ -0,0 +1,21 @@ +# .notmuch-config - Configuration file for the notmuch mail system +# +# For more information about notmuch, see https://notmuchmail.org + +[database] +path=/home/vincent/mail + +[user] +name=Vincent Ambo +primary_email=mail@tazj.in +other_email=tazjin@gmail.com; + +[new] +tags=unread;inbox; +ignore= + +[search] +exclude_tags=deleted;spam;draft; + +[maildir] +synchronize_flags=true diff --git a/ops/nixos/dotfiles/offlineimaprc b/ops/nixos/dotfiles/offlineimaprc new file mode 100644 index 000000000000..78315447e4bd --- /dev/null +++ b/ops/nixos/dotfiles/offlineimaprc @@ -0,0 +1,39 @@ +[general] +accounts = tazjin, gmail + +[DEFAULT] +ssl = yes +sslcacertfile = /etc/ssl/certs/ca-certificates.crt + +# Private GMail account (old): +[Account gmail] +maxage = 90 +localrepository = gmail-local +remoterepository = gmail-remote +synclabels = yes + +[Repository gmail-local] +type = GmailMaildir +localfolders = ~/mail/gmail + +[Repository gmail-remote] +type = Gmail +remoteuser = tazjin@gmail.com +remotepassfile = ~/.config/mail/gmail-pass +folderfilter = lambda folder: folder == 'INBOX' + +# Main private account: +[Account tazjin] +localrepository = tazjin-local +remoterepository = tazjin-remote + +[Repository tazjin-local] +type = Maildir +localfolders = ~/mail/tazjin + +[Repository tazjin-remote] +type = IMAP +remotehost = mail.runbox.com +remoteuser = mail@tazj.in +remotepassfile = ~/.config/mail/tazjin-pass +auth_mechanisms = LOGIN diff --git a/ops/nixos/mail.nix b/ops/nixos/mail.nix new file mode 100644 index 000000000000..ba4ebfa06026 --- /dev/null +++ b/ops/nixos/mail.nix @@ -0,0 +1,77 @@ +# This file configures offlineimap, notmuch and MSMTP. +# +# Some manual configuration is required the first time this is +# applied: +# +# 1. Credential setup. +# 2. Linking of MSMTP config (ln -s /etc/msmtprc ~/.msmtprc) +# 3. Linking of notmuch config (ln -s /etc/notmuch-config ~/.notmuch-config) + +{ config, lib, pkgs, ... }: + +let offlineImapConfig = pkgs.writeText "offlineimaprc" + (builtins.readFile ./dotfiles/offlineimaprc); + +msmtpConfig = pkgs.writeText "msmtprc" + (builtins.readFile ./dotfiles/msmtprc); + +notmuchConfig = pkgs.writeText "notmuch-config" + (builtins.readFile ./dotfiles/notmuch-config); + +tagConfig = pkgs.writeText "notmuch-tags" '' + # Tag emacs-devel mailing list: + -inbox +emacs-devel -- to:emacs-devel@gnu.org OR cc:emacs-devel@gnu.org + + # Tag nix-devel mailing list & discourse: + -inbox +nix-devel -- to:nix-devel@googlegroups.com OR from:nixos1@discoursemail.com + + # Tag my own mail (from other devices) as sent: + -inbox +sent -- from:mail@tazj.in + + # Drafts are always read, duh. + -unread -- tag:draft +''; + +notmuchIndex = pkgs.writeShellScriptBin "notmuch-index" '' + echo "Indexing new mails in notmuch" + + # Index new mail + ${pkgs.notmuch}/bin/notmuch new + + # Apply tags + cat ${tagConfig} | ${pkgs.notmuch}/bin/notmuch tag --batch + + echo "Done indexing new mails" +''; +in { + # Enable OfflineIMAP timer & service: + systemd.user.timers.offlineimap = { + description = "OfflineIMAP timer"; + wantedBy = [ "timers.target" ]; + + timerConfig = { + Unit = "offlineimap.service"; + OnCalendar = "*:0/2"; # every 2 minutes + Persistent = "true"; # persist timer state after reboots + }; + }; + + systemd.user.services.offlineimap = { + description = "OfflineIMAP service"; + path = with pkgs; [ pass notmuch ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.offlineimap}/bin/offlineimap -u syslog -o -c ${offlineImapConfig}"; + ExecStartPost = "${notmuchIndex}/bin/notmuch-index"; + TimeoutStartSec = "2min"; + }; + }; + + # Link configuration files to /etc/ (from where they will be linked + # further): + environment.etc = { + "msmtprc".source = msmtpConfig; + "notmuch-config".source = notmuchConfig; + }; +} diff --git a/ops/nixos/modules/.skip-subtree b/ops/nixos/modules/.skip-subtree new file mode 100644 index 000000000000..80d92f2eb485 --- /dev/null +++ b/ops/nixos/modules/.skip-subtree @@ -0,0 +1 @@ +The files in this folder are NixOS modules, not readTree-importables. diff --git a/ops/nixos/modules/v4l2loopback.nix b/ops/nixos/modules/v4l2loopback.nix new file mode 100644 index 000000000000..636b2ff6cf27 --- /dev/null +++ b/ops/nixos/modules/v4l2loopback.nix @@ -0,0 +1,12 @@ +{ config, lib, pkgs, ... }: + +{ + boot = { + extraModulePackages = [ config.boot.kernelPackages.v4l2loopback ]; + kernelModules = [ "v4l2loopback" ]; + extraModprobeConfig = '' + options v4l2loopback exclusive_caps=1 + ''; + }; +} + diff --git a/ops/nixos/nugget/default.nix b/ops/nixos/nugget/default.nix new file mode 100644 index 000000000000..185123e77cc6 --- /dev/null +++ b/ops/nixos/nugget/default.nix @@ -0,0 +1,262 @@ +# This file configures nugget, my home desktop machine. +{ depot, lib, ... }: + +config: let + nixpkgs = import depot.third_party.nixpkgsSrc { + config.allowUnfree = true; + }; + + lieer = (depot.third_party.lieer {}); + + # google-c-style is installed only on nugget because other + # machines get it from, eh, elsewhere. + nuggetEmacs = (depot.tools.emacs.overrideEmacs(epkgs: epkgs ++ [ + depot.third_party.emacsPackages.google-c-style + ])); +in depot.lib.fix(self: { + imports = [ + ../modules/v4l2loopback.nix + ]; + + hardware = { + pulseaudio.enable = true; + cpu.intel.updateMicrocode = true; + u2f.enable = true; + }; + + boot = { + cleanTmpDir = true; + kernelModules = [ "kvm-intel" ]; + + loader = { + timeout = 3; + systemd-boot.enable = true; + efi.canTouchEfiVariables = false; + }; + + initrd = { + luks.devices.nugget-crypt.device = "/dev/disk/by-label/nugget-crypt"; + availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" ]; + kernelModules = [ "dm-snapshot" ]; + }; + }; + + nix = { + package = depot.third_party.nix; + nixPath = [ + "depot=/home/tazjin/depot" + "nixpkgs=${depot.third_party.nixpkgsSrc}" + ]; + }; + + nixpkgs.pkgs = nixpkgs; + + networking = { + hostName = "nugget"; + useDHCP = false; + interfaces.eno1.useDHCP = true; + interfaces.wlp7s0.useDHCP = true; + + # Don't use ISP's DNS servers: + nameservers = [ + "8.8.8.8" + "8.8.4.4" + ]; + + # Open Chromecast-related ports & servedir + firewall.enable = false; + firewall.allowedTCPPorts = [ 4242 5556 5558 ]; + + # Connect to the WiFi to let the Chromecast work. + wireless.enable = true; + wireless.networks = { + "How do I computer?" = { + psk = "washyourface"; + }; + }; + }; + + # Generate an immutable /etc/resolv.conf from the nameserver settings + # above (otherwise DHCP overwrites it): + environment.etc."resolv.conf" = with lib; { + source = depot.third_party.writeText "resolv.conf" '' + ${concatStringsSep "\n" (map (ns: "nameserver ${ns}") self.networking.nameservers)} + options edns0 + ''; + }; + + time.timeZone = "Europe/London"; + + environment.systemPackages = + # programs from the depot + (with depot; [ + fun.idual.script + lieer + nuggetEmacs + ops.kontemplate + third_party.ffmpeg + third_party.git + ]) ++ + + # programs from nixpkgs + (with nixpkgs; [ + age + bat + cachix + chromium + clang-manpages + clang-tools + clang_9 + curl + direnv + dnsutils + exa + fd + gnupg + go + google-chrome + google-cloud-sdk + guile + htop + i3lock + imagemagick + jq + keybase-gui + kubectl + meson + miller + msmtp + nix-prefetch-github + notmuch + openssh + openssl + pass + pavucontrol + pinentry + pinentry-emacs + pwgen + ripgrep + rustup + sbcl + scrot + spotify + steam + tokei + tree + unzip + vlc + xclip + yubico-piv-tool + yubikey-personalization + ]); + + fileSystems = { + "/".device = "/dev/disk/by-label/nugget-root"; + "/boot".device = "/dev/disk/by-label/EFI"; + "/home".device = "/dev/disk/by-label/nugget-home"; + }; + + # Configure user account + users.extraUsers.tazjin = { + extraGroups = [ "wheel" "audio" ]; + isNormalUser = true; + uid = 1000; + shell = nixpkgs.fish; + }; + + security.sudo = { + enable = true; + extraConfig = "wheel ALL=(ALL:ALL) SETENV: ALL"; + }; + + fonts = { + fonts = with nixpkgs; [ + corefonts + dejavu_fonts + jetbrains-mono + noto-fonts-cjk + noto-fonts-emoji + ]; + + fontconfig = { + hinting.enable = true; + subpixel.lcdfilter = "light"; + + defaultFonts = { + monospace = [ "JetBrains Mono" ]; + }; + }; + }; + + # Configure location (Vauxhall, London) for services that need it. + location = { + latitude = 51.4819109; + longitude = -0.1252998; + }; + + programs.fish.enable = true; + programs.ssh.startAgent = true; + + services.redshift.enable = true; + services.openssh.enable = true; + services.keybase.enable = true; + + # Required for Yubikey usage as smartcard + services.pcscd.enable = true; + services.udev.packages = [ + nixpkgs.yubikey-personalization + ]; + + services.xserver = { + enable = true; + layout = "us"; + xkbOptions = "caps:super"; + exportConfiguration = true; + videoDrivers = [ "nvidia" ]; + + displayManager = { + # Give EXWM permission to control the session. + sessionCommands = "${nixpkgs.xorg.xhost}/bin/xhost +SI:localuser:$USER"; + + lightdm.enable = true; + lightdm.greeters.gtk.clock-format = "%H·%M"; + }; + + windowManager.session = lib.singleton { + name = "exwm"; + start = "${nuggetEmacs}/bin/tazjins-emacs"; + }; + }; + + # Do not restart the display manager automatically + systemd.services.display-manager.restartIfChanged = lib.mkForce false; + + # Configure email setup + systemd.user.services.lieer-tazjin = { + description = "Synchronise mail@tazj.in via lieer"; + script = "${lieer}/bin/gmi sync"; + + serviceConfig = { + WorkingDirectory = "%h/mail/account.tazjin"; + Type = "oneshot"; + }; + }; + + systemd.user.timers.lieer-tazjin = { + wantedBy = [ "timers.target" ]; + + timerConfig = { + OnActiveSec = "1"; + OnUnitActiveSec = "180"; + }; + }; + + # Use Tailscale \o/ + services.tailscale.enable = true; + + # nugget has an SSD + services.fstrim.enable = true; + + # ... and other nonsense. + system.stateVersion = "19.09"; +}) |