From b14a123560dbfc4b7b9ceedf12cc5730558e2418 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sat, 17 Feb 2024 10:00:34 -0500 Subject: Move all os/home configurations into modules. --- dthompson/machines/ikaruga.scm | 219 ++++++++++++++++++++++++++ dthompson/machines/rise.scm | 185 ++++++++++++++++++++++ dthompson/machines/takemi.scm | 350 +++++++++++++++++++++++++++++++++++++++++ ikaruga-home.scm | 82 ---------- ikaruga-os.scm | 116 -------------- rise-home.scm | 65 -------- rise-os.scm | 120 -------------- takemi-os.scm | 348 ---------------------------------------- 8 files changed, 754 insertions(+), 731 deletions(-) create mode 100644 dthompson/machines/ikaruga.scm create mode 100644 dthompson/machines/rise.scm create mode 100644 dthompson/machines/takemi.scm delete mode 100644 ikaruga-home.scm delete mode 100644 ikaruga-os.scm delete mode 100644 rise-home.scm delete mode 100644 rise-os.scm delete mode 100644 takemi-os.scm diff --git a/dthompson/machines/ikaruga.scm b/dthompson/machines/ikaruga.scm new file mode 100644 index 0000000..0f4e402 --- /dev/null +++ b/dthompson/machines/ikaruga.scm @@ -0,0 +1,219 @@ +;;; Copyright © 2022-2024 David Thompson +;;; +;;; This program is free software; you can redistribute it and/or +;;; modify it under the terms of the GNU General Public License as +;;; published by the Free Software Foundation; either version 3 of the +;;; License, or (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see +;;; . + +;;; Commentary: +;; +;; Laptop OS configuration. +;; +;; To update the OS, run: +;; +;; sudo -E guix system reconfigure -L . -e '(@ (dthompson machines ikaruga) ikaruga-os)' +;; +;; To update the home environment, run: +;; +;; guix home reconfigure -L . -e '(@ (dthompson machines ikaruga) ikaruga-home)' + +(define-module (dthompson machines ikaruga) + #:use-module (dthompson home common) + #:use-module (dthompson home pipewire) + #:use-module (gnu) + #:use-module (gnu bootloader) + #:use-module (gnu home) + #:use-module (gnu packages) + #:use-module (gnu services) + #:use-module (gnu services base) + #:use-module (gnu services cups) + #:use-module (gnu services desktop) + #:use-module (gnu services games) + #:use-module (gnu services pm) + #:use-module (gnu services virtualization) + #:use-module (gnu services sound) + #:use-module (gnu services xorg) + #:use-module (gnu system) + #:use-module (gnu system accounts) + #:use-module (gnu system file-systems) + #:use-module (gnu system mapped-devices) + #:use-module (nongnu packages linux) + #:use-module (nongnu system linux-initrd)) + +(define-public ikaruga-os + (operating-system + (locale "en_US.utf8") + (timezone "America/New_York") + (keyboard-layout (keyboard-layout "us")) + (host-name "ikaruga") + (bootloader (bootloader-configuration + (bootloader grub-efi-bootloader) + (targets (list "/boot/efi")) + (keyboard-layout keyboard-layout))) + ;; Use regular Linux with the big bad proprietary firmware blobs. + (kernel linux) + (initrd microcode-initrd) + ;; sof-firmware is required for sound to work, linux-firmware takes + ;; care of everything else. + (firmware (list sof-firmware linux-firmware)) + (users (cons* (user-account + (name "dave") + (comment "David Thompson") + (group "users") + (home-directory "/home/dave") + (supplementary-groups + '("audio" + "kvm" ; for running VMs + "libvirt" ; also for VMs + "lp" ; for bluetooth + "netdev" + "realtime" ; for realtime prioritization + "video" + "wheel"))) ; for sudo + %base-user-accounts)) + (groups (cons (user-group + (name "realtime") + (system? #t)) + %base-groups)) + (packages (cons (specification->package "nss-certs") + %base-packages)) + (services + (let ((services + (cons* (service gnome-desktop-service-type) + (service bluetooth-service-type) + (service thermald-service-type) + ;; For Nintendo Switch Pro controller + (service joycond-service-type) + (service cups-service-type + (cups-configuration + (web-interface? #t) + (extensions + (list (specification->package "cups-filters") + ;; Brother laser printers + (specification->package "brlaser"))))) + ;; Used by GNOME Boxes + (service libvirt-service-type) + (service virtlog-service-type) + ;; The first entry increases the maximum realtime + ;; priority for non-privileged processes; the second + ;; entry lifts any restriction of the maximum + ;; address space that can be locked in memory. + (service pam-limits-service-type + (list + (pam-limits-entry "@realtime" 'both 'rtprio 99) + (pam-limits-entry "@realtime" 'both 'memlock + 'unlimited))) + %desktop-services))) + (modify-services services + ;; No pulseaudio. We run pipewire as a home service instead. + (delete pulseaudio-service-type) + ;; Use Wayland instead of X11 + (gdm-service-type config => + (gdm-configuration + (inherit config) + (wayland? #t))) + ;; Get nonguix substitutes. + (guix-service-type config => + (guix-configuration + (inherit config) + (substitute-urls + (cons "https://substitutes.nonguix.org" + %default-substitute-urls)) + (authorized-keys + (cons (local-file "../../keys/nonguix-signing-key.pub") + %default-authorized-guix-keys))))))) + (mapped-devices (list (mapped-device + (source (uuid "02b1ffb4-d868-4e5f-ab9b-8be3092e3a3c")) + (target "cryptroot") + (type luks-device-mapping)))) + (file-systems (cons* (file-system + (mount-point "/boot/efi") + (device (uuid "91D3-F76B" 'fat32)) + (type "vfat")) + (file-system + (mount-point "/") + (device "/dev/mapper/cryptroot") + (type "ext4") + (dependencies mapped-devices)) + %base-file-systems)) + (name-service-switch %mdns-host-lookup-nss))) + +(define-public ikaruga-home + (home-environment + (packages (specifications->packages + '("ardour" + "blender" + "calf" + "dragonfly-reverb" + "emacs" + "emacs-better-defaults" + "emacs-buffer-env" + "emacs-doom-modeline" + "emacs-doom-themes" + "emacs-flycheck-guile" + "emacs-geiser-guile" + "emacs-htmlize" + "emacs-js2-mode" + "emacs-magit" + "emacs-magit-annex" + "emacs-markdown-mode" + "emacs-org-reveal" + "emacs-paredit" + "emacs-racket-mode" + "emacs-rainbow-delimiters" + "emacs-smex" + "emacs-typo" + "emacs-use-package" + "emacs-web-mode" + "emacs-which-key" + "emacs-yaml-mode" + "firefox" + "font-google-noto-emoji" + "font-google-noto-sans-cjk" + "font-google-noto-serif-cjk" + "font-inconsolata" + "gimp" + "git" + "git:send-email" + "git-annex" + "gnome-boxes" + "gnome-tweaks" + "gnupg" + "google-chrome-unstable" + "gst-plugins-bad" + "guile@3" + "htop" + "hydrogen" + "keepassxc" + "libreoffice" + "libresprite" + "lsp-plugins" + "milkytracker" + "ncurses" + "obs" + "openssh" + "pavucontrol" + "pinentry" + "qpwgraph" + "quodlibet" + "sfxr" + "sicp" + "steam" + "strace" + "tiled" + "tor" + "vlc" + "x42-plugins" + "xournal" + "yt-dlp"))) + (services (cons (service home-pipewire-service-type) + common-services)))) diff --git a/dthompson/machines/rise.scm b/dthompson/machines/rise.scm new file mode 100644 index 0000000..c5fb3de --- /dev/null +++ b/dthompson/machines/rise.scm @@ -0,0 +1,185 @@ +;;; Copyright © 2022-2024 David Thompson +;;; +;;; This program is free software; you can redistribute it and/or +;;; modify it under the terms of the GNU General Public License as +;;; published by the Free Software Foundation; either version 3 of the +;;; License, or (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see +;;; . + +;;; Commentary: +;; +;; DAW laptop configuration. +;; +;; To update the OS configuration, run: +;; +;; guix system reconfigure -L . -e '(@ (dthompson machines rise) rise-os)' +;; +;; To update the home environment, run: +;; +;; guix home reconfigure -L . -e '(@ (dthompson machines rise) rise-home)' + +(define-module (dthompson machines rise) + #:use-module (dthompson home common) + #:use-module (dthompson home pipewire) + #:use-module (gnu) + #:use-module (gnu bootloader) + #:use-module (gnu home) + #:use-module (gnu packages) + #:use-module (gnu services) + #:use-module (gnu services base) + #:use-module (gnu services cups) + #:use-module (gnu services desktop) + #:use-module (gnu services games) + #:use-module (gnu services pm) + #:use-module (gnu services virtualization) + #:use-module (gnu services sound) + #:use-module (gnu services xorg) + #:use-module (gnu system) + #:use-module (gnu system accounts) + #:use-module (gnu system file-systems) + #:use-module (gnu system mapped-devices) + #:use-module (nongnu packages linux) + #:use-module (nongnu system linux-initrd)) + +(define-public rise-os + (operating-system + (locale "en_US.utf8") + (timezone "America/New_York") + (keyboard-layout (keyboard-layout "us")) + (host-name "rise") + (bootloader (bootloader-configuration + (bootloader grub-efi-bootloader) + (targets (list "/boot/efi")) + (keyboard-layout keyboard-layout))) + ;; Use regular Linux with the big bad proprietary firmware blobs. + (kernel linux) + ;; Install microcode updates because why the heck wouldn't you want + ;; this??? + (initrd microcode-initrd) + ;; sof-firmware is required for sound to work, linux-firmware takes + ;; care of everything else. + (firmware (list sof-firmware linux-firmware)) + (users (cons* (user-account + (name "dave") + (comment "David Thompson") + (group "users") + (home-directory "/home/dave") + (supplementary-groups + '("audio" + "kvm" ; for VMs + "lp" ; for bluetooth + "netdev" + "realtime" ; for realtime prioritization + "video" + "wheel"))) ; for sudo + %base-user-accounts)) + (groups (cons (user-group + (name "realtime") + (system? #t)) + %base-groups)) + (packages (append (map specification->package + '("ncurses" "nss-certs" "strace")) + %base-packages)) + (services (modify-services + (cons* (service gnome-desktop-service-type) + (service bluetooth-service-type) + ;; Keep CPU temp in check. + (service thermald-service-type) + ;; Enable CUPS web UI and also add the extension + ;; for my Brother laser printer. + (service cups-service-type + (cups-configuration + (web-interface? #t) + (extensions + (map specification->package '("cups-filters" "brlaser"))))) + ;; The first entry increases the maximum realtime + ;; priority for non-privileged processes; the + ;; second entry lifts any restriction of the + ;; maximum address space that can be locked in + ;; memory. + (service pam-limits-service-type + (list + (pam-limits-entry "@realtime" + 'both 'rtprio 99) + (pam-limits-entry "@realtime" + 'both 'memlock 'unlimited))) + %desktop-services) + ;; In this house, we use JACK. + (delete pulseaudio-service-type) + ;; Get nonguix substitutes. + (guix-service-type config => + (guix-configuration + (inherit config) + (substitute-urls + (append (list "https://substitutes.nonguix.org") + %default-substitute-urls)) + (authorized-keys + (append (list (local-file "keys/nonguix-signing-key.pub")) + %default-authorized-guix-keys)))))) + (mapped-devices (list (mapped-device + (source (uuid "ee0a37d1-36d6-4e50-8af0-fc0bfe8c22ef")) + (target "cryptroot") + (type luks-device-mapping)))) + (file-systems (cons* (file-system + (mount-point "/boot/efi") + (device (uuid "1F21-80A1" 'fat32)) + (type "vfat")) + (file-system + (mount-point "/") + (device "/dev/mapper/cryptroot") + (type "ext4") + (dependencies mapped-devices)) %base-file-systems)) + (name-service-switch %mdns-host-lookup-nss))) + +(define-public rise-home + (home-environment + (packages (specifications->packages + '("audacity" + "alsa-utils" + "ardour" + "blender" + "calf" + "carla" + "dragonfly-reverb" + "emacs" + "emacs-better-defaults" + "emacs-buffer-env" + "emacs-doom-modeline" + "emacs-doom-themes" + "emacs-flycheck-guile" + "emacs-geiser-guile" + "emacs-magit" + "emacs-markdown-mode" + "emacs-paredit" + "emacs-rainbow-delimiters" + "emacs-smex" + "emacs-use-package" + "emacs-which-key" + "firefox" + "font-google-noto-sans-cjk" + "font-google-noto-serif-cjk" + "font-inconsolata" + "gimp" + "git" + "gnome-tweaks" + "htop" + "hydrogen" + "jack" + "lsp-plugins" + "milkytracker" + "obs" + "openssh" + "patchage" + "qjackctl" + "sfxr" + "x42-plugins" + "yt-dlp"))) + (services common-services))) diff --git a/dthompson/machines/takemi.scm b/dthompson/machines/takemi.scm new file mode 100644 index 0000000..5a94e16 --- /dev/null +++ b/dthompson/machines/takemi.scm @@ -0,0 +1,350 @@ +(define-module (dthompson machines takemi) + #:use-module (gnu) + #:use-module (gnu packages version-control) + #:use-module (gnu services admin) + #:use-module (gnu services certbot) + #:use-module (gnu services cgit) + #:use-module (gnu services ci) + #:use-module (gnu services networking) + #:use-module (gnu services ssh) + #:use-module (gnu services version-control) + #:use-module (gnu services web)) + +(define letsencrypt-cert + "/etc/letsencrypt/live/dthompson.us/fullchain.pem") +(define letsencrypt-cert-key + "/etc/letsencrypt/live/dthompson.us/privkey.pem") +(define dave-pub-key (local-file "keys/dave.pub")) +(define git-root "/var/lib/gitolite") +(define fcgiwrap-socket "127.0.0.1:9000") + +(define nginx-accounts + (list (user-group (name "nginx") (system? #t)) + (user-account + (name "nginx") + (group "nginx") + (supplementary-groups '("git")) + (system? #t) + (comment "nginx server user") + (home-directory "/var/empty") + (shell (file-append (specification->package "shadow") + "/sbin/nologin"))))) + +(define (nginx-signal name signal) + (program-file + name + #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) + (kill pid #$signal)))) + +;; Need to override the default nginx service account configuration so +;; that the nginx user is a member of the git group. +(define nginx-service-type* + (service-type + (inherit nginx-service-type) + (extensions + (map (lambda (extension) + (if (eq? (service-extension-target extension) + account-service-type) + (service-extension account-service-type + (const nginx-accounts)) + extension)) + (service-type-extensions nginx-service-type))))) + +(define takemi-os + (operating-system + (locale "en_US.utf8") + (timezone "America/New_York") + (keyboard-layout (keyboard-layout "us")) + (host-name "takemi") + (users (cons* (user-account + (name "dave") + (comment "David Thompson") + (group "users") + (home-directory "/home/dave") + (supplementary-groups + '("wheel" "netdev"))) + (user-account + (name "publish") + (comment "Web file publisher") + (group "publish") + (home-directory "/var/www") + (system? #t) + (create-home-directory? #f)) + %base-user-accounts)) + (groups (cons* (user-group + (name "publish") + (system? #t)) + %base-groups)) + (sudoers-file + (plain-file "sudoers" + (string-append (plain-file-content %sudoers-specification) + ;; 'guix deploy' requires no password + ;; sudo capability. + "dave ALL = NOPASSWD: ALL\n"))) + (packages + (append (map specification->package '("emacs" "nss-certs" "rsync" "git" "laminar")) + %base-packages)) + (services + (cons* + (service dhcp-client-service-type) + (service openssh-service-type + (openssh-configuration + (password-authentication? #f) + ;; So I can forward ports from my local host to + ;; the server and have the ports accessible from + ;; the internet. + (gateway-ports? #t) + (authorized-keys + `(("dave" ,dave-pub-key) + ("publish" ,dave-pub-key))))) + ;; Git repository hosting. + (service gitolite-service-type + (gitolite-configuration + (admin-pubkey dave-pub-key) + (rc-file (gitolite-rc-file + ;; Grant read access to git group so + ;; cgit will work. + (umask #o0027) + (git-config-keys "gitweb\\..*"))))) + ;; Continuous integration. + (service laminar-service-type + (laminar-configuration + (supplementary-groups '("git")))) + ;; TLS certificates. Certbot extends nginx with configuration to + ;; redirect all HTTP requests to HTTPS. + (service (service-type + (inherit certbot-service-type) + (extensions + ;; Replace original nginx-service-type with + ;; our modified one. + (map (lambda (extension) + (if (eq? (service-extension-target extension) + nginx-service-type) + (service-extension nginx-service-type* + (@@ (gnu services certbot) + certbot-nginx-server-configurations)) + extension)) + (service-type-extensions certbot-service-type)))) + (certbot-configuration + (email "dthompson2@worcester.edu") + (certificates + (list + (certificate-configuration + (domains '("dthompson.us" + "www.dthompson.us" + "git.dthompson.us" + "ci.dthompson.us" + "files.dthompson.us" + "haunt.dthompson.us")) + ;; Send SIGHUP signal to nginx to trigger a + ;; configuration reload, thus loading the + ;; updated certificates. + (deploy-hook (nginx-signal "nginx-deploy-hook" SIGHUP))))) + (webroot "/var/www/certbot"))) + (service nginx-service-type* + (nginx-configuration + (server-blocks + (list (nginx-server-configuration + (listen '("443 ssl")) + (server-name '("www.dthompson.us")) + (root "/var/www/blog") + ;; I used to check in the HTML output of + ;; manuals to my blog's git repo which was + ;; super gross. This rewrite rule keeps those + ;; links alive. + (locations + (list + (nginx-location-configuration + (uri "/manuals") + (body '("rewrite ^/manuals/([^/]+)/(.*) https://files.dthompson.us/docs/$1/latest/$2 permanent;"))))) + (ssl-certificate letsencrypt-cert) + (ssl-certificate-key letsencrypt-cert-key)) + (nginx-server-configuration + (listen '("443 ssl")) + (server-name '("files.dthompson.us")) + (root "/var/www/files") + (raw-content '("autoindex on;")) + (ssl-certificate letsencrypt-cert) + (ssl-certificate-key letsencrypt-cert-key)) + (nginx-server-configuration + ;; Laminar recommends using HTTP2 here. + (listen '("443 ssl http2")) + (server-name '("ci.dthompson.us")) + (locations + (list + ;; Reverse proxy to Laminar daemon. + (nginx-location-configuration + (uri "/") + (body '("proxy_pass http://127.0.0.1:8080;" + "proxy_http_version 1.1;" + "proxy_set_header Connection \"\";"))) + ;; Serve static files directly. + (nginx-location-configuration + (uri "/archive") + (body '("alias /var/lib/laminar/archive/;"))))) + (ssl-certificate letsencrypt-cert) + (ssl-certificate-key letsencrypt-cert-key) + ;; Modern TLS only. + (raw-content + '("ssl_protocols TLSv1.3;" + "ssl_ciphers EECDH+AESGCM:EDH+AESGCM;"))) + ;; I used to have the Haunt website under + ;; its own subdomain, and some sites still + ;; point to it. + (nginx-server-configuration + (listen '("443 ssl")) + (server-name '("haunt.dthompson.us")) + (root "/var/www/haunt") + (locations + (list + (nginx-location-configuration + (uri "/") + (body '("rewrite .* https://dthompson.us/projects/haunt.html permanent;"))))) + (ssl-certificate letsencrypt-cert) + (ssl-certificate-key letsencrypt-cert-key)))))) + ;; Git repository viewer. + (let ((cgit (specification->package "cgit"))) + (service (service-type + (inherit cgit-service-type) + (extensions + ;; Replace original nginx-service-type with + ;; our modified one. + (map (lambda (extension) + (if (eq? (service-extension-target extension) + nginx-service-type) + (service-extension nginx-service-type* + cgit-configuration-nginx-config) + extension)) + (service-type-extensions cgit-service-type)))) + (cgit-configuration + (project-list (string-append git-root "/projects.list")) + (repository-directory (string-append git-root "/repositories")) + (root-desc "all i wanted was a pepsi") ; just one pepsi + (enable-git-config? #t) + ;; Cgit only supports the old HTTP "dumb" + ;; protocol, which notably libgit2 won't even + ;; entertain supporting. So, we'll disable + ;; that and use Git itself to provide the HTTP + ;; "smart" protocol instead. + (enable-http-clone? #f) + (enable-index-links? #t) + (enable-index-owner? #f) + (enable-commit-graph? #t) + (enable-log-filecount? #t) + (enable-log-linecount? #t) + (remove-suffix? #t) + (clone-url '("https://git.dthompson.us/$CGIT_REPO_URL.git")) + ;; Is there a way to avoid this wrapper script? + (source-filter (program-file + "cgit-syntax-highlight" + #~(apply execl + (string-append #$cgit "/lib/cgit/filters/syntax-highlighting.py") + (command-line)))) + (nginx + (list (nginx-server-configuration + (listen '("443 ssl")) + (server-name '("git.dthompson.us")) + (root cgit) + (locations + (list + ;; URI paths with .git are handled by + ;; Git's "smart" HTTP protocol. + (nginx-location-configuration + (uri "~ (/.*\\.git/.*)") + (body + `(("fastcgi_pass " ,fcgiwrap-socket ";") + ("fastcgi_param SCRIPT_FILENAME " + ,git "/libexec/git-core/git-http-backend;") + "fastcgi_param QUERY_STRING $query_string;" + "fastcgi_param REQUEST_METHOD $request_method;" + "fastcgi_param CONTENT_TYPE $content_type;" + "fastcgi_param CONTENT_LENGTH $content_length;" + ("fastcgi_param GIT_PROJECT_ROOT " + ,git-root "/repositories;") + "fastcgi_param PATH_INFO $1;"))) + ;; Redirect old URLs to .git pages to + ;; the new .git-less URL. This + ;; doesn't handle deeper links but + ;; that's okay. + (nginx-location-configuration + (uri "~ (/.*)\\.git") + (body + `("return 301 $1;"))) + ;; Serve a static file if one exists, + ;; otherwise send the request to + ;; cgit. + (nginx-location-configuration + (uri "/") + (body + '("try_files $uri @cgit;"))) + (nginx-location-configuration + (uri "@cgit") + (body `("fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi;" + "fastcgi_param PATH_INFO $uri;" + "fastcgi_param QUERY_STRING $args;" + "fastcgi_param HTTP_HOST $server_name;" + ("fastcgi_pass " ,fcgiwrap-socket ";")))))) + (ssl-certificate letsencrypt-cert) + (ssl-certificate-key letsencrypt-cert-key))))))) + ;; fcgriwrap wraps cgit. + (service fcgiwrap-service-type + (fcgiwrap-configuration + ;; Use git group for read-only access to gitolite + ;; repos. + (group "git") + (socket (string-append "tcp:" fcgiwrap-socket)))) + ;; Log rotation. + (simple-service 'rotate-logs + rottlog-service-type + (list (log-rotation + (frequency 'daily) + (files '("/var/log/nginx/access.log" + "/var/log/nginx/error.log")) + (options `("storedir /var/log/nginx" + ;; Keep a week of logs. + "rotate 6" + ;; Run post-rotate once per + ;; rotation rather than once + ;; for each file. + "sharedscripts" + ,@%default-log-rotation-options)) + ;; Tell nginx to reopen its log files after rotation. + (post-rotate (nginx-signal "nginx-post-rotate-hook" SIGUSR1))) + (log-rotation + (frequency 'daily) + (files '("/var/log/fcgiwrap.log")) + (options `("rotate 6" + ,@%default-log-rotation-options))))) + (modify-services %base-services + (guix-service-type config => + (guix-configuration + (inherit config) + (authorized-keys (cons (local-file "keys/signing-key.pub") + %default-authorized-guix-keys))))))) + (bootloader + (bootloader-configuration + (bootloader grub-bootloader) + (targets '("/dev/vda")) + (keyboard-layout keyboard-layout))) + (initrd-modules + (append '("virtio_scsi") %base-initrd-modules)) + (swap-devices (list (swap-space (target "/dev/vda2")))) + (file-systems + (cons* (file-system + (mount-point "/") + (device (uuid "f99d3ff5-57ea-4b20-bca7-bc2d58b4c364" 'ext4)) + (type "ext4")) + %base-file-systems)))) + +(define takemi-host-key + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOrptBAMgs8dGDerBkcmZQ2W/0nEXtOBCl8nLlEwjKdI") + +(define-public takemi-machine + (list (machine + (operating-system takemi-os) + (environment managed-host-environment-type) + (configuration (machine-ssh-configuration + (host-name "dthompson.us") + (system "x86_64-linux") + (user "dave") + (host-key takemi-host-key)))))) diff --git a/ikaruga-home.scm b/ikaruga-home.scm deleted file mode 100644 index 85bd022..0000000 --- a/ikaruga-home.scm +++ /dev/null @@ -1,82 +0,0 @@ -;;; Copyright © 2023 David Thompson -;;; -;;; This program is free software; you can redistribute it and/or -;;; modify it under the terms of the GNU General Public License as -;;; published by the Free Software Foundation; either version 3 of the -;;; License, or (at your option) any later version. -;;; -;;; This program is distributed in the hope that it will be useful, -;;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;;; General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with this program. If not, see -;;; . - -(define-module (ikaruga-home) - #:use-module (dthompson home common) - #:use-module (dthompson home pipewire) - #:use-module (gnu home) - #:use-module (gnu packages) - #:use-module (gnu services)) - -(home-environment - (packages (specifications->packages - '("emacs" - "emacs-better-defaults" - "emacs-buffer-env" - "emacs-doom-modeline" - "emacs-doom-themes" - "emacs-flycheck-guile" - "emacs-geiser-guile" - "emacs-htmlize" - "emacs-js2-mode" - "emacs-magit" - "emacs-magit-annex" - "emacs-markdown-mode" - "emacs-org-reveal" - "emacs-paredit" - "emacs-racket-mode" - "emacs-rainbow-delimiters" - "emacs-smex" - "emacs-typo" - "emacs-use-package" - "emacs-web-mode" - "emacs-which-key" - "emacs-yaml-mode" - "firefox" - "font-google-noto-emoji" - "font-google-noto-sans-cjk" - "font-google-noto-serif-cjk" - "font-inconsolata" - "gimp" - "git" - "git:send-email" - "git-annex" - "gnome-boxes" - "gnome-tweaks" - "gnupg" - "google-chrome-unstable" - "gst-plugins-bad" - "guile@3" - "keepassxc" - "libreoffice" - "libresprite" - "milkytracker" - "ncurses" - "obs" - "openssh" - "pavucontrol" - "pinentry" - "quodlibet" - "sfxr" - "sicp" - "steam" - "strace" - "tiled" - "tor" - "vlc" - "xournal"))) - (services (cons (service home-pipewire-service-type) - common-services))) diff --git a/ikaruga-os.scm b/ikaruga-os.scm deleted file mode 100644 index 28d7b06..0000000 --- a/ikaruga-os.scm +++ /dev/null @@ -1,116 +0,0 @@ -;;; Copyright © 2022 David Thompson -;;; -;;; This program is free software; you can redistribute it and/or -;;; modify it under the terms of the GNU General Public License as -;;; published by the Free Software Foundation; either version 3 of the -;;; License, or (at your option) any later version. -;;; -;;; This program is distributed in the hope that it will be useful, -;;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;;; General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with this program. If not, see -;;; . - -;;; Commentary: -;; -;; Laptop OS configuration. -;; -;; To update using this OS configuration, run: -;; -;; guix system reconfigure ikaruga.scm - -(use-modules (gnu) - (gnu services cups) - (gnu services desktop) - (gnu services games) - (gnu services pm) - (gnu services virtualization) - (gnu services sound) - (gnu services xorg) - (nongnu packages linux) - (nongnu system linux-initrd)) - -(operating-system - (locale "en_US.utf8") - (timezone "America/New_York") - (keyboard-layout (keyboard-layout "us")) - (host-name "ikaruga") - (bootloader (bootloader-configuration - (bootloader grub-efi-bootloader) - (targets (list "/boot/efi")) - (keyboard-layout keyboard-layout))) - ;; Use regular Linux with the big bad proprietary firmware blobs. - (kernel linux) - (initrd microcode-initrd) - ;; sof-firmware is required for sound to work, linux-firmware takes - ;; care of everything else. - (firmware (list sof-firmware linux-firmware)) - (users (cons* (user-account - (name "dave") - (comment "David Thompson") - (group "users") - (home-directory "/home/dave") - (supplementary-groups - '("audio" - "kvm" ; for running VMs - "libvirt" ; also for VMs - "lp" ; for bluetooth - "netdev" - "video" - "wheel"))) ; for sudo - %base-user-accounts)) - (packages (append (list (specification->package "nss-certs")) - %base-packages)) - (services (modify-services (cons* (service gnome-desktop-service-type) - (service bluetooth-service-type) - (service thermald-service-type) - ;; For Nintendo Switch Pro controller - (service joycond-service-type) - (service cups-service-type - (cups-configuration - (web-interface? #t) - (extensions - (list (specification->package - "cups-filters") - ;; Brother laser printers - (specification->package - "brlaser"))))) - ;; Used by GNOME Boxes - (service libvirt-service-type) - (service virtlog-service-type) - %desktop-services) - ;; No pulseaudio. We run pipewire as a home service instead. - (delete pulseaudio-service-type) - ;; Use Wayland instead of X11 - (gdm-service-type config => - (gdm-configuration - (inherit config) - (wayland? #t))) - ;; Get nonguix substitutes. - (guix-service-type config => - (guix-configuration - (inherit config) - (substitute-urls - (append (list "https://substitutes.nonguix.org") - %default-substitute-urls)) - (authorized-keys - (append (list (local-file "keys/nonguix-signing-key.pub")) - %default-authorized-guix-keys)))))) - (mapped-devices (list (mapped-device - (source (uuid "02b1ffb4-d868-4e5f-ab9b-8be3092e3a3c")) - (target "cryptroot") - (type luks-device-mapping)))) - (file-systems (cons* (file-system - (mount-point "/boot/efi") - (device (uuid "91D3-F76B" 'fat32)) - (type "vfat")) - (file-system - (mount-point "/") - (device "/dev/mapper/cryptroot") - (type "ext4") - (dependencies mapped-devices)) - %base-file-systems)) - (name-service-switch %mdns-host-lookup-nss)) diff --git a/rise-home.scm b/rise-home.scm deleted file mode 100644 index c072142..0000000 --- a/rise-home.scm +++ /dev/null @@ -1,65 +0,0 @@ -;;; Copyright © 2023 David Thompson -;;; -;;; This program is free software; you can redistribute it and/or -;;; modify it under the terms of the GNU General Public License as -;;; published by the Free Software Foundation; either version 3 of the -;;; License, or (at your option) any later version. -;;; -;;; This program is distributed in the hope that it will be useful, -;;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;;; General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with this program. If not, see -;;; . - -(define-module (rise-home) - #:use-module (dthompson home common) - #:use-module (gnu home) - #:use-module (gnu packages) - #:use-module (gnu services)) - -(home-environment - (packages (specifications->packages - '("audacity" - "alsa-utils" - "ardour" - "blender" - "calf" - "carla" - "dragonfly-reverb" - "emacs" - "emacs-better-defaults" - "emacs-buffer-env" - "emacs-doom-modeline" - "emacs-doom-themes" - "emacs-flycheck-guile" - "emacs-geiser-guile" - "emacs-magit" - "emacs-markdown-mode" - "emacs-paredit" - "emacs-rainbow-delimiters" - "emacs-smex" - "emacs-use-package" - "emacs-which-key" - "firefox" - "font-google-noto-sans-cjk" - "font-google-noto-serif-cjk" - "font-inconsolata" - "gimp" - "git" - "gnome-tweaks" - "htop" - "hydrogen" - "jack" - "lsp-plugins" - "milkytracker" - "obs" - "openssh" - "patchage" - "qjackctl" - "sfxr" - "x42-plugins" - "yt-dlp"))) - (services common-services)) diff --git a/rise-os.scm b/rise-os.scm deleted file mode 100644 index 7dc5247..0000000 --- a/rise-os.scm +++ /dev/null @@ -1,120 +0,0 @@ -;;; Copyright © 2023 David Thompson -;;; -;;; This program is free software; you can redistribute it and/or -;;; modify it under the terms of the GNU General Public License as -;;; published by the Free Software Foundation; either version 3 of the -;;; License, or (at your option) any later version. -;;; -;;; This program is distributed in the hope that it will be useful, -;;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;;; General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with this program. If not, see -;;; . - -;;; Commentary: -;; -;; Digital Audio Workstation configuration. -;; -;; To update using this OS configuration, run: -;; -;; sudo -E guix system reconfigure rise.scm - -(use-modules (gnu) - (gnu services cups) - (gnu services desktop) - (gnu services pm) - (gnu services sound) - (nongnu packages linux) - (nongnu system linux-initrd)) - -(operating-system - (locale "en_US.utf8") - (timezone "America/New_York") - (keyboard-layout (keyboard-layout "us")) - (host-name "rise") - (bootloader (bootloader-configuration - (bootloader grub-efi-bootloader) - (targets (list "/boot/efi")) - (keyboard-layout keyboard-layout))) - ;; Use regular Linux with the big bad proprietary firmware blobs. - (kernel linux) - ;; Install microcode updates because why the heck wouldn't you want - ;; this??? - (initrd microcode-initrd) - ;; sof-firmware is required for sound to work, linux-firmware takes - ;; care of everything else. - (firmware (list sof-firmware linux-firmware)) - (users (cons* (user-account - (name "dave") - (comment "David Thompson") - (group "users") - (home-directory "/home/dave") - (supplementary-groups - '("audio" - "kvm" ; for VMs - "lp" ; for bluetooth - "netdev" - "realtime" ; for realtime prioritization - "video" - "wheel"))) ; for sudo - %base-user-accounts)) - (groups (cons (user-group - (name "realtime") - (system? #t)) - %base-groups)) - (packages (append (map specification->package - '("ncurses" "nss-certs" "strace")) - %base-packages)) - (services (modify-services - (cons* (service gnome-desktop-service-type) - (service bluetooth-service-type) - ;; Keep CPU temp in check. - (service thermald-service-type) - ;; Enable CUPS web UI and also add the extension - ;; for my Brother laser printer. - (service cups-service-type - (cups-configuration - (web-interface? #t) - (extensions - (map specification->package '("cups-filters" "brlaser"))))) - ;; The first entry increases the maximum realtime - ;; priority for non-privileged processes; the - ;; second entry lifts any restriction of the - ;; maximum address space that can be locked in - ;; memory. - (service pam-limits-service-type - (list - (pam-limits-entry "@realtime" - 'both 'rtprio 99) - (pam-limits-entry "@realtime" - 'both 'memlock 'unlimited))) - %desktop-services) - ;; In this house, we use JACK. - (delete pulseaudio-service-type) - ;; Get nonguix substitutes. - (guix-service-type config => - (guix-configuration - (inherit config) - (substitute-urls - (append (list "https://substitutes.nonguix.org") - %default-substitute-urls)) - (authorized-keys - (append (list (local-file "keys/nonguix-signing-key.pub")) - %default-authorized-guix-keys)))))) - (mapped-devices (list (mapped-device - (source (uuid "ee0a37d1-36d6-4e50-8af0-fc0bfe8c22ef")) - (target "cryptroot") - (type luks-device-mapping)))) - (file-systems (cons* (file-system - (mount-point "/boot/efi") - (device (uuid "1F21-80A1" 'fat32)) - (type "vfat")) - (file-system - (mount-point "/") - (device "/dev/mapper/cryptroot") - (type "ext4") - (dependencies mapped-devices)) %base-file-systems)) - (name-service-switch %mdns-host-lookup-nss)) diff --git a/takemi-os.scm b/takemi-os.scm deleted file mode 100644 index 5bac09e..0000000 --- a/takemi-os.scm +++ /dev/null @@ -1,348 +0,0 @@ -(use-modules (gnu) - (gnu packages version-control) - (gnu services admin) - (gnu services certbot) - (gnu services cgit) - (gnu services ci) - (gnu services networking) - (gnu services ssh) - (gnu services version-control) - (gnu services web)) - -(define letsencrypt-cert - "/etc/letsencrypt/live/dthompson.us/fullchain.pem") -(define letsencrypt-cert-key - "/etc/letsencrypt/live/dthompson.us/privkey.pem") -(define dave-pub-key (local-file "keys/dave.pub")) -(define git-root "/var/lib/gitolite") -(define fcgiwrap-socket "127.0.0.1:9000") - -(define nginx-accounts - (list (user-group (name "nginx") (system? #t)) - (user-account - (name "nginx") - (group "nginx") - (supplementary-groups '("git")) - (system? #t) - (comment "nginx server user") - (home-directory "/var/empty") - (shell (file-append (specification->package "shadow") - "/sbin/nologin"))))) - -(define (nginx-signal name signal) - (program-file - name - #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) - (kill pid #$signal)))) - -;; Need to override the default nginx service account configuration so -;; that the nginx user is a member of the git group. -(define nginx-service-type* - (service-type - (inherit nginx-service-type) - (extensions - (map (lambda (extension) - (if (eq? (service-extension-target extension) - account-service-type) - (service-extension account-service-type - (const nginx-accounts)) - extension)) - (service-type-extensions nginx-service-type))))) - -(define takemi-os - (operating-system - (locale "en_US.utf8") - (timezone "America/New_York") - (keyboard-layout (keyboard-layout "us")) - (host-name "takemi") - (users (cons* (user-account - (name "dave") - (comment "David Thompson") - (group "users") - (home-directory "/home/dave") - (supplementary-groups - '("wheel" "netdev"))) - (user-account - (name "publish") - (comment "Web file publisher") - (group "publish") - (home-directory "/var/www") - (system? #t) - (create-home-directory? #f)) - %base-user-accounts)) - (groups (cons* (user-group - (name "publish") - (system? #t)) - %base-groups)) - (sudoers-file - (plain-file "sudoers" - (string-append (plain-file-content %sudoers-specification) - ;; 'guix deploy' requires no password - ;; sudo capability. - "dave ALL = NOPASSWD: ALL\n"))) - (packages - (append (map specification->package '("emacs" "nss-certs" "rsync" "git" "laminar")) - %base-packages)) - (services - (cons* - (service dhcp-client-service-type) - (service openssh-service-type - (openssh-configuration - (password-authentication? #f) - ;; So I can forward ports from my local host to - ;; the server and have the ports accessible from - ;; the internet. - (gateway-ports? #t) - (authorized-keys - `(("dave" ,dave-pub-key) - ("publish" ,dave-pub-key))))) - ;; Git repository hosting. - (service gitolite-service-type - (gitolite-configuration - (admin-pubkey dave-pub-key) - (rc-file (gitolite-rc-file - ;; Grant read access to git group so - ;; cgit will work. - (umask #o0027) - (git-config-keys "gitweb\\..*"))))) - ;; Continuous integration. - (service laminar-service-type - (laminar-configuration - (supplementary-groups '("git")))) - ;; TLS certificates. Certbot extends nginx with configuration to - ;; redirect all HTTP requests to HTTPS. - (service (service-type - (inherit certbot-service-type) - (extensions - ;; Replace original nginx-service-type with - ;; our modified one. - (map (lambda (extension) - (if (eq? (service-extension-target extension) - nginx-service-type) - (service-extension nginx-service-type* - (@@ (gnu services certbot) - certbot-nginx-server-configurations)) - extension)) - (service-type-extensions certbot-service-type)))) - (certbot-configuration - (email "dthompson2@worcester.edu") - (certificates - (list - (certificate-configuration - (domains '("dthompson.us" - "www.dthompson.us" - "git.dthompson.us" - "ci.dthompson.us" - "files.dthompson.us" - "haunt.dthompson.us")) - ;; Send SIGHUP signal to nginx to trigger a - ;; configuration reload, thus loading the - ;; updated certificates. - (deploy-hook (nginx-signal "nginx-deploy-hook" SIGHUP))))) - (webroot "/var/www/certbot"))) - (service nginx-service-type* - (nginx-configuration - (server-blocks - (list (nginx-server-configuration - (listen '("443 ssl")) - (server-name '("www.dthompson.us")) - (root "/var/www/blog") - ;; I used to check in the HTML output of - ;; manuals to my blog's git repo which was - ;; super gross. This rewrite rule keeps those - ;; links alive. - (locations - (list - (nginx-location-configuration - (uri "/manuals") - (body '("rewrite ^/manuals/([^/]+)/(.*) https://files.dthompson.us/docs/$1/latest/$2 permanent;"))))) - (ssl-certificate letsencrypt-cert) - (ssl-certificate-key letsencrypt-cert-key)) - (nginx-server-configuration - (listen '("443 ssl")) - (server-name '("files.dthompson.us")) - (root "/var/www/files") - (raw-content '("autoindex on;")) - (ssl-certificate letsencrypt-cert) - (ssl-certificate-key letsencrypt-cert-key)) - (nginx-server-configuration - ;; Laminar recommends using HTTP2 here. - (listen '("443 ssl http2")) - (server-name '("ci.dthompson.us")) - (locations - (list - ;; Reverse proxy to Laminar daemon. - (nginx-location-configuration - (uri "/") - (body '("proxy_pass http://127.0.0.1:8080;" - "proxy_http_version 1.1;" - "proxy_set_header Connection \"\";"))) - ;; Serve static files directly. - (nginx-location-configuration - (uri "/archive") - (body '("alias /var/lib/laminar/archive/;"))))) - (ssl-certificate letsencrypt-cert) - (ssl-certificate-key letsencrypt-cert-key) - ;; Modern TLS only. - (raw-content - '("ssl_protocols TLSv1.3;" - "ssl_ciphers EECDH+AESGCM:EDH+AESGCM;"))) - ;; I used to have the Haunt website under - ;; its own subdomain, and some sites still - ;; point to it. - (nginx-server-configuration - (listen '("443 ssl")) - (server-name '("haunt.dthompson.us")) - (root "/var/www/haunt") - (locations - (list - (nginx-location-configuration - (uri "/") - (body '("rewrite .* https://dthompson.us/projects/haunt.html permanent;"))))) - (ssl-certificate letsencrypt-cert) - (ssl-certificate-key letsencrypt-cert-key)))))) - ;; Git repository viewer. - (let ((cgit (specification->package "cgit"))) - (service (service-type - (inherit cgit-service-type) - (extensions - ;; Replace original nginx-service-type with - ;; our modified one. - (map (lambda (extension) - (if (eq? (service-extension-target extension) - nginx-service-type) - (service-extension nginx-service-type* - cgit-configuration-nginx-config) - extension)) - (service-type-extensions cgit-service-type)))) - (cgit-configuration - (project-list (string-append git-root "/projects.list")) - (repository-directory (string-append git-root "/repositories")) - (root-desc "all i wanted was a pepsi") ; just one pepsi - (enable-git-config? #t) - ;; Cgit only supports the old HTTP "dumb" - ;; protocol, which notably libgit2 won't even - ;; entertain supporting. So, we'll disable - ;; that and use Git itself to provide the HTTP - ;; "smart" protocol instead. - (enable-http-clone? #f) - (enable-index-links? #t) - (enable-index-owner? #f) - (enable-commit-graph? #t) - (enable-log-filecount? #t) - (enable-log-linecount? #t) - (remove-suffix? #t) - (clone-url '("https://git.dthompson.us/$CGIT_REPO_URL.git")) - ;; Is there a way to avoid this wrapper script? - (source-filter (program-file - "cgit-syntax-highlight" - #~(apply execl - (string-append #$cgit "/lib/cgit/filters/syntax-highlighting.py") - (command-line)))) - (nginx - (list (nginx-server-configuration - (listen '("443 ssl")) - (server-name '("git.dthompson.us")) - (root cgit) - (locations - (list - ;; URI paths with .git are handled by - ;; Git's "smart" HTTP protocol. - (nginx-location-configuration - (uri "~ (/.*\\.git/.*)") - (body - `(("fastcgi_pass " ,fcgiwrap-socket ";") - ("fastcgi_param SCRIPT_FILENAME " - ,git "/libexec/git-core/git-http-backend;") - "fastcgi_param QUERY_STRING $query_string;" - "fastcgi_param REQUEST_METHOD $request_method;" - "fastcgi_param CONTENT_TYPE $content_type;" - "fastcgi_param CONTENT_LENGTH $content_length;" - ("fastcgi_param GIT_PROJECT_ROOT " - ,git-root "/repositories;") - "fastcgi_param PATH_INFO $1;"))) - ;; Redirect old URLs to .git pages to - ;; the new .git-less URL. This - ;; doesn't handle deeper links but - ;; that's okay. - (nginx-location-configuration - (uri "~ (/.*)\\.git") - (body - `("return 301 $1;"))) - ;; Serve a static file if one exists, - ;; otherwise send the request to - ;; cgit. - (nginx-location-configuration - (uri "/") - (body - '("try_files $uri @cgit;"))) - (nginx-location-configuration - (uri "@cgit") - (body `("fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi;" - "fastcgi_param PATH_INFO $uri;" - "fastcgi_param QUERY_STRING $args;" - "fastcgi_param HTTP_HOST $server_name;" - ("fastcgi_pass " ,fcgiwrap-socket ";")))))) - (ssl-certificate letsencrypt-cert) - (ssl-certificate-key letsencrypt-cert-key))))))) - ;; fcgriwrap wraps cgit. - (service fcgiwrap-service-type - (fcgiwrap-configuration - ;; Use git group for read-only access to gitolite - ;; repos. - (group "git") - (socket (string-append "tcp:" fcgiwrap-socket)))) - ;; Log rotation. - (simple-service 'rotate-logs - rottlog-service-type - (list (log-rotation - (frequency 'daily) - (files '("/var/log/nginx/access.log" - "/var/log/nginx/error.log")) - (options `("storedir /var/log/nginx" - ;; Keep a week of logs. - "rotate 6" - ;; Run post-rotate once per - ;; rotation rather than once - ;; for each file. - "sharedscripts" - ,@%default-log-rotation-options)) - ;; Tell nginx to reopen its log files after rotation. - (post-rotate (nginx-signal "nginx-post-rotate-hook" SIGUSR1))) - (log-rotation - (frequency 'daily) - (files '("/var/log/fcgiwrap.log")) - (options `("rotate 6" - ,@%default-log-rotation-options))))) - (modify-services %base-services - (guix-service-type config => - (guix-configuration - (inherit config) - (authorized-keys (cons (local-file "keys/signing-key.pub") - %default-authorized-guix-keys))))))) - (bootloader - (bootloader-configuration - (bootloader grub-bootloader) - (targets '("/dev/vda")) - (keyboard-layout keyboard-layout))) - (initrd-modules - (append '("virtio_scsi") %base-initrd-modules)) - (swap-devices (list (swap-space (target "/dev/vda2")))) - (file-systems - (cons* (file-system - (mount-point "/") - (device (uuid "f99d3ff5-57ea-4b20-bca7-bc2d58b4c364" 'ext4)) - (type "ext4")) - %base-file-systems)))) - -(define takemi-host-key - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOrptBAMgs8dGDerBkcmZQ2W/0nEXtOBCl8nLlEwjKdI") - -(list (machine - (operating-system takemi-os) - (environment managed-host-environment-type) - (configuration (machine-ssh-configuration - (host-name "dthompson.us") - (system "x86_64-linux") - (user "dave") - (host-key takemi-host-key))))) -- cgit v1.2.3