From 50f771f355f879118d047feac647c69eea58131a Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Fri, 18 Apr 2025 22:04:55 +0200 Subject: [PATCH 1/4] Provision turing with guix This places a starting point for Guix experiments on Turing. At present, it configures the following things on Turing: - SSH - nginx with `certbot` - PostgreSQL - nftables blocking everything but SSH It serves to test out fully declarative deployments and in no point aims to replace our Ansible setup. This commit is purely proposed for merge to enable collaboration. --- .pre-commit-config.yaml | 1 + guix/README.md | 26 ++++ guix/guix-acl-keys/jc.pub | 6 + guix/guix-acl-keys/joe-lovelace.pub | 6 + guix/guix-acl-keys/lovelace.pub | 6 + guix/ssh-keys/chris-lovelace.pub | 1 + guix/ssh-keys/chris.pub | 1 + guix/ssh-keys/jb-lovelace.pub | 1 + guix/ssh-keys/jb.pub | 1 + guix/ssh-keys/jb2.pub | 1 + guix/ssh-keys/jc.pub | 1 + guix/turing.scm | 180 ++++++++++++++++++++++++++++ 12 files changed, 231 insertions(+) create mode 100644 guix/README.md create mode 100644 guix/guix-acl-keys/jc.pub create mode 100644 guix/guix-acl-keys/joe-lovelace.pub create mode 100644 guix/guix-acl-keys/lovelace.pub create mode 100644 guix/ssh-keys/chris-lovelace.pub create mode 100644 guix/ssh-keys/chris.pub create mode 100644 guix/ssh-keys/jb-lovelace.pub create mode 100644 guix/ssh-keys/jb.pub create mode 100644 guix/ssh-keys/jb2.pub create mode 100644 guix/ssh-keys/jc.pub create mode 100644 guix/turing.scm diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af0c8c98..4970c40b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace args: [--markdown-linebreak-ext=md] + exclude: ^guix/guix-acl-keys/ - repo: local hooks: diff --git a/guix/README.md b/guix/README.md new file mode 100644 index 00000000..9031cf3b --- /dev/null +++ b/guix/README.md @@ -0,0 +1,26 @@ +# DevOps Area 51 + +> This directory is a declarative deployment... and part of a system of +> declarative deployments... pay attention to it! + +Here we test out declarative deployments using Guix on Turing. It serves mainly +as a playground for ideas. + +## Deploying + +**Prerequisites** + +- Relevant SSH key (see `./ssh-keys/`) in your SSH agent +- Guix packaging ACL key deployed on turing + - This is usually at `/etc/guix/signing-key`. If not, run `guix archive + --generate-key` as root. + - This is needed for the remote Guix instance to accept packages we build + locally. + +**Deploying** + +```sh +# Optional, but recommended +# guix pull +guix deploy turing.scm +``` diff --git a/guix/guix-acl-keys/jc.pub b/guix/guix-acl-keys/jc.pub new file mode 100644 index 00000000..c6e9ba75 --- /dev/null +++ b/guix/guix-acl-keys/jc.pub @@ -0,0 +1,6 @@ +(public-key + (ecc + (curve Ed25519) + (q #4D454A6338DCC455670972224BC70BEB22BA45E5D90010B9982B8BADF3BF1391#) + ) + ) diff --git a/guix/guix-acl-keys/joe-lovelace.pub b/guix/guix-acl-keys/joe-lovelace.pub new file mode 100644 index 00000000..00cbdcde --- /dev/null +++ b/guix/guix-acl-keys/joe-lovelace.pub @@ -0,0 +1,6 @@ +(public-key + (ecc + (curve Ed25519) + (q #D8779FCB5D4BDF0837560B19D534BE9188D8BEC24EC315A934B8350C5CC75BD8#) + ) +) diff --git a/guix/guix-acl-keys/lovelace.pub b/guix/guix-acl-keys/lovelace.pub new file mode 100644 index 00000000..c5f9fd82 --- /dev/null +++ b/guix/guix-acl-keys/lovelace.pub @@ -0,0 +1,6 @@ +(public-key + (ecc + (curve Ed25519) + (q #C2F473C5A16D14256DC6CBE78DB3F2D782B7723AECCCBCB123BE84DB110BF348#) + ) + ) diff --git a/guix/ssh-keys/chris-lovelace.pub b/guix/ssh-keys/chris-lovelace.pub new file mode 100644 index 00000000..c496d536 --- /dev/null +++ b/guix/ssh-keys/chris-lovelace.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9bVRTi9UIihz9B2wRpnsyl/1NqXJXuea6aPrH/h+o2 cj@lovelace.box.pydis.wtf diff --git a/guix/ssh-keys/chris.pub b/guix/ssh-keys/chris.pub new file mode 100644 index 00000000..c7c2d104 --- /dev/null +++ b/guix/ssh-keys/chris.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMxOPLzQEOJtBJJ6Od9ucrDUpAFOviqJaUAvoG8NzyM chris@neptune diff --git a/guix/ssh-keys/jb-lovelace.pub b/guix/ssh-keys/jb-lovelace.pub new file mode 100644 index 00000000..9e2acc67 --- /dev/null +++ b/guix/ssh-keys/jb-lovelace.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIFKEXZxjRHz7Isq6+XmwkVu+PLDtlVRWlWfvx1QFxCN joe@lovelace diff --git a/guix/ssh-keys/jb.pub b/guix/ssh-keys/jb.pub new file mode 100644 index 00000000..dffdbd8e --- /dev/null +++ b/guix/ssh-keys/jb.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPyNdEOw7tfOHWCM0w2A7UzspnYYpNiF+nak51dcx3d7 diff --git a/guix/ssh-keys/jb2.pub b/guix/ssh-keys/jb2.pub new file mode 100644 index 00000000..66ad73f7 --- /dev/null +++ b/guix/ssh-keys/jb2.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBAeclEz5F0yR4ip/cCbsJ6uHdo8QPK5FBPb6aH/e2Fg diff --git a/guix/ssh-keys/jc.pub b/guix/ssh-keys/jc.pub new file mode 100644 index 00000000..a4ac0573 --- /dev/null +++ b/guix/ssh-keys/jc.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINoHtDPD+w3rKGW4JVEDXidpRM1UXksC+/cMFgCykQBy jc@turing.box.chrisjl.dev diff --git a/guix/turing.scm b/guix/turing.scm new file mode 100644 index 00000000..937b3c16 --- /dev/null +++ b/guix/turing.scm @@ -0,0 +1,180 @@ +;; Module imports +(use-modules (gnu) + (guix) + (gnu packages databases) + (gnu packages linux) + (gnu packages tmux) + (gnu packages vim) + (gnu services admin) + (gnu services certbot) + (gnu services databases) + (gnu services networking) + (gnu services web)) +(use-service-modules networking ssh) +(use-package-modules bootloaders) + +;; Getting "unauthorized public key"? +;; your key needs to be in the guix authorized-keys, search for `guix-archive-key`. +;; Add your key there, then: +;; scp -r . turing.box.chrisjl.dev:guix +;; ssh turing.box.chrisjl.dev +;; cd guix +;; vim turing.scm +;; # Delete the `(list (machine ...))` stuff +;; # Add %turing-os +;; # Save +;; sudo guix system reconfigure turing.scm + +(define %this-dir (dirname (current-filename))) + +(define (file-from-cwd path) + (local-file (string-append %this-dir path))) + +(define (ssh-key name) + (file-from-cwd (string-append "/ssh-keys/" name ".pub"))) + +(define (guix-archive-key name) + (file-from-cwd (string-append "/guix-acl-keys/" name ".pub"))) + +(define %hidden-service-turing + (simple-service 'hidden-service-turing tor-service-type + (list (tor-onion-service-configuration + (name "turing") + (mapping '((22 "127.0.0.1:22"))))))) + +(define %certbot-deploy-hook + (program-file + "nginx-deploy-hook" + #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) + (kill pid SIGHUP)))) + +(define (letsencrypt-path hostname filename) + (string-append "/etc/letsencrypt/live/" hostname "/" filename)) + +(define (letsencrypt-key hostname) + (letsencrypt-path hostname "privkey.pem")) + +(define (letsencrypt-cert hostname) + (letsencrypt-path hostname "fullchain.pem")) + +(define %services + (append (list (service openssh-service-type + (openssh-configuration + (permit-root-login #f) + (password-authentication? #f) + (authorized-keys `(("cj" ,(ssh-key "chris") + ,(ssh-key "chris-lovelace")) + ("jc" ,(ssh-key "jc")) + ("j" ,(ssh-key "jb") + ,(ssh-key "jb2") + ,(ssh-key "jb-lovelace")))))) + (service dhcp-client-service-type) + (service postgresql-service-type + (postgresql-configuration + (postgresql postgresql-16))) + (service tor-service-type) + (service nftables-service-type) + (service ntp-service-type) + %hidden-service-turing + (service nginx-service-type + (nginx-configuration + (server-blocks + (list + (nginx-server-configuration + (listen '("443 ssl http2")) + (server-name '("turing.box.pydis.wtf")) + (ssl-certificate (letsencrypt-cert "turing.box.pydis.wtf")) + (ssl-certificate-key (letsencrypt-key "turing.box.pydis.wtf")) + (root "/var/www/turing.box.pydis.wtf")))))) +; The below is added by the certbot role +; (listen '("80" "[::]:80")) +; (server-name '("turing.box.pydis.wtf")) +; (root "/var/www/owlcorp.uk") +; (locations +; (list +; (nginx-location-configuration +; ; Certbot webroot serving +; (uri "/.well-known") +; (body (list "root /var/www; ")))))))))) +; + (service certbot-service-type + (certbot-configuration + (email "ops@owlcorp.uk") + ; Do not add certbot configuration to nginx automatically + ; XXX: seems broken, report upstream? + ; (default-location #f) + (webroot "/var/www") + (certificates + (list + (certificate-configuration + (domains '("turing.box.pydis.wtf")) + (deploy-hook %certbot-deploy-hook)))))) + (service unattended-upgrade-service-type) + (simple-service 'resolv-conf etc-service-type + (list `("resolv.conf" ,(plain-file + "resolv.conf" + "nameserver 1.1.1.1 1.0.0.1\n"))))) + %base-services)) + +;; Operating system description +(define %turing-os + (operating-system + (locale "en_GB.utf8") + (timezone "UTC") + (keyboard-layout (keyboard-layout "gb")) + (bootloader (bootloader-configuration + (bootloader grub-bootloader) + (targets '("/dev/vda")) + (keyboard-layout keyboard-layout))) + (file-systems (cons* (file-system + (mount-point "/") + (device "/dev/vda2") + (type "ext4")) + %base-file-systems)) + (host-name "u-76") + (users (cons* (user-account + (name "cj") + (comment "Chris") + (group "users") + (home-directory "/home/cj") + (supplementary-groups '("wheel" "netdev" "audio" "video"))) + (user-account + (name "jc") + (comment "void") + (group "users") + (home-directory "/home/jc") + (supplementary-groups '("wheel" "netdev" "audio" "video"))) + (user-account + (name "j") + (comment "J") + (group "users") + (home-directory "/home/j") + (supplementary-groups '("wheel" "netdev" "audio" "video"))) + %base-user-accounts)) + (packages (cons* %base-packages)) + (sudoers-file (plain-file "sudoers" "root ALL=(ALL) ALL +%wheel ALL=NOPASSWD: ALL +")) + (services (modify-services %services + (guix-service-type config => + (guix-configuration + (inherit config) + (authorized-keys + (append (list (guix-archive-key "jc") + (guix-archive-key "lovelace") + (guix-archive-key "joe-lovelace")) + %default-authorized-guix-keys)))))))) + +; local deployments: +; SSHKEY=path/to/key USER=myuser guix deploy turing.scm +; USER is usually implicitly declared somewhere +(list (machine + (operating-system %turing-os) + (environment managed-host-environment-type) + (configuration (machine-ssh-configuration + (host-name "turing.box.chrisjl.dev") + (build-locally? #f) + (system "x86_64-linux") + (host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMvvi6P/G+rZ2qUZ+anluvFQwYM/WFZkERygd9X9+xqU") + (user (getenv "USER")) + (identity (getenv "SSHKEY")))))) From 9dabf2a431ddaad9e14a85b59afd9ea3576de270 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sun, 8 Mar 2026 22:39:44 +0000 Subject: [PATCH 2/4] Add memorium to our founder --- guix/resources/motd.txt | 16 ++++++++++++++++ guix/turing.scm | 7 ++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 guix/resources/motd.txt diff --git a/guix/resources/motd.txt b/guix/resources/motd.txt new file mode 100644 index 00000000..7513b700 --- /dev/null +++ b/guix/resources/motd.txt @@ -0,0 +1,16 @@ + .--, .--, + ( ( \.---./ ) ) + '.__/o o\__.' + {= ^ =} + > - < + ________________________.""`-------`"".________________________ +/ \ +\ R.I.P. Christopher J. Lovering / +/ \ +\ 'They popped a cap in his ass.' / +/ \ +\ Dec 26th 1991 - March 8th 2026 / +/ \ +\_______________________________________________________________/ + ___)( )(___ + (((__) (__))) diff --git a/guix/turing.scm b/guix/turing.scm index 937b3c16..ed6756ad 100644 --- a/guix/turing.scm +++ b/guix/turing.scm @@ -42,6 +42,9 @@ (name "turing") (mapping '((22 "127.0.0.1:22"))))))) +(define %motd + (file-from-cwd "/resources/motd.txt")) + (define %certbot-deploy-hook (program-file "nginx-deploy-hook" @@ -113,7 +116,9 @@ (simple-service 'resolv-conf etc-service-type (list `("resolv.conf" ,(plain-file "resolv.conf" - "nameserver 1.1.1.1 1.0.0.1\n"))))) + "nameserver 1.1.1.1 1.0.0.1\n")))) + (simple-service 'motd etc-service-type + (list `("motd" ,%motd)))) %base-services)) ;; Operating system description From da06b9a86d56bb0142cee9bb3a1ec19752c94f99 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Mon, 9 Mar 2026 21:42:09 +0100 Subject: [PATCH 3/4] Add IPv6 connectivity to turing Deployed and host rebooted to cleanly apply. Co-authored-by: Joe Banks --- guix/turing.scm | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/guix/turing.scm b/guix/turing.scm index ed6756ad..d7544a7b 100644 --- a/guix/turing.scm +++ b/guix/turing.scm @@ -71,7 +71,24 @@ ("j" ,(ssh-key "jb") ,(ssh-key "jb2") ,(ssh-key "jb-lovelace")))))) - (service dhcp-client-service-type) + (service static-networking-service-type + (list + (static-networking + (addresses + (list + (network-address + (device "eth0") + (value "5.252.225.193/22")) + (network-address + (device "eth0") + (value "2a03:4000:40:2f2:7460:66ff:feda:145b/64")))) + (routes + (list + (network-route + (destination "default") + (gateway "5.252.224.1")))) + (name-servers + '("1.1.1.1" "1.0.0.1"))))) (service postgresql-service-type (postgresql-configuration (postgresql postgresql-16))) @@ -113,10 +130,6 @@ (domains '("turing.box.pydis.wtf")) (deploy-hook %certbot-deploy-hook)))))) (service unattended-upgrade-service-type) - (simple-service 'resolv-conf etc-service-type - (list `("resolv.conf" ,(plain-file - "resolv.conf" - "nameserver 1.1.1.1 1.0.0.1\n")))) (simple-service 'motd etc-service-type (list `("motd" ,%motd)))) %base-services)) From 475a1dae2451c39f1961d6326e5ca71626cd1991 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Wed, 11 Mar 2026 19:57:07 +0100 Subject: [PATCH 4/4] Refactor Guix deployment into separate module This sets the foundation for being able to test changes to Turing locally via `guix system`. --- .pre-commit-config.yaml | 2 +- guix/deployment.scm | 20 +++++++++++++ guix/{ => machines}/turing.scm | 28 ++++++------------- guix/{ => resources}/guix-acl-keys/jc.pub | 0 .../guix-acl-keys/joe-lovelace.pub | 0 .../guix-acl-keys/lovelace.pub | 0 .../ssh-keys/chris-lovelace.pub | 0 guix/{ => resources}/ssh-keys/chris.pub | 0 guix/{ => resources}/ssh-keys/jb-lovelace.pub | 0 guix/{ => resources}/ssh-keys/jb.pub | 0 guix/{ => resources}/ssh-keys/jb2.pub | 0 guix/{ => resources}/ssh-keys/jc.pub | 0 12 files changed, 30 insertions(+), 20 deletions(-) create mode 100644 guix/deployment.scm rename guix/{ => machines}/turing.scm (88%) rename guix/{ => resources}/guix-acl-keys/jc.pub (100%) rename guix/{ => resources}/guix-acl-keys/joe-lovelace.pub (100%) rename guix/{ => resources}/guix-acl-keys/lovelace.pub (100%) rename guix/{ => resources}/ssh-keys/chris-lovelace.pub (100%) rename guix/{ => resources}/ssh-keys/chris.pub (100%) rename guix/{ => resources}/ssh-keys/jb-lovelace.pub (100%) rename guix/{ => resources}/ssh-keys/jb.pub (100%) rename guix/{ => resources}/ssh-keys/jb2.pub (100%) rename guix/{ => resources}/ssh-keys/jc.pub (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4970c40b..0edc4694 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace args: [--markdown-linebreak-ext=md] - exclude: ^guix/guix-acl-keys/ + exclude: ^guix/resources/guix-acl-keys/ - repo: local hooks: diff --git a/guix/deployment.scm b/guix/deployment.scm new file mode 100644 index 00000000..f156b1eb --- /dev/null +++ b/guix/deployment.scm @@ -0,0 +1,20 @@ +(define-module (deployment)) +(add-to-load-path (dirname (current-filename))) +(use-modules (gnu machine) + (gnu machine ssh) + (machines turing)) + + +; local deployments: +; SSHKEY=path/to/key USER=myuser guix deploy turing.scm +; USER is usually implicitly declared somewhere +(list (machine + (operating-system %turing-os) + (environment managed-host-environment-type) + (configuration (machine-ssh-configuration + (host-name "turing.box.chrisjl.dev") + (build-locally? #f) + (system "x86_64-linux") + (host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMvvi6P/G+rZ2qUZ+anluvFQwYM/WFZkERygd9X9+xqU") + (user (getenv "USER")) + (identity (getenv "SSHKEY")))))) diff --git a/guix/turing.scm b/guix/machines/turing.scm similarity index 88% rename from guix/turing.scm rename to guix/machines/turing.scm index d7544a7b..c0a21b1c 100644 --- a/guix/turing.scm +++ b/guix/machines/turing.scm @@ -1,4 +1,6 @@ ;; Module imports +(define-module (machines turing) + #:export (%turing-os)) (use-modules (gnu) (guix) (gnu packages databases) @@ -25,16 +27,16 @@ ;; # Save ;; sudo guix system reconfigure turing.scm -(define %this-dir (dirname (current-filename))) +(define %guix-dir (dirname (dirname (canonicalize-path (current-filename))))) -(define (file-from-cwd path) - (local-file (string-append %this-dir path))) +(define (resource path) + (local-file (string-append %guix-dir "/resources/" path))) (define (ssh-key name) - (file-from-cwd (string-append "/ssh-keys/" name ".pub"))) + (resource (string-append "/ssh-keys/" name ".pub"))) (define (guix-archive-key name) - (file-from-cwd (string-append "/guix-acl-keys/" name ".pub"))) + (resource (string-append "/guix-acl-keys/" name ".pub"))) (define %hidden-service-turing (simple-service 'hidden-service-turing tor-service-type @@ -43,7 +45,7 @@ (mapping '((22 "127.0.0.1:22"))))))) (define %motd - (file-from-cwd "/resources/motd.txt")) + (resource "/motd.txt")) (define %certbot-deploy-hook (program-file @@ -183,16 +185,4 @@ (guix-archive-key "joe-lovelace")) %default-authorized-guix-keys)))))))) -; local deployments: -; SSHKEY=path/to/key USER=myuser guix deploy turing.scm -; USER is usually implicitly declared somewhere -(list (machine - (operating-system %turing-os) - (environment managed-host-environment-type) - (configuration (machine-ssh-configuration - (host-name "turing.box.chrisjl.dev") - (build-locally? #f) - (system "x86_64-linux") - (host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMvvi6P/G+rZ2qUZ+anluvFQwYM/WFZkERygd9X9+xqU") - (user (getenv "USER")) - (identity (getenv "SSHKEY")))))) +%turing-os diff --git a/guix/guix-acl-keys/jc.pub b/guix/resources/guix-acl-keys/jc.pub similarity index 100% rename from guix/guix-acl-keys/jc.pub rename to guix/resources/guix-acl-keys/jc.pub diff --git a/guix/guix-acl-keys/joe-lovelace.pub b/guix/resources/guix-acl-keys/joe-lovelace.pub similarity index 100% rename from guix/guix-acl-keys/joe-lovelace.pub rename to guix/resources/guix-acl-keys/joe-lovelace.pub diff --git a/guix/guix-acl-keys/lovelace.pub b/guix/resources/guix-acl-keys/lovelace.pub similarity index 100% rename from guix/guix-acl-keys/lovelace.pub rename to guix/resources/guix-acl-keys/lovelace.pub diff --git a/guix/ssh-keys/chris-lovelace.pub b/guix/resources/ssh-keys/chris-lovelace.pub similarity index 100% rename from guix/ssh-keys/chris-lovelace.pub rename to guix/resources/ssh-keys/chris-lovelace.pub diff --git a/guix/ssh-keys/chris.pub b/guix/resources/ssh-keys/chris.pub similarity index 100% rename from guix/ssh-keys/chris.pub rename to guix/resources/ssh-keys/chris.pub diff --git a/guix/ssh-keys/jb-lovelace.pub b/guix/resources/ssh-keys/jb-lovelace.pub similarity index 100% rename from guix/ssh-keys/jb-lovelace.pub rename to guix/resources/ssh-keys/jb-lovelace.pub diff --git a/guix/ssh-keys/jb.pub b/guix/resources/ssh-keys/jb.pub similarity index 100% rename from guix/ssh-keys/jb.pub rename to guix/resources/ssh-keys/jb.pub diff --git a/guix/ssh-keys/jb2.pub b/guix/resources/ssh-keys/jb2.pub similarity index 100% rename from guix/ssh-keys/jb2.pub rename to guix/resources/ssh-keys/jb2.pub diff --git a/guix/ssh-keys/jc.pub b/guix/resources/ssh-keys/jc.pub similarity index 100% rename from guix/ssh-keys/jc.pub rename to guix/resources/ssh-keys/jc.pub