Compare commits

...

No commits in common. "master" and "keyring" have entirely different histories.

67 changed files with 706 additions and 2890 deletions

10
.gitignore vendored
View File

@ -1,10 +0,0 @@
# Emacs
*~
# Private ssh key used for 'guix deploy'
# Note: 'guix deploy' will generate a public key for the provided private key
.deploy-key
.deploy-key.pub
# Environment variable files used for docker-compose/docker; generally contain secrets
*.env

View File

@ -1,13 +0,0 @@
;; -*- mode: scheme; -*-
;; This is the list of OpenPGP keys currently authorized to sign commits in
;; this repository.
(authorizations
(version 0)
((;; primary: "F7BD DC6D BBE6 B16B 2C71 1A02 5FAB 9938 E05B FEC8"
"A0E0 5DC0 09F3 348F F191 19E3 F77E 3193 97CD A716"
(name "rekahsoft-ed25519"))
(;; primary: "F7BD DC6D BBE6 B16B 2C71 1A02 5FAB 9938 E05B FEC8"
"F8D5 46F3 AF37 EF53 D1B6 48BE 7B4D EB93 212B 3022"
(name "rekahsoft-rsa2048"))))

View File

@ -1,24 +0,0 @@
;; -*- mode: scheme; -*-
(channel
(version 0)
(directory ".guix")
(dependencies
(channel
(name nonguix)
(url "https://gitlab.com/nonguix/nonguix")
(branch "master")
(introduction
(channel-introduction
(version 0)
(commit "897c1a470da759236cc11798f4e0a5f7d4d59fbc")
(signer "2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5"))))
(channel
(name rekahsoft-guix)
(url "https://git.rekahsoft.ca/rekahsoft/rekahsoft-guix.git")
(branch "master")
(introduction
(channel-introduction
(version 0)
(commit "191cdaa0947657e0c85fe89ebbb8e7b1e7a8e0a4")
(signer "F8D5 46F3 AF37 EF53 D1B6 48BE 7B4D EB93 212B 3022"))))))

View File

@ -1,169 +0,0 @@
(define-module (rekahsoft guix-config desktop)
#:use-module (gnu)
#:use-module (gnu system nss)
#:use-module (gnu packages gnome)
#:use-module (gnu packages linux)
#:use-module (gnu packages wm)
#:use-module (gnu packages shells)
#:use-module (gnu services virtualization)
#:use-module (gnu services docker)
#:use-module (gnu services desktop)
#:use-module (gnu services nix)
#:use-module (gnu services networking)
#:use-module (gnu services xorg)
#:use-module (gnu services security-token)
#:use-module (nongnu packages linux)
#:use-module (nongnu system linux-initrd)
#:export (%rkd-desktop-services
%rkd-desktop-kernel-arguments
rkd-desktop))
(define %rkd-desktop-services
(append
(list (service bluetooth-service-type)
(service nix-service-type
(nix-configuration
(extra-config (list "substituters = https://cache.nixos.org https://nri.cachix.org\n"
"trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= nri.cachix.org-1:9/BMj3Obc+uio3O5rYGT+egHzkBzDunAzlZZfhCGj6o="))))
(udev-rules-service 'android (specification->package "android-udev-rules")
#:groups '("adbusers"))
(udev-rules-service 'u2f (specification->package "libu2f-host")
#:groups '("plugdev"))
(udev-rules-service 'hackrf (specification->package "hackrf")
#:groups '("dialout"))
(service pcscd-service-type)
(service libvirt-service-type
(libvirt-configuration
(unix-sock-group "libvirt")
(listen-tls? #f)
(listen-tcp? #f)))
(service docker-service-type)
(service qemu-binfmt-service-type
(qemu-binfmt-configuration
(platforms (lookup-qemu-platforms "arm" "aarch64"))))
(service screen-locker-service-type
(screen-locker-configuration
(name "i3lock")
(program (file-append i3lock "/bin/i3lock")))))
(modify-services %desktop-services
;; Enable network-manager-openvpn plugin
(network-manager-service-type config =>
(network-manager-configuration
(inherit config)
(vpn-plugins (list network-manager-openvpn))))
;; Add and authorize non-guix substitute server
(guix-service-type config =>
(guix-configuration
(inherit config)
(substitute-urls
(append (list "https://substitutes.nonguix.org"
"https://guix-ci.home.rekahsoft.ca")
%default-substitute-urls))
(authorized-keys
(append (list (plain-file "non-guix.pub"
"(public-key
(ecc
(curve Ed25519)
(q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98#)
)
)")
(plain-file "rekahsoft-guix.pub"
"(public-key
(ecc
(curve Ed25519)
(q #13EBA5788C96A57B32273782E8CB24834338B7DC00D7C0F103CA2C5576409A78#)
)
)"))
%default-authorized-guix-keys)))))))
(define %rkd-desktop-kernel-arguments
(cons* "resume=/dev/mapper/vg0-swap"
%default-kernel-arguments))
(define (rkd-desktop host-name root-uuid efi-boot-uuid)
(operating-system
(host-name host-name)
(timezone "America/Toronto")
(locale "en_US.utf8")
;; Choose US English keyboard layout.
(keyboard-layout (keyboard-layout "us"))
;; Use the UEFI variant of GRUB with the EFI System
;; Partition mounted on /boot/efi.
(bootloader (bootloader-configuration
(bootloader grub-efi-bootloader)
(targets '("/boot/efi"))
(keyboard-layout keyboard-layout)))
;; Use non-free kernel, intel microcode and proprietary firmware
(kernel linux)
(kernel-arguments %rkd-desktop-kernel-arguments)
(initrd microcode-initrd)
(firmware (list linux-firmware))
;; Specify a mapped device for the encrypted root partition.
;; The UUID is that returned by 'cryptsetup luksUUID'.
(mapped-devices
(list (mapped-device
(source (uuid root-uuid))
(target "crypt")
(type luks-device-mapping))
(mapped-device
(source "vg0")
(targets (list "vg0-root" "vg0-swap"))
(type lvm-device-mapping))))
(file-systems (append
(list (file-system
(device (file-system-label "root"))
(mount-point "/")
(type "btrfs")
(options "subvol=@,compress=zstd")
(dependencies mapped-devices))
(file-system
(device (uuid efi-boot-uuid 'fat))
(mount-point "/boot/efi")
(type "vfat")))
%base-file-systems))
(swap-devices
(list (swap-space
(target (file-system-label "swap"))
(dependencies mapped-devices))))
(users (cons* (user-account
(name "collin")
(comment "Collin J Doering")
(shell (file-append zsh "/bin/zsh"))
(group "users")
(supplementary-groups '("wheel" "netdev" "lp" "libvirt" "docker" "wireshark"
"plugdev" "adbusers" "dialout" "kvm" "audio" "video")))
%base-user-accounts))
(groups (cons* (user-group (name "wireshark"))
%base-groups))
(packages
(append
(map specification->package
'("xinitrc-xsession" ;; for starting users .xinitrc from display manager
"btrfs-progs" ;; for btrfs root filesystem
"docker-compose"
"emacs"
"emacs-guix"
"gvfs" ;; for user mounts
"hackrf" ;; for hackrf user space tools
"soapysdr" ;; SoapySDRUtil and library
"soapyhackrf" ;; SoapySDR library support for the hackrf one
"lvm2" ;; for lvm2 tools
"nix"
"recutils"
"tmux"))
%base-packages))
(services %rkd-desktop-services)
;; Allow resolution of '.local' host names with mDNS.
(name-service-switch %mdns-host-lookup-nss)))

View File

@ -1,93 +0,0 @@
;; (C) Copyright Collin J. Doering 2024
;;
;; 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 <http://www.gnu.org/licenses/>.
(define-module (rekahsoft guix-config home)
#:use-module (gnu home)
#:use-module (gnu packages)
#:use-module (gnu services)
#:use-module (guix profiles)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (gnu home services)
#:use-module (gnu home services shells)
#:use-module (gnu home services ssh)
#:use-module (rekahsoft-gnu packages shellutils)
#:export (%home %home-manifest))
(define-public %home-manifest
(concatenate-manifests
(list
(packages->manifest
(list
;; TODO: this was added upstream (as "go-github-com-junegunn-fzf") but is not as complete as my existing package
fzf
;; Remaining packages from the rekahsoft-guix channel
spaceship-prompt))
(specifications->manifest
'("bat"
"bind:utils" ;; for dig
"bmon"
"curl"
"direnv"
"eza"
"fd"
"gawk"
"git"
"git-lfs"
"git:send-email"
"git:subtree"
"glibc-locales"
"htop"
"jq"
"nmap"
"recutils"
"rhash"
"ripgrep"
"sh-z"
"tmux"
"zsh-autosuggestions"
"zsh-syntax-highlighting")))))
(define %home
(home-environment
(packages
(map (lambda (m)
(list (manifest-entry-item m)
(manifest-entry-output m)))
(manifest-entries %home-manifest)))
(services
(list
(service home-bash-service-type
(home-bash-configuration
(environment-variables '(("PS1" . "[\\u@\\h \\W]\\$ ")))))
(service home-zsh-service-type
(home-zsh-configuration
(zshenv (list (local-file "../../../user-config/zsh/.zshenv" "zshenv")))
(zprofile (list (local-file "../../../user-config/zsh/.zprofile" "zprofile")))
(zshrc (list (local-file "../../../user-config/zsh/.zshrc" "zshrc")))))
(service home-openssh-service-type
(home-openssh-configuration
(hosts
(list (openssh-host (name "*.home.rekahsoft.ca rekahsoft.ca")
(forward-agent? #t))))
(authorized-keys (list))))
(simple-service
'extra-xdg-configuration-files-service
home-xdg-configuration-files-service-type
`(("spaceship.zsh" ,(local-file "../../../user-config/zsh/.config/spaceship.zsh"))
("tmux/tmux.conf" ,(local-file "../../../user-config/tmux/.tmux.conf" "tmux.conf"))))))))

View File

@ -1,26 +0,0 @@
(define-module (rekahsoft guix-config manual laptop-dell-precision)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu services xorg)
#:use-module (nongnu packages nvidia)
#:use-module (nongnu packages linux)
#:use-module (nongnu services nvidia)
#:use-module (rekahsoft guix-config desktop)
#:export (%system))
(define base-system (rkd-desktop "rekahsoft-little" "43e2445a-bcb8-4ade-a2b1-40bc311034f6" "7C07-B4DE"))
(define %system
(operating-system
(inherit base-system)
(kernel-arguments
(append '("modprobe.blacklist=nouveau"
"nvidia_drm.modeset=1"
"quiet")
%rkd-desktop-kernel-arguments))
(services
(append
(list (service nvidia-service-type))
%rkd-desktop-services))))

View File

@ -1,22 +0,0 @@
(define-module (rekahsoft guix-config manual laptop-lenovo-t480s)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu services xorg)
#:use-module (nongnu packages nvidia)
#:use-module (nongnu packages linux)
#:use-module (nongnu services nvidia)
#:use-module (rekahsoft guix-config desktop)
#:export (%system))
(define base-system (rkd-desktop "rekahsoft-mini" "c811a95f-7de8-4c25-8b96-f4d223e5a06e" "8767-90D2"))
(define %system
(operating-system
(inherit base-system)
(services
(append
(list (set-xorg-configuration
(xorg-configuration
(keyboard-layout (operating-system-keyboard-layout base-system)))))
%rkd-desktop-services))))

View File

@ -1,28 +0,0 @@
(define-module (rekahsoft guix-config proxmox-vm-legacy)
#:use-module (gnu)
#:use-module (gnu packages)
#:use-module (rekahsoft guix-config proxmox-vm-lvm-minimal)
#:export (%proxmox-vm-legacy-services
proxmox-vm-legacy))
(define %proxmox-vm-legacy-services %proxmox-vm-lvm-minimal-services)
;; "Legacy" vm's do not use lvm, but are all based on the same image (therefore, same root uuid)
(define (proxmox-vm-legacy host-name)
(let ((base-system (proxmox-vm-lvm-minimal host-name)))
(operating-system
(inherit base-system)
(file-systems
(cons* (file-system
(mount-point "/")
(device
(uuid "f354b908-fd6f-46c9-931b-2bebaac61b56"
'ext4))
(type "ext4"))
%base-file-systems))
(swap-devices
(list (swap-space (target "/dev/sda2"))))
(mapped-devices '()))))

View File

@ -1,179 +0,0 @@
(define-module (rekahsoft guix-config proxmox-vm-lvm-minimal)
#:use-module (gnu)
#:use-module (gnu packages)
#:use-module (gnu system nss)
#:use-module (srfi srfi-1)
#:use-module (gnu services dbus)
#:use-module (gnu services desktop)
#:use-module (gnu services guix)
#:use-module (gnu services networking)
#:use-module (gnu services monitoring)
#:use-module (gnu services shepherd)
#:use-module (gnu services ssh)
#:use-module (gnu services xorg)
#:use-module (gnu packages admin)
#:use-module (gnu packages bash)
#:use-module (gnu packages shells)
#:use-module (rekahsoft guix-config home)
#:export (%proxmox-vm-lvm-minimal-services
proxmox-vm-lvm-minimal))
(define %automation-user "auto")
(define %guix-key (local-file "../../../.pubkeys/guix-coordinator-key.pub"))
;; Keys used for ssh access
(define %deploy-key (local-file "../../../.pubkeys/deploy-key.pub"))
(define %collin-ed25519-key (local-file "../../../.pubkeys/ed25519-861CD08E.pub"))
(define %collin-rsa4096-key (local-file "../../../.pubkeys/rsa4096-6765FB18.pub"))
(define %collin-rsa-key (local-file "../../../.pubkeys/rsa2048-ED51AB07.pub"))
(define syslog-configuration
(plain-file "syslog.conf"
"
# Log all error messages, authentication messages of
# level notice or higher and anything of level err or
# higher to the console.
# Don't log private authentication messages!
*.alert;auth.notice;authpriv.none -/dev/console
# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none -/var/log/messages
# Log \"debug\"-level entries and nothing else.
*.=debug -/var/log/debug
# Same, in a different place.
*.info;mail.none;authpriv.none -/dev/tty12
# The authpriv file has restricted access.
# 'fsync' the file after each line (hence the lack of a leading dash).
authpriv.* /var/log/secure
# Log all the mail messages in one place.
mail.* -/var/log/maillog
# Forward all logs to remote syslog server
*.* @logs.home.rekahsoft.ca
"))
;; TODO: this is a temporary solution; the syslogd service configuration should be extended
;; to allow for the various options supported by inetutils syslogd.
(define syslog-service-hop
(simple-service 'syslogd shepherd-root-service-type
(list
;; Taken from 'gnu/services/base.scm' and and adjusted to allow forwarding to
;; remote hosts using the '-h|--hop' option
(shepherd-service
(documentation "Run the syslog daemon (syslogd).")
(provision '(syslogd))
(requirement '(user-processes))
(actions (list (shepherd-configuration-action syslog-configuration)))
(start #~(let ((spawn (make-forkexec-constructor
(list #$(file-append inetutils "/libexec/syslogd")
"--rcfile" #$syslog-configuration "--hop")
#:pid-file "/var/run/syslog.pid")))
(lambda ()
;; Set the umask such that file permissions are #o640.
(let ((mask (umask #o137))
(pid (spawn)))
(umask mask)
pid))))
(stop #~(make-kill-destructor))))))
;; Services need to be exposed this way so they can be overriden via guix's special
;; record inheritance. Otherwise, if trying to directly use an operating-system's
;; services, an error will be recieved about an abiguous-service called 'system.
(define %proxmox-vm-lvm-minimal-services
(append
(list (service guix-home-service-type
`(("collin" ,%home)))
(service openssh-service-type
(openssh-configuration
(password-authentication? #f)
(authorized-keys
`(("auto" ,%deploy-key)
("collin" ,%collin-ed25519-key ,%collin-rsa4096-key ,%collin-rsa-key)
("root" ,%collin-ed25519-key ,%collin-rsa4096-key ,%collin-rsa-key)))))
(service prometheus-node-exporter-service-type)
(service dhcp-client-service-type)
(service ntp-service-type)
;; Services required by dockerd
(service dbus-root-service-type)
(service elogind-service-type)
syslog-service-hop)
(modify-services
%base-services
(delete syslog-service-type)
(guix-service-type
config => (guix-configuration
(inherit config)
(authorized-keys (cons %guix-key %default-authorized-guix-keys))
(substitute-urls %default-substitute-urls))))))
(define (proxmox-vm-lvm-minimal host-name)
(operating-system
(host-name host-name)
(timezone "America/Toronto")
(locale "en_US.utf8")
(keyboard-layout (keyboard-layout "us"))
(bootloader (bootloader-configuration
(bootloader grub-bootloader)
(targets '("/dev/sda"))))
(initrd-modules
(append '("virtio_scsi") %base-initrd-modules))
(mapped-devices
(list (mapped-device
(source "vg0")
(targets (list "vg0-root" "vg0-swap"))
(type lvm-device-mapping))))
(swap-devices
(list (swap-space
(target (file-system-label "swap"))
(dependencies mapped-devices))))
(file-systems (append
(list (file-system
(device (file-system-label "root"))
(mount-point "/")
(type "ext4")
(dependencies mapped-devices)))
%base-file-systems))
(users (cons* (user-account
(name %automation-user)
(comment "Automation User")
(group "users")
(shell #~(string-append #$bash "/bin/bash"))
(supplementary-groups
'("wheel" "netdev" "audio" "video"))
(home-directory "/home/auto"))
%base-user-accounts))
(sudoers-file
(plain-file "sudoers"
(string-append (plain-file-content %sudoers-specification)
(format #f "~a ALL = NOPASSWD: ALL~%"
%automation-user))))
(packages
(append
(map specification->package
'("recutils"
"openssh"
"tmux"
"emacs"
"emacs-guix"))
%base-packages))
(services %proxmox-vm-lvm-minimal-services)
;; Allow resolution of '.local' host names with mDNS.
(name-service-switch %mdns-host-lookup-nss)))

View File

@ -1,27 +0,0 @@
(define-module (rekahsoft guix-config vms ci-runner0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "ci-runner0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-legacy-services))))

View File

@ -1,27 +0,0 @@
(define-module (rekahsoft guix-config vms ci0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "ci0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-legacy-services))))

View File

@ -1,58 +0,0 @@
(define-module (rekahsoft guix-config vms cloud0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages docker)
#:use-module (gnu packages shells)
#:use-module (gnu packages storage)
#:use-module (gnu services docker)
#:use-module (gnu services mail)
#:use-module (gnu services shepherd)
#:use-module (rekahsoft guix-config proxmox-vm-lvm-minimal)
#:use-module (rekahsoft-gnu services ceph)
#:export (%system))
(define base-system (proxmox-vm-lvm-minimal "cloud0"))
(define %radicale-config-file
(plain-file "radicale.conf" "
[auth]
type = htpasswd
htpasswd_filename = /var/lib/radicale/users
htpasswd_encryption = bcrypt
[server]
hosts = 0.0.0.0:5232
[storage]
filesystem_folder = /var/lib/radicale/collections"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type)
(service radicale-service-type
(radicale-configuration
(config-file %radicale-config-file)))
(service cephfs-service-type
(cephfs-configuration
(name "file-vault-nextcloud")
(mount-point "/mnt/cephfs")
(fsid "0f2890c4-3a78-4859-b7c1-43f749b127b3")
(fs-name "cephfs")
(secret-file "/etc/ceph/ceph.client.file-vault-nextcloud.key")
(monitors (list "172.16.0.20" "172.16.0.21" "172.16.0.22"))
(subdir "/file-vault/nextcloud"))))
%proxmox-vm-lvm-minimal-services))))

View File

@ -1,27 +0,0 @@
(define-module (rekahsoft guix-config vms dash0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "dash0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-legacy-services))))

View File

@ -1,27 +0,0 @@
(define-module (rekahsoft guix-config vms git0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "git0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-legacy-services))))

View File

@ -1,32 +0,0 @@
(define-module (rekahsoft guix-config vms grocy0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-lvm-minimal)
#:export (%system))
(define base-system (proxmox-vm-lvm-minimal "grocy0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(packages
(append
(map specification->package
'("docker-compose"))
(operating-system-packages base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-lvm-minimal-services))))

View File

@ -1,346 +0,0 @@
(define-module (rekahsoft guix-config vms guix-ci0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services base)
#:use-module (gnu services cuirass)
#:use-module (gnu services web)
#:use-module (rekahsoft guix-config proxmox-vm-lvm-minimal)
#:export (%system))
(define base-system (proxmox-vm-lvm-minimal "guix-ci0"))
(define %cuirass-specs
#~(let ((rekahsoft-guix-channel
(channel
(name 'rekahsoft-guix)
(url "https://git.rekahsoft.ca/rekahsoft/rekahsoft-guix.git")
(introduction
(make-channel-introduction
"d910ac4ca1e1a115934b10921bc23f50bd481043"
(openpgp-fingerprint
"F8D5 46F3 AF37 EF53 D1B6 48BE 7B4D EB93 212B 3022")))))
(nonguix-channel
(channel
(name 'nonguix)
(url "https://gitlab.com/nonguix/nonguix")
(introduction
(make-channel-introduction
"897c1a470da759236cc11798f4e0a5f7d4d59fbc"
(openpgp-fingerprint
"2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5"))))))
(list (specification
(name "rekahsoft-guix")
(priority 0)
(build '(channels rekahsoft-guix))
(channels
(cons rekahsoft-guix-channel
%default-channels)))
(specification
(name "rekahsoft-dotfiles")
(build '(manifests "home-manifest.scm"))
(channels
(cons* (channel
(name 'rekahsoft-dotfiles)
(url "https://git.home.rekahsoft.ca/rekahsoft-public/dotfiles.git")
(introduction
(make-channel-introduction
"32b8ebec9a503b9796fda0a8ac3eb11eec744397"
(openpgp-fingerprint
"F8D5 46F3 AF37 EF53 D1B6 48BE 7B4D EB93 212B 3022"))))
nonguix-channel
rekahsoft-guix-channel
%default-channels)))
(specification
(name "guix-machines")
(build '(channels guix-machines))
(channels
(cons* (channel
(name 'guix-machines)
(url "https://git.home.rekahsoft.ca/rekahsoft-public/guix-machines.git")
(introduction
(make-channel-introduction
"acaa20d632da16937508a45ef2cc0083e09bae4c"
(openpgp-fingerprint
"F8D5 46F3 AF37 EF53 D1B6 48BE 7B4D EB93 212B 3022"))))
nonguix-channel
rekahsoft-guix-channel
%default-channels))))))
;; Taken from: https://git.savannah.gnu.org/cgit/guix/maintenance.git/tree/hydra/nginx/berlin.scm
(define (publish-locations url)
"Return the nginx location blocks for 'guix publish' running on URL."
(list (nginx-location-configuration
(uri "/nix-cache-info")
(body
(list
(string-append
"proxy_pass " url "/nix-cache-info;")
;; Cache this file since that's always the first thing we ask
;; for.
"proxy_cache static;"
"proxy_cache_valid 200 100d;" ; cache hits for a looong time.
"proxy_cache_valid any 5m;" ; cache misses/others for 5 min.
"proxy_ignore_client_abort on;"
;; We need to hide and ignore the Set-Cookie header to enable
;; caching.
"proxy_hide_header Set-Cookie;"
"proxy_ignore_headers Set-Cookie;")))
(nginx-location-configuration
(uri "/nar/")
(body
(list
(string-append "proxy_pass " url ";")
"client_body_buffer_size 256k;"
;; Be more tolerant of delays when fetching a nar.
"proxy_read_timeout 60s;"
"proxy_send_timeout 60s;"
;; Enable caching for nar files, to avoid reconstructing and
;; recompressing archives.
"proxy_cache nar;"
"proxy_cache_valid 200 30d;" ; cache hits for 1 month
"proxy_cache_valid 504 3m;" ; timeout, when hydra.gnu.org is overloaded
"proxy_cache_valid any 1h;" ; cache misses/others for 1h.
"proxy_ignore_client_abort on;"
;; Nars are already compressed.
"gzip off;"
;; We need to hide and ignore the Set-Cookie header to enable
;; caching.
"proxy_hide_header Set-Cookie;"
"proxy_ignore_headers Set-Cookie;"
;; Provide a 'content-length' header so that 'guix
;; substitute-binary' knows upfront how much it is downloading.
;; "add_header Content-Length $body_bytes_sent;"
)))
(nginx-location-configuration
(uri "~ \\.narinfo$")
(body
(list
;; Since 'guix publish' has its own caching, and since it relies
;; on the atime of cached narinfos to determine whether a
;; narinfo can be removed from the cache, don't do any caching
;; here.
(string-append "proxy_pass " url ";")
;; For HTTP pipelining. This has a dramatic impact on
;; performance.
"client_body_buffer_size 128k;"
;; Narinfos requests are short, serve many of them on a
;; connection.
"keepalive_requests 600;"
;; Do not tolerate slowness of hydra.gnu.org when fetching
;; narinfos: better return 504 quickly than wait forever.
"proxy_connect_timeout 10s;"
"proxy_read_timeout 10s;"
"proxy_send_timeout 10s;"
;; 'guix publish --ttl' produces a 'Cache-Control' header for
;; use by 'guix substitute'. Let it through rather than use
;; nginx's "expire" directive since the expiration time defined
;; by 'guix publish' is the right one.
"proxy_pass_header Cache-Control;"
"proxy_ignore_client_abort on;"
;; We need to hide and ignore the Set-Cookie header to enable
;; caching.
"proxy_hide_header Set-Cookie;"
"proxy_ignore_headers Set-Cookie;")))
;; Content-addressed files served by 'guix publish'.
(nginx-location-configuration
(uri "/file/")
(body
(list
(string-append "proxy_pass " url ";")
"proxy_cache cas;"
"proxy_cache_valid 200 200d;" ; cache hits
"proxy_cache_valid any 5m;" ; cache misses/others
"proxy_ignore_client_abort on;")))))
(define %publish-url "http://localhost:3000")
;; Modified from: https://git.savannah.gnu.org/cgit/guix/maintenance.git/tree/hydra/nginx/berlin.scm (berlin-locations)
(define (nginx-locations publish-url)
"Return nginx location blocks with 'guix publish' reachable at
PUBLISH-URL."
(append (publish-locations publish-url)
(list
;; Cuirass.
(nginx-location-configuration
(uri "/")
(body (list "proxy_pass http://localhost:8081;")))
;; TODO: disabled as currently there is no auth setup for cuirass
;; (nginx-location-configuration
;; (uri "~ ^/admin")
;; (body
;; (list "if ($ssl_client_verify != SUCCESS) { return 403; } proxy_pass http://localhost:8081;")))
(nginx-location-configuration
(uri "/static")
(body
(list
"proxy_pass http://localhost:8081;"
;; Let browsers cache this for a while.
"expires 10d;"
;; Cache quite aggressively.
"proxy_cache static;"
"proxy_cache_valid 200 5d;"
"proxy_cache_valid any 10m;"
"proxy_ignore_client_abort on;"))))))
(define %extra-content
(list
"default_type application/octet-stream;"
"sendfile on;"
; (accept-languages)
;; Maximum chunk size to send. Partly this is a workaround for
;; <http://bugs.gnu.org/19939>, but also the nginx docs mention that
;; "Without the limit, one fast connection may seize the worker
;; process entirely."
;; <http://nginx.org/en/docs/http/ngx_http_core_module#sendfile_max_chunk>
"sendfile_max_chunk 1m;"
"keepalive_timeout 65;"
;; Use HTTP 1.1 to talk to the backend so we benefit from keep-alive
;; connections and chunked transfer encoding. The latter allows us to
;; make sure we do not cache partial downloads.
"proxy_http_version 1.1;"
;; The 'inactive' parameter for caching is not very useful in our
;; case: all that matters is that LRU sweeping happens when 'max_size'
;; is hit.
;; cache for nar files
"proxy_cache_path /var/cache/nginx/nar"
" levels=2"
" inactive=8d" ; inactive keys removed after 8d
" keys_zone=nar:4m" ; nar cache meta data: ~32K keys
" max_size=10g;" ; total cache data size max
;; cache for content-addressed files
"proxy_cache_path /var/cache/nginx/cas"
" levels=2"
" inactive=180d" ; inactive keys removed after 180d
" keys_zone=cas:8m" ; nar cache meta data: ~64K keys
" max_size=50g;" ; total cache data size max
;; cache for build logs
"proxy_cache_path /var/cache/nginx/logs"
" levels=2"
" inactive=60d" ; inactive keys removed after 60d
" keys_zone=logs:8m" ; narinfo meta data: ~64K keys
" max_size=4g;" ; total cache data size max
;; cache for static data
"proxy_cache_path /var/cache/nginx/static"
" levels=1"
" inactive=10d" ; inactive keys removed after 10d
" keys_zone=static:1m" ; nar cache meta data: ~8K keys
" max_size=200m;" ; total cache data size max
;; If Hydra cannot honor these delays, then something is wrong and
;; we'd better drop the connection and return 504.
"proxy_connect_timeout 10s;"
"proxy_read_timeout 10s;"
"proxy_send_timeout 10s;"
;; Cache timeouts for a little while to avoid increasing pressure.
"proxy_cache_valid 504 30s;"))
(define %nginx-configuration
(nginx-configuration
(server-blocks
(list
(nginx-server-configuration
(listen '("80"))
(server-name '("guix-ci0.home.rekahsoft.ca"
"guix-ci.home.rekahsoft.ca"
;; <https://logs.guix.gnu.org/guix/2021-11-20.log#155427>
"~[0-9]$"))
(locations (nginx-locations %publish-url))
(raw-content
(list
"access_log /var/log/nginx/http.access.log;"
"proxy_set_header X-Forwarded-Host $host;"
"proxy_set_header X-Forwarded-Port $server_port;"
"proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;")))))
(global-directives
'((worker_processes . 4)
(pcre_jit . on)
(events . ((worker_connections . 1024)))))
(extra-content
(string-join %extra-content "\n"))))
(define %nginx-cache-activation
;; Make sure /var/cache/nginx exists on the first run.
(simple-service 'nginx-/var/cache/nginx
activation-service-type
(with-imported-modules '((guix build utils))
#~(begin
(use-modules (guix build utils))
(mkdir-p "/var/cache/nginx")))))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service cuirass-service-type
(cuirass-configuration
(host "localhost")
(specifications %cuirass-specs)))
%nginx-cache-activation
(service nginx-service-type %nginx-configuration)
(service guix-publish-service-type
(guix-publish-configuration
(port 3000)
(cache "/var/cache/guix/publish"))))
(modify-services %proxmox-vm-lvm-minimal-services
;; Add and authorize non-guix substitute server
(guix-service-type config =>
(guix-configuration
(inherit config)
(extra-options '("--max-jobs=4"))
(substitute-urls
(append (list "https://substitutes.nonguix.org")
(guix-configuration-substitute-urls config)))
(authorized-keys
(append (list (plain-file "non-guix.pub"
"(public-key
(ecc
(curve Ed25519)
(q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98#)
)
)"))
(guix-configuration-authorized-keys config))))))))))

View File

@ -1,32 +0,0 @@
(define-module (rekahsoft guix-config vms loki-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "loki"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(packages
(append
(map specification->package
'("docker-compose"))
(operating-system-packages base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-legacy-services))))

View File

@ -1,27 +0,0 @@
(define-module (rekahsoft guix-config vms my0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "my0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-legacy-services))))

View File

@ -1,42 +0,0 @@
(define-module (rekahsoft guix-config vms postgres-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu packages databases)
#:use-module (gnu services databases)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "postgres"))
(define postgres-hba
(plain-file "pg_hba.conf"
"
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
host all all 172.16.0.0/20 md5"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service postgresql-service-type
(postgresql-configuration
(postgresql postgresql-10)
(config-file (postgresql-config-file
(hba-file postgres-hba)
(extra-config
'(("listen_addresses" "*"))))))))
%proxmox-vm-legacy-services))))

View File

@ -1,28 +0,0 @@
(define-module (rekahsoft guix-config vms prom0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "prom0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-legacy-services))))

View File

@ -1,27 +0,0 @@
(define-module (rekahsoft guix-config vms searx0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-legacy)
#:export (%system))
(define base-system (proxmox-vm-legacy "searx0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-legacy-services))))

View File

@ -1,27 +0,0 @@
(define-module (rekahsoft guix-config vms vault0-home-rekahsoft-ca)
#:use-module (gnu)
#:use-module (gnu system)
#:use-module (gnu packages shells)
#:use-module (gnu services docker)
#:use-module (rekahsoft guix-config proxmox-vm-lvm-minimal)
#:export (%system))
(define base-system (proxmox-vm-lvm-minimal "vault0"))
(define %system
(operating-system
(inherit base-system)
(users (cons*
(user-account
(name "collin")
(comment "Master User")
(group "users")
(shell #~(string-append #$zsh "/bin/zsh"))
(supplementary-groups
'("wheel" "netdev" "audio" "video" "docker"))
(home-directory "/home/collin"))
(operating-system-users base-system)))
(services
(append
(list (service docker-service-type))
%proxmox-vm-lvm-minimal-services))))

View File

@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDJUw9g8nlwChpfvxmoBHXs+XN+l/E/00q74GQSfMxe8CN0128c5AE68pZZviCGTUvlESqkytBRdOV1HkG1P9JqZWkkVN2Agc0HRapVCWryFIO59VPg7Nurzkdr/Jft7Nv+BKJcfptzzq2JG54rUPw1Q0Kl9YG6oHoQuPRRWJbzdgpcULaEmKgg07I+Gc/viRSHjjBMjfR1Pvp2iKan7VTnEKsrkKnEiELxNKHvQVmYnStnf0SYL87AhcIB0C8wAE8d5FqzBQ+PAcqoeYakXnqm2C6TEiUH7vCmDusoR8gCL0xQTduSQKPDgbBWCeN3X9f3zh/8KWHCLauuU/wFNpfwQV93DQ4F5e+rJcNMv1VHGjggjF+zTvso+sbOlDjV2befFcbaDuHDvqIltm1III64Zqde65BbjdpTwCGZWJN76ML4TGxqsHSsnrr4g3Wlh2xO+LjbYEs/6ORTTQQTjhHfF+TT/URatAAOuZ8Dm0jyGO6ZDETddaO8xFas2q2vf68=

View File

@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGyBPoUlcUrkyL5j+LILb8Zq+gJydQQyJRIbxi+B1ZWF openpgp:0x861CD08E

View File

@ -1,7 +0,0 @@
(public-key
(ecc
(curve Ed25519)
(q #4C9DDCA82172D07FE644BEB4B5B39429F835BEE7E11E3F770EAB79ECBE226DE9#)
)
)

View File

@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDbkiHEE2y85M1qkOBG9p0nuplkFETuMmRudDJ2ryf2gakD1NGMbKz82EHWWyPagkXMHx0tw4TZyV/AOq2LqzH8ZVDAj+QOO2wkFIRIXr3rsZGeMO9kpaZORwdTMTABRPcIg+KteWXe7Qq4I1H3izSuIIbyOW2wFdHkMxWAJEGr2L/q8qMlYbCbDwj1v7AQQRUjy8a0pTyG9eZ6kmc0bVxuFGAsvKtJSPpYxFNNGr8f2EY977DkmHK146B+Ce6Vp9wFDV5PwIQOFnZFXLDoYkI/ndshW+7+LQKViYP/ftIMTt4LC/0BC56heHOKkTCE3FHo4W/0zxfJdcLLkfRoev9T

View File

@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCjVU55upz6s1E0JFfTWKIymDZPkT3aGWjz6T6g5vZ9gAyKdkvqlYZAX6PK/q6ojxqVGuug63+TrhaGMLfz6TfjKoXUK2fgBf0dKCvSRvIMaaBkzA6QcUHXoFqD/5wHqyZurmUArFWEh1puXj1XFl8fhMqEKJyPQQCDb6NfMjTUuK6TAwcoUfWU1y/j2gYeYbUsFCnBnxgtAUm+DLz9Ym0MbLcpNfBPXrX9JxIpVaZIphF+d/GfGMB7vnAPlc6hlyJypVMkMBn4vdYyC6UQ/6qtpDWnSAFaLDa7mXpTihbN2o8C8w4rxSvWf9LQ3KSGUg4x1k7wXlrqhDCBD7VWe+4tlyfNKia3VeWely5sR1onKVeT+ya44s1525sdbyx46E/6uwxZc9ZoJv35tKocv7kInP7Vum/vYAP/YH/SsbWSjk9WTTlmxGHnZIYNKUq1xN7VvYSP17OEcFCbCPFULbAHGT6o4Hi8D1um7U31opSCxccHk3yWohK9stGntm0Vhrlotqn7mPcvPd4NnjukkLdLuL94fiU+Ka1aNGmnnOypfecm2GWMeAcPBQdthL960hP42HtnRerHEns9nfI/99GiBajcu9t95L0sPWJzemNGWm6MgBAniyJLqEI2CiUoRnSNYjNRVoxRPxRN+PnWEj5UEpuowdThPrchxY9MLJaoNQ== openpgp:0x6765FB18

View File

@ -1,359 +0,0 @@
#+TITLE: Guix Machines
#+AUTHOR: Collin J. Doering
#+BEGIN_EXPORT html
<p><a href="https://guix-ci.home.rekahsoft.ca/jobset/guix-machines"><img src="https://guix-ci.home.rekahsoft.ca/jobset/guix-machines/badge.svg?type=0" alt="Cuirass Status"></a></p>
#+END_EXPORT
#+begin_abstract
Guix configurations for all Guix powered systems privately managed by the author. This
includes all virtual machines for my home network, cloud/vps instances, as well as personal
computers. Due to the variety of types of systems managed via this repository, two mutable
deployment methodologies are supported:
1. A push based model, using ~guix deploy~[fn:1] to remotely deploy changes (useful for example
from ci/cd).
2. A pull based model, using ~guix~ directly from the target, along with either the entire
repository, or its channel file.
Immutable deployment is not yet supported, but is certainly possible given Guix's ability to
build an ~operating-system~ configuration into a image.
#+end_abstract
* Repository Structure
- ~channels*.scm~ :: [[*Guix Channel Files][Guix channel files]]
- ~deploy/~ :: Folder containing all ~guix deploy~ configurations
- ~.gitignore~ :: Files ignored by git
- ~.guix/~ :: Guix channel directory
- ~.guix-authorizations~ :: Guix authorizations file[fn:2]
- ~.guix-channel~ :: Guix channel file[fn:3]
- ~.pub-keys/~ :: Folder containing public key files used by Guix configurations
- ~README.org~ :: Org-mode[fn:4] documentation
- ~TODO.org~ :: Org-mode todo's, known issues and future aspirations
- ~unguix/~ :: Docker/docker-compose files used on deployed instances, managed
outside of guix. Once better support for running docker/docker-compose via shepherd,
specified declaratively via Guix configuration has been implemented, this directory and all
files within it should be able to be removed.
** User Supplied Files Required for Push Based Deployment
- ~.deploy-key~ :: Private ssh key used to deploy changes to the target.
** Guix Channel Files
Guix channels[fn:5] allow for Guix to be customized and extended. They are also critical for
replicating a Guix system[fn:6]. As mentioned above, there are two primary classes of
deployments that are managed using this repository, push based and pull based. In both cases,
what specific versions of software that will be installed during deployment depends on the
guix channels in use. To ensure reproducibility, a ~channels.scm~ file is provided in this
repository that is expected to be used during deployment. It pins external guix channels to
specific versions.
If for some reason channels need to be pinned for a specific deployment, a new channel file
named ~channels-<hostname>.scm~ can be created and used in place of normally used channel
file.
*** TODO Updating guix channels used for deployment
**This doesn't work right unless your channels match what is expected by this repository.**
#+begin_src shell
guix time-machine -- describe -f channels > channels.scm
#+end_src
** ~guix-machines~ the Guix Channel
This repository is itself a Guix channel, which allows operating-system configurations to
come directly from the channel, and the version of this configuration be managed just like
any other guix channel. It also facilitates CI, allowing for changes this channel be
evaluated by Cuirass at [[https://guix-ci.home.rekahsoft.ca]][fn:7]. This channel does not define
any packages, only system configurations and machine specifications for deployment.
At a later date, this also will allow for building of machine images for immutable
deployment, bootstrapping and more.
* TODO Initializing a System
** Using an existing guix installation image
*** TODO Producing an installation image
TODO: It would be convent to be able to produce an image that can be used to install my
normal setup. This would avoid pulling my channels, as well as downloading software (it could
all be pre-packaged in the image).
If you produce and use this installation image, you can skip to [[*Disk Setup and Partitioning][Disk Setup and Partitioning]].
*** TODO Setup Installation
TODO: network needs to be setup; local, keymap, and font too.
*** Configure Guix Channels
First, fetch the most recent channel file from the target machine. For most, this will be
done via the internet using my public mirror.
#+begin_src shell
curl -O https://git.rekahsoft.ca/rekahsoft/guix-machines/raw/branch/master/channels.scm
#+end_src
When on my network, I pull from my internal git (notice the different URL).
#+begin_src shell
curl -O https://git.home.rekahsoft.ca/rekahsoft-public/guix-machines/raw/branch/master/channels.scm
#+end_src
Once the channel file is available on the target, refresh the cached command paths with
~hash~ and update guix to use the new channels.
#+begin_src shell
hash guix
sudo -i guix pull -C $(realpath channels.scm)
#+end_src
*** TODO Disk Setup and Partitioning
TODO: disks need to be partitioned and appropriately mounted. This varies depending on the setup.
#+begin_src bash
# Create disk partition table and layout
parted /dev/nvme0n1 mklabel gpt
# Create partitions
parted /dev/nvme0n1 mkpart primary ESP 0% 512MiB
parted /dev/nvme0n1 mkpart 512MiB 100%
# Create EFI partition
parted /dev/nvme0n1p1 set 1 esp on
mkfs.fat -F32 /dev/nvme0n1p1
# Create LUKS container on remainder of disk
cryptsetup luksFormat --label crypt /dev/nvme0n1p2
# Unlock LUKS container after creation
cryptsetup luksOpen /dev/nvme0n1p2 crypt
#
# Create LVM2 container inside of LUKS container
# Create Physical Volume (pv)
pvcreate /dev/mapper/crypt
# Create Volume Group (vg)
vgcreate vg0 /dev/mapper/crypt
# Create Logical Volume/s (vg)
lvcreate -L <ROOT_VOL_SIZE>G vg0 -n root
lvcreate -l +100%FREE vg0 -n swap
#
# Create btrfs 'pool' (file-system) and subvolumes
# Create btrfs file-system
mkfs.btrfs --label root /dev/vg0/root
# Create btrfs subvolumes
mount /dev/vg0/root /mnt
btrfs subvolume create /mnt/@
umount /mnt
# Mount the root subvolume.
mount -o subvol=@,compress=zstd /dev/vg0/root /mnt
# Create nested subvolumes for /gnu/store, /home, and /var
mkdir -p /mnt/gnu
btrfs subvolume create /mnt/gnu/store
btrfs subvolume create /mnt/home
btrfs subvolume create /mnt/var
# Create and activate swap
mkswap --label swap /dev/vg0/swap
swapon /dev/vg0/swap
# Prepare /mnt for Guix installation
mkdir -p /mnt/boot/efi
mount /dev/nvme0n1p1 /mnt/boot/efi
#+end_src
*** Bootstrap System
**** Start ~cow-store~ Service
As described in guix documentation, start ~cow-store~ to allow later steps to write store
changes to ~/mnt/gnu/store~.
#+begin_src bash
herd start cow-store /mnt
#+end_src
**** Optional (but recommended): Use additional or alternative substitute servers
Optionally additional or alternative substitute servers can be setup for guix-daemon. This is
recommended to greatly speed up installation (so that nonguix and rekahsoft-guix (internal
network only) substitutes can be used).
First stop the running ~guix-daemon~.
#+begin_src bash
herd stop guix-daemon
#+end_src
Then start a new instance of ~guix-daemon~ as it is normally started by its Shepherd service,
but with additional or alternative substitute servers provided.
#+begin_src bash
guix-daemon \
--build-users-group guixbuild \
--max-silent-time 0 \
--timeout 0 \
--log-compression gzip \
--discover=no \
--substitute-urls https://substitutes.nonguix.org https://guix-ci.home.rekahsoft.ca https://ci.guix.gnu.org https://bordeaux.guix.gnu.org &
#+end_src
**** Create and Bootstrap System
Create a ~bootstrap.scm~ file like this:
#+begin_src scheme
(@ (rekahsoft guix-config <vms|manual> <target>) %system)
#+end_src
Use ~guix system init ...~ to instantiate the system.
#+begin_src bash
guix system init bootstrap.scm /mnt
#+end_src
** TODO Producing an image to be flashed directly
TODO: there are limitations on what images I can produce; namely, lvm and luks cannot be
setup easily (or at all?) it seems?
#+begin_src shell
guix time-machine -C channels.scm -- system image -e '(@ (rekahsoft guix-config <vms|manual> <target>) %image)'
#+end_src
* Push Deployment with ~guix deploy~
Push based mutable deployment is the default deployment methodology for the majority of
systems managed by this repository. This is particularity safe because Guix changes are done
as transactions, and thus can easily be rolled back.
To deploy a system use the following (substituting ~<hostname>~ with the appropriate deploy
file).
#+begin_src shell
guix time-machine -C channels.scm -- deploy deploy/<hostname>.scm
#+end_src
**Note:** Deploy files in [[./deploy]] are named after the hostname that would be used to ssh to
the machine.
* Pull Based Deployment
Pull based mutable deployment is the default deployment methodology for personal computers,
where using a push based method doesn't make sense. It also serves as a secondary deployment
mechanism for systems normally maintained using the push deployment model; for example, this
becomes necessary when facing ~guix deploy~ bugs.
First [[*Configure Guix Channels][Configure Guix Channels]] as described above. Once channels have been updated
successfully, use the following to reconfigure the system.
#+begin_src shell
sudo -i guix system reconfigure -e '(@ (rekahsoft guix-config <vms|manual> <target>) %system)'
#+end_src
Alternatively, the same effect can be achieved without first pulling the appropriate channels
by instead using ~guix time-machine~ as follows.
#+begin_src shell
sudo -i guix time-machine -C $(realpath channels.scm) -- system reconfigure -e '(@ (rekahsoft guix-config <vms|manual> <target>) %system)'
#+end_src
* Using Local Sources
Regardless of the deployment methodology used, sometimes it is useful to deploy changes that
have not yet been committed. This should be done sparingly, as it can be slightly confusing
if forgotten; that being said, Guix makes this a semi-reasonable thing to do, as how the
system changes is tracked very explicitly by guix generations local to the target.
To manually deploy using local sources, the local sources must exist on the working machine
(of course). The easiest way to do this is via git, from the working machine like so. Most
will pull from my public git mirror.
#+begin_src shell
git clone https://git.rekahsoft.ca/rekahsoft/guix-machines.git
#+end_src
On my network, internal git is used instead (notice the different URL).
#+begin_src shell
git clone https://git.home.rekahsoft.ca/rekahsoft-public/guix-machines.git
#+end_src
Once a copy of the sources are available on the working machine, all that remains is
following the normal deployment steps, but with a slight modification; use the
~-L|--load-path~ argument to specify the current working sources, effectively overriding what
is in the ~guix-machines~ channel.
** Building Operating System Configuration
Many times its useful to verify that a change to a system configuration will build correctly,
prior to deploying it. ~guix system build~ is meant for exactly this, and can be run as
follows.
#+begin_src shell
guix time-machine -C channels.scm -- system build -L .guix -e '(@ (rekahsoft guix-config <vms|manual> <target>) %system)'
#+end_src
** Running Operating System in VM for testing
#+begin_src shell
$(guix time-machine -C channels.scm -- system vm -e '(@ (rekahsoft guix-config <vms|manual> <target>) %system)') -m 2G -smp 2 -nic user,model=virtio-net-pci
#+end_src
** Generating the OS service extension graph
#+begin_src shell
guix time-machine -C channels.scm -- system extension-graph -e '(@ (rekahsoft guix-config <vms|manual> <target>) %system)' | guix shell xdot -- xdot -
#+end_src
** Generating the shepherd service graph
#+begin_src shell
guix time-machine -C channels.scm -- system shepherd-graph -e '(@ (rekahsoft guix-config <vms|manual> <target>) %system)' | guix shell xdot -- xdot -
#+end_src
** Push Based Deployments
#+begin_src shell
guix time-machine -C channels.scm -- deploy -L ./.guix deploy/<hostname>.scm
#+end_src
See the [[*Push Deployment with ~guix deploy~][Push Deployment with ~guix deploy~]] section for more details.
** Pull Based Deployments
#+begin_src shell
sudo -i guix time-machine -C $(realpath channels.scm) -- system reconfigure -L $(realpath ./.guix) -e '(@ (rekahsoft guix-config <vms|manual> <target>) %system)'
#+end_src
See the [[*Pull Based Deployment][Pull Based Deployment]] section for more details.
* Footnotes
[fn:1] https://guix.gnu.org/manual/en/html_node/Invoking-guix-deploy.html
[fn:2] https://guix.gnu.org/manual/en/html_node/Channel-Authentication.html
[fn:3] https://guix.gnu.org/manual/en/html_node/Package-Modules-in-a-Sub_002ddirectory.html
[fn:4] https://orgmode.org/
[fn:5] https://guix.gnu.org/manual/en/html_node/Channels.html
[fn:6] https://guix.gnu.org/manual/en/html_node/Replicating-Guix.html
[fn:7] Only available in my internal home-network

View File

@ -1,44 +0,0 @@
(list (channel
(name 'guix)
(url "https://git.savannah.gnu.org/git/guix.git")
(branch "master")
(commit
"703ae431f4ad28658e34675310b4fdf58685ccdd")
(introduction
(make-channel-introduction
"9edb3f66fd807b096b48283debdcddccfea34bad"
(openpgp-fingerprint
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA"))))
(channel
(name 'nonguix)
(url "https://gitlab.com/nonguix/nonguix")
(branch "master")
(commit
"7081518be7d2dbb58f3fbfeb1785254a6f0059c8")
(introduction
(make-channel-introduction
"897c1a470da759236cc11798f4e0a5f7d4d59fbc"
(openpgp-fingerprint
"2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5"))))
(channel
(name 'rekahsoft-guix)
(url "https://git.rekahsoft.ca/rekahsoft/rekahsoft-guix.git")
(branch "master")
(commit
"deef3bf38160928b803d498db45288d5150a244b")
(introduction
(make-channel-introduction
"d910ac4ca1e1a115934b10921bc23f50bd481043"
(openpgp-fingerprint
"F8D5 46F3 AF37 EF53 D1B6 48BE 7B4D EB93 212B 3022"))))
(channel
(name 'guix-machines)
(url "https://git.home.rekahsoft.ca/rekahsoft-public/guix-machines.git")
(branch "master")
;; (commit ;; Pin to <commit-sha> if/when required
;; "<commit-sha>")
(introduction
(make-channel-introduction
"acaa20d632da16937508a45ef2cc0083e09bae4c"
(openpgp-fingerprint
"F8D5 46F3 AF37 EF53 D1B6 48BE 7B4D EB93 212B 3022")))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms ci-runner0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "ci-runner0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHMwljf3lDt+Sl7G5eU9vhDrcNC7lB1GZ0YnkaLw4TuJ root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms ci0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "ci0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAQzhX0t1wGMDr9XEuieTBrwhv+qe44n8RZyTDmGkebN root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms cloud0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "cloud0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINwGi4YmUyLgpmFxJzGQF5Ju7CL8d2Wa2VtHMZGms0KO root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms dash0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "dash0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAv65AjAwV/oHE2krai3mfaXVL8HQEPrpRs+xMoSbRXT root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms git0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "git0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDDZpi0ZrsyZwL/wZBBHHo28NGGD9l4fECWnvsxeCM8K root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms grocy0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "grocy0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICSMBcmFdlDI/JKOBC/RRJh2VM0MY45o684OXaTQ3fGm root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms guix-ci0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "guix-ci0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILrv3Ygq47GYt5jYiNPUhvIDOOl4H17Z/abMvA1l/xkj root@(none)")
(system "x86_64-linux")
(port 22)
(user "auto")
(identity ".deploy-key")))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms loki-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "loki.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDBhpS71+xy0v0F5oBfr9wJ63D9AKObWJuK6xNYiT8Fs root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms my0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "my0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO5vvmg2XyYhEUOI3yxLxpFMrL2yFcALCqoGQH9cbzHh root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms postgres-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "postgres.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILyZiN3cN8c1Sq6FSBvW7un/0+seR7BOH48IUbpa/mXW root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms prom0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "prom0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOeRGcJWB3ilkKKOT+8e0TqyP4YRQ8jRB4spiOzdnl5N root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms searx0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "searx0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtVW/MHrl4etw6xpbwOm5qxjuU5+x78PKuN0+WEuzYl root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

View File

@ -1,14 +0,0 @@
(use-modules
(rekahsoft guix-config vms vault0-home-rekahsoft-ca))
(list
(machine
(operating-system %system)
(environment managed-host-environment-type)
(configuration (machine-ssh-configuration
(host-name "vault0.home.rekahsoft.ca")
(host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINwGi4YmUyLgpmFxJzGQF5Ju7CL8d2Wa2VtHMZGms0KO root@(none)")
(system "x86_64-linux")
(user "auto")
(identity ".deploy-key")
(port 22)))))

344
rekahsoft-212B3022.key Normal file
View File

@ -0,0 +1,344 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBE0JkwwBEADhh0exJx9tBJXEulXa7/JrfDK3hwZt42W3NDHHuJsyWdOeS9hz
AW/MQNOERHdwY/Q2H8sjtKsXyQ4BIe3O2SyjfzDHGYhYSFiihdXYhmmdka2MwNL6
glg3XEpnUKRGsTqHRQgIBAOEG9q3xJ+u8j10PcqM1eNxai88sLJ9vdwymuzpEm/d
tWhTReZB0wy5T9IHJEHhqAnvZ7sYLnkAJZQRkw7ondMrK4MnQrgVxdrZv68Vuiuz
IXwg27WAireuvw4JjpLRSwujzQnFuO2R6fW/lIQ5oomaaa649ijtrrMEZfVBO863
kv3eo7s6XM6xdDmYbbU7oXAFm0dhT1kaJTH1BBXzM1DRljwIC/qj5DqIRVKUANjN
bUb0cfg/FpvenBXQ0umSCW91TaQn4EZXvqu+2exMr7PmA9/RTI6dBNJPwTbeGqQe
TZ6IN4meFlJWNLhh04vtZzfH2DjqEOLIb5S6mVK3u/eTmv1rCRnFI14MY4PUOq4u
tKlDjw5pVxq0AY3dZXQsnfQRGkelHYHhoS7NVMCUkiOmYHVQC0i5TwsWEdTcbL7C
PvIx92qXz2XRwSwJPsEEDIz0QOIBiBiFhsHhOEZ7VpOzj2RwTV/mdGS3DjW2+vuY
Rjv9/SFB17QfUEKnSGwpDZ4QOVx54KtyHvI1L4UjLGuhgKzpoqeJOSU6yQARAQAB
tCRDb2xsaW4gRG9lcmluZyA8Y29sbGluQHJla2Foc29mdC5jYT6JAk4EEwEIADgW
IQT3vdxtu+axayxxGgJfq5k44Fv+yAUCW7ZFpgIbAwULCQgHAgYVCgkICwIEFgID
AQIeAQIXgAAKCRBfq5k44Fv+yBG4D/9vlOe5yNEeUhn+Q40nRZDtUxT6by1PHVrK
n/dwOwYxqfJxD7Wn5ba+JJ5Cqd2b09o9G9IymwROGsqftM08I+GHyzM4wA1o57JZ
Brmx/phd7HKSrZhs4Gz8bEQ+zqQyo9QmVqGu1IXwxuEGH9vdj+pbt+9+mARsL8HI
ObUaa8X18uy+DSe64ZZ6WkUa9WlkIkbcvAUi36pw6csCNJOXJpkHv109y7iRqq60
3YD3yqI8DObMjmqG4nFi3J90swqRXiygvnKV0lhE8xyRY4GhPKUwLB2q89RCLSJ6
k1JKAGJW5HV+ru+SQzNViwhbWc4N7klmi3HFaISPtfXCTlNAianHq8RjQNYR+53q
bSZAnCsq5e+ae/sgAWKzQM/8UjInOZgmstrqBzzY5ikXZZwLe6IjshKYa/8HmIxG
Wium/ZyohAIMczpWdxUYDL6fUEKVf6fZRr8te1Rlp4xBJ6xC1n3WUDxUtAzI8AqV
/vrqfOra53kHePIkMAlSf+6drO1TwzLCUNsjAVasDsOyCC+tEqEHD9C5+rXDtQVJ
XuyHIQ7b5Pzjp3ZverguIFLTF99dbiv/2sLbjZvOA5aQIrY1VgQjRINNmIUpEsXx
s989ASs1wnK9L6kQV9sWpVtmnXnQzOmrfOtScvuRmXZ5ylU6BKfZ82LYLE3zOT7N
TVyWDMoMBLQsQ29sbGluIEouIERvZXJpbmcgPGNvbGxpbi5kb2VyaW5nQGdtYWls
LmNvbT6JAjcEEwEKACEFCwkIBwMGFQoJCwgDBBYCAwECGQAFglR4YFwCngECmwMA
CgkQX6uZOOBb/shFNxAAqInmaEKDBZn92OXaxWCK0I5QmODmQ+a12teFMzL93CuU
9vO5wNl6bp1D/Im9EBIgH65tykcrwivIShBclvA5f9YT0yuUgtHV1sJpObUXGxFO
h41lJH7TalF0mcMK1udz9yVDScBTj9JWDb250mPUs6d1JS/R6fq+l0iRNY1BqEC5
Ju0G7j8e2aDL7wplu9m6T7rm2JZBREKXd78nM21Dlixbu2whTRwVI6jjLLjmBMJN
ArbvFjCpw5wPV4o5U9RrMNy6tjRgu6tfS9UVwvlLL2al5GWVqyVpPeB3C3hG/IpI
6Rtiuf81Icdw9Onri5gGfakhjXPoyg09s14ILHr5XKFau3mBedsv+vjAezdQHNYm
Rxo8tBIs3QYnLEiVfOeBRMD0tFvPmPkiwofHqR82YWp0T2je/8tRFsCneZqMpenu
Ft85BvxiRW+RMUJZBt8RWUaXW/6PpNjpmMKs1eMQVrrAuJ3ma2nEuITxB8BZUH0m
DUNijYxUH2m6LvvanjrWb6gPLUsG5w9chk6AswsJ8jKfed+hP1wlp0tBHz4vWiex
/rrCN7E2uigVo3lbagCAVQnFwbh8sPTZmZ/34x2vKG2Zpq4V3XVSVrlDsXtCEL6f
IvIGeTCZu++gC5IiBkvE6CrX/m4+76d2SuepaCaU5xhpODetUScj1xsC1kW+lJC0
L0NvbGxpbiBKLiBEb2VyaW5nIDxjb2xsaW4uZG9lcmluZ0ByZWthaHNvZnQuY2E+
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
0KHBUYnw2ko1HeMTqgwSWqHEK9Wd++a2nsfT6A==
=clJ6
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,362 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
L0gP
=LKBO
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -1,20 +0,0 @@
#!/usr/bin/env bash
docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-e DRONE_RPC_PROTO="https" \
-e DRONE_RPC_HOST="ci.home.rekahsoft.ca" \
-e DRONE_RPC_SECRET="8cb1a6fbc4febc68a99c4f1cc3f11f2a" \
-e DRONE_RUNNER_CAPACITY=4 \
-e DRONE_RUNNER_NAME="ci-runner1.home.rekahsoft.ca" \
-e DRONE_RUNNER_LABELS=guix:on \
-e DRONE_RUNNER_VOLUMES=/var/guix/daemon-socket/socket:/var/guix/daemon-socket/socket,/gnu/store:/gnu/store,/home/collin/guix-ci-cache:/.cache/guix \
-e DRONE_DEBUG=true \
-p 3001:3000 \
--restart unless-stopped \
--name runner-guix \
--log-driver=loki \
--log-opt loki-url="http://loki.home.rekahsoft.ca:3100/loki/api/v1/push" \
--log-opt loki-retries=5 \
--log-opt loki-batch-size=400 \
docker.nexus.home.rekahsoft.ca/drone/drone-runner-docker:1.6.3

View File

@ -1,17 +0,0 @@
#!/usr/bin/env bash
docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-e DRONE_RPC_PROTO="https" \
-e DRONE_RPC_HOST="ci.home.rekahsoft.ca" \
-e DRONE_RPC_SECRET="8cb1a6fbc4febc68a99c4f1cc3f11f2a" \
-e DRONE_RUNNER_CAPACITY=4 \
-e DRONE_RUNNER_NAME="ci-runner0.home.rekahsoft.ca" \
-p 3000:3000 \
--restart unless-stopped \
--name runner \
--log-driver=loki \
--log-opt loki-url="http://loki.home.rekahsoft.ca:3100/loki/api/v1/push" \
--log-opt loki-retries=5 \
--log-opt loki-batch-size=400 \
docker.nexus.home.rekahsoft.ca/drone/drone-runner-docker:1.6.3

View File

@ -1,94 +0,0 @@
# Example configuration file, it's safe to copy this as the default config file without any modification.
# You don't have to copy this file to your instance,
# just run `./act_runner generate-config > config.yaml` to generate a config file.
log:
# The level of logging, can be trace, debug, info, warn, error, fatal
level: info
runner:
# Where to store the registration result.
file: .runner
# Execute how many tasks concurrently at the same time.
capacity: 1
# Extra environment variables to run jobs.
envs: {}
# Extra environment variables to run jobs from a file.
# It will be ignored if it's empty or the file doesn't exist.
env_file: .job-env
# The timeout for a job to be finished.
# Please note that the Gitea instance also has a timeout (3h by default) for the job.
# So the job could be stopped by the Gitea instance if it's timeout is shorter than this.
timeout: 3h
# Whether skip verifying the TLS certificate of the Gitea instance.
insecure: false
# The timeout for fetching the job from the Gitea instance.
fetch_timeout: 5s
# The interval for fetching the job from the Gitea instance.
fetch_interval: 2s
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
# Like: ["macos-arm64:host", "ubuntu-latest:docker://node:16-bullseye", "ubuntu-22.04:docker://node:16-bullseye"]
# If it's empty when registering, it will ask for inputting labels.
# If it's empty when execute `deamon`, will use labels in `.runner` file.
labels:
- guix:docker://guix-builder:latest
# - guix:docker://guix:latest
# NOTE: it appears that using a registry name is not supported, and /etc/docker/daemon.conf will need to be adjusted instead
# - guix:docker://docker.nexus.home.rekahsoft.ca/guix:latest
cache:
# Enable cache server to use actions/cache.
enabled: true
# The directory to store the cache data.
# If it's empty, the cache data will be stored in $HOME/.cache/actcache.
dir: ""
# The host of the cache server.
# It's not for the address to listen, but the address to connect from job containers.
# So 0.0.0.0 is a bad choice, leave it empty to detect automatically.
host: ""
# The port of the cache server.
# 0 means to use a random available port.
port: 0
# The external cache server URL. Valid only when enable is true.
# If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself.
# The URL should generally end with "/".
external_server: ""
container:
# Specifies the network to which the container will connect.
# Could be host, bridge or the name of a custom network.
# If it's empty, act_runner will create a network automatically.
network: ""
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
privileged: false
# And other options to be used when the container is started (eg, --add-host=my.gitea.url:host-gateway).
options: "-v /var/guix/daemon-socket/socket:/var/guix/daemon-socket/socket -v /gnu/store:/gnu/store:ro -v /home/collin/guix-ci-cache:/root/.cache/guix"
# The parent directory of a job's working directory.
# If it's empty, /workspace will be used.
workdir_parent:
# Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob
# You can specify multiple volumes. If the sequence is empty, no volumes can be mounted.
# For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to:
# valid_volumes:
# - data
# - /src/*.json
# If you want to allow any volume, please use the following configuration:
# valid_volumes:
# - '**'
valid_volumes:
- /var/guix/daemon-socket/socket
- /gnu/store
- /home/collin/guix-ci-cache
# overrides the docker client host with the specified one.
# If it's empty, act_runner will find an available docker host automatically.
# If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers.
# If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work.
docker_host: ""
# Pull docker image(s) even if already present
force_pull: false
host:
# The parent directory of a job's working directory.
# If it's empty, $HOME/.cache/act/ will be used.
workdir_parent:

View File

@ -1,14 +0,0 @@
version: "3.8"
services:
runner:
image: docker.nexus.home.rekahsoft.ca/gitea/act_runner:0.2.6
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: "${INSTANCE_URL}"
GITEA_RUNNER_REGISTRATION_TOKEN: "${REGISTRATION_TOKEN}"
GITEA_RUNNER_NAME: "${RUNNER_NAME}"
volumes:
- ./config.yaml:/config.yaml
- ./data:/data
- /var/run/docker.sock:/var/run/docker.sock

View File

@ -1,14 +0,0 @@
#!/usr/bin/env bash
# Using this temporarily until docker-compose is available on the host (need to install it)
docker run -d \
-v $PWD/config.yaml:/config.yaml \
-v $PWD/data:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CONFIG_FILE=/config.yaml \
-e GITEA_INSTANCE_URL=${INSTANCE_URL} \
-e GITEA_RUNNER_REGISTRATION_TOKEN=${REGISTRATION_TOKEN} \
-e GITEA_RUNNER_NAME=${RUNNER_NAME} \
--name gitea-runner-guix \
docker.nexus.home.rekahsoft.ca/gitea/act_runner:0.2.6

View File

@ -1,21 +0,0 @@
#!/usr/bin/env bash
docker run \
--volume=/var/lib/drone:/data \
--env=DRONE_GITEA_SERVER="https://git.home.rekahsoft.ca" \
--env=DRONE_GITEA_CLIENT_ID="25793ca8-0057-494b-b6a5-e7534104f546" \
--env=DRONE_GITEA_CLIENT_SECRET="Br9vQ-WG4nkC4cVwnCEFsfQg_WD6ax5Ebi5hNwiSd9M=" \
--env=DRONE_RPC_SECRET="8cb1a6fbc4febc68a99c4f1cc3f11f2a" \
--env=DRONE_SERVER_HOST="ci.home.rekahsoft.ca" \
--env=DRONE_SERVER_PROTO=https \
--env=DRONE_USER_CREATE=username:rekahsoft,admin:true \
--env=DRONE_JSONNET_ENABLED=true \
--publish=80:80 \
--restart=always \
--detach=true \
--name=drone \
--log-driver=loki \
--log-opt loki-url="http://loki.home.rekahsoft.ca:3100/loki/api/v1/push" \
--log-opt loki-retries=5 \
--log-opt loki-batch-size=400 \
docker.nexus.home.rekahsoft.ca/drone/drone:2

View File

@ -1,16 +0,0 @@
#/usr/bin/env bash
docker run -d --name nextcloud \
-p 80:80 \
--restart unless-stopped \
-v nextcloud:/var/www/html \
-v apps:/var/www/html/custom_apps \
-v config:/var/www/html/config \
-v /mnt/cephfs:/var/www/html/data \
-e APACHE_DISABLE_REWRITE_IP=1 \
-e TRUSTED_PROXIES="172.16.0.1" \
-e NEXTCLOUD_TRUSTED_DOMAINS="cloud.home.rekahsoft.ca,cloud0.home.rekahsoft.ca" \
docker.nexus.home.rekahsoft.ca/nextcloud:stable
# Last working: 22.2.3-apache
# Broken upgrade: 22.2.5.1

View File

@ -1,10 +0,0 @@
#!/usr/bin/env bash
docker run -d \
-p 80:3000 \
--restart unless-stopped \
--name grafana \
-v grafana:/var/lib/grafana \
-e "GF_INSTALL_PLUGINS=vonage-status-panel,grafana-piechart-panel" \
-e "GF_SECURITY_ALLOW_EMBEDDING=true" \
docker.nexus.home.rekahsoft.ca/grafana/grafana-oss:9.3.6

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
docker run -d \
--restart unless-stopped \
--name gitea \
-v gitea:/data \
-v /etc/timezone:/etc/timezone:ro \
-v /etc/localtime:/etc/localtime:ro \
-p 80:3000 \
-p 2222:22 \
--log-driver=loki \
--log-opt loki-url="http://loki.home.rekahsoft.ca:3100/loki/api/v1/push" \
--log-opt loki-retries=5 \
--log-opt loki-batch-size=400 \
docker.nexus.home.rekahsoft.ca/gitea/gitea:1.18.5

View File

@ -1,40 +0,0 @@
version: "3.9"
services:
loki:
image: docker.nexus.home.rekahsoft.ca/grafana/loki:2.7.4
command: "-config.file=/mnt/config/loki-config.yaml"
networks:
- net-bridge
ports:
- "3100:3100"
volumes:
- /var/lib/loki/config:/mnt/config
rsyslog:
image: docker.nexus.home.rekahsoft.ca/rsyslog/syslog_appliance_alpine:8.36.0-3.7
networks:
- net-bridge
ports:
- "514:514"
- "514:514/udp"
environment:
RSYSLOG_CONF: /config/rsyslog.conf
volumes:
- /var/lib/rsyslog/config:/config
- /var/lib/rsyslog/work:/work
- /var/lib/rsyslog/logs:/logs
promtail:
image: docker.nexus.home.rekahsoft.ca/grafana/promtail:2.7.4
command: "-config.file=/mnt/config/promtail-config.yaml"
networks:
- net-bridge
ports:
- "1514:1514/udp"
- "9080:9080"
- "1514:1514"
volumes:
- /var/lib/loki/config:/mnt/config
- /var/lib/loki/data:/loki
networks:
net-bridge:

View File

@ -1,47 +0,0 @@
auth_enabled: false
server:
http_listen_port: 3100
ingester:
lifecycler:
address: 127.0.0.1
ring:
kvstore:
store: inmemory
replication_factor: 1
final_sleep: 0s
chunk_idle_period: 5m
chunk_retain_period: 30s
max_transfer_retries: 0
wal:
dir: /loki/wal
schema_config:
configs:
- from: 2018-04-15
store: boltdb
object_store: filesystem
schema: v11
index:
prefix: index_
period: 168h
storage_config:
boltdb:
directory: /loki/index
filesystem:
directory: /loki/chunks
limits_config:
enforce_metric_name: false
reject_old_samples: true
reject_old_samples_max_age: 168h
chunk_store_config:
max_look_back_period: 0s
table_manager:
retention_deletes_enabled: false
retention_period: 0s

View File

@ -1,22 +0,0 @@
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: syslog
syslog:
listen_address: 0.0.0.0:1514
listen_protocol: tcp
label_structured_data: yes
max_message_length: 1000
labels:
job: "syslog"
relabel_configs:
- source_labels: ['__syslog_message_hostname']
target_label: 'host'

View File

@ -1,41 +0,0 @@
global(processInternalMessages="on")
#module(load="imtcp" StreamDriver.AuthMode="anon" StreamDriver.Mode="1")
module(load="impstats") # config.enabled=`echo $ENABLE_STATISTICS`)
module(load="imrelp")
module(load="imptcp")
module(load="imudp" TimeRequery="500")
module(load="omstdout")
module(load="omelasticsearch")
module(load="mmjsonparse")
module(load="mmutf8fix")
input(type="imptcp" port="514")
input(type="imudp" port="514")
input(type="imrelp" port="1601")
template(name="log_to_files_dynafile" type="string" string=`echo $LOGFILES_STORE`)
ruleset(name="log_to_files") {
/logs/debug;RSYSLOG_DebugFormat
action(type="omfile" dynafile="log_to_files_dynafile" name="log_to_logfiles")
}
ruleset(name="remote") {
# TODO: the target is a docker bridge ip (on the default bridge, so an alias cannot be used); this should be fixed
action(type="omfwd" Target="promtail" Port="1514" Protocol="tcp" Template="RSYSLOG_SyslogProtocol23Format" TCP_Framing="octet-counted")
}
#################### default ruleset begins ####################
# we emit our own messages to docker console:
syslog.* :omstdout:
include(file="/config/droprules.conf" mode="optional") # this permits the user to easily drop unwanted messages
action(name="main_utf8fix" type="mmutf8fix" replacementChar="?")
include(text=`echo $CNF_CALL_LOG_TO_LOGFILES`)
call remote

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
docker run \
-d \
--name=organizr \
--restart unless-stopped \
-v organizr:/config \
-e PGID=1000 -e PUID=1000 \
-e fpm=true \
-e branch=v2-master \
-p 80:80 \
docker.nexus.home.rekahsoft.ca/organizr/organizr

View File

@ -1,9 +0,0 @@
#!/usr/bin/env bash
docker run -d \
--name prometheus \
--restart unless-stopped \
-p 9090:9090 \
-v /var/lib/prometheus/etc:/etc/prometheus \
-v /var/lib/prometheus/data:/prometheus \
docker.nexus.home.rekahsoft.ca/prom/prometheus:v2.42.0

View File

@ -1,258 +0,0 @@
# my global config
global:
scrape_interval: 15s
evaluation_interval: 30s
# scrape_timeout is set to the global default (10s).
#
# Applications
scrape_configs:
- job_name: grafana
scheme: http
dns_sd_configs:
- type: 'A'
port: 80
names:
- dash0.home.rekahsoft.ca
- job_name: gitea
scheme: http
dns_sd_configs:
- type: 'A'
port: 80
names:
- git0.home.rekahsoft.ca
#
# VMs
- job_name: vm-searx
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- searx0.home.rekahsoft.ca
- job_name: vm-git0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- git0.home.rekahsoft.ca
- job_name: vm-ci0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- ci0.home.rekahsoft.ca
- job_name: vm-ci-runner0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- ci-runner0.home.rekahsoft.ca
- job_name: vm-my0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- my0.home.rekahsoft.ca
- job_name: vm-torrent0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- torrent0.home.rekahsoft.ca
- job_name: vm-plex0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- plex0.home.rekahsoft.ca
- job_name: vm-loki
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- loki.home.rekahsoft.ca
- job_name: vm-postgres
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- postgres.home.rekahsoft.ca
- job_name: vm-guix-ci0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- guix-ci0.home.rekahsoft.ca
- job_name: vm-vault0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- vault0.home.rekahsoft.ca
- job_name: vm-cloud0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- cloud0.home.rekahsoft.ca
- job_name: vm-grocy0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- grocy0.home.rekahsoft.ca
- job_name: vm-pbs
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- pbs.home.rekahsoft.ca
- job_name: vm-nexus0
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- nexus0.home.rekahsoft.ca
#
# Physical hardware
- job_name: proxmox-nodes
scheme: http
dns_sd_configs:
- type: 'A'
port: 9100
names:
- pve-0.home.rekahsoft.ca
- type: 'A'
port: 9100
names:
- pve-1.home.rekahsoft.ca
- type: 'A'
port: 9100
names:
- pve-2.home.rekahsoft.ca
- type: 'A'
port: 9100
names:
- pve-3.home.rekahsoft.ca
- type: 'A'
port: 9100
names:
- pve-4.home.rekahsoft.ca
#
# Applications running directly on physical hardware
- job_name: ceph-metrics
scheme: http
dns_sd_configs:
- type: 'A'
port: 9283
names:
- pve-0.home.rekahsoft.ca
- type: 'A'
port: 9283
names:
- pve-1.home.rekahsoft.ca
- type: 'A'
port: 9283
names:
- pve-2.home.rekahsoft.ca
- type: 'A'
port: 9283
names:
- pve-3.home.rekahsoft.ca
- type: 'A'
port: 9283
names:
- pve-4.home.rekahsoft.ca
# - job_name: some-service
# metrics_path: /metrics
# static_configs:
# - targets:
# - localhost:9090
# - job_name: prometheus
# honor_labels: true
# # scrape_interval is defined by the configured global (15s).
# # scrape_timeout is defined by the global default (10s).
# # metrics_path defaults to '/metrics'
# # scheme defaults to 'http'.
# file_sd_configs:
# - files:
# - foo/*.slow.json
# - foo/*.slow.yml
# - single/file.yml
# refresh_interval: 10m
# - files:
# - bar/*.yaml
# static_configs:
# - targets: ['localhost:9090', 'localhost:9191']
# labels:
# my: label
# your: label
# relabel_configs:
# - source_labels: [job, __meta_dns_name]
# regex: (.*)some-[regex]
# target_label: job
# replacement: foo-${1}
# # action defaults to 'replace'
# - source_labels: [abc]
# target_label: cde
# - replacement: static
# target_label: abc
# - regex:
# replacement: static
# target_label: abc
# bearer_token_file: valid_token_file
# - job_name: badfederation
# honor_timestamps: false
# metrics_path: /federate
# static_configs:
# - targets:
# - localhost:9090

View File

@ -1,9 +0,0 @@
#!/usr/bin/env bash
docker run -d \
--name searx \
--restart unless-stopped \
-v /var/lib/searx:/etc/searx \
-p 8080:8080 \
-e BASE_URL=https://searx.home.rekahsoft.ca \
docker.nexus.home.rekahsoft.ca/searx/searx

View File

@ -1,11 +0,0 @@
#!/usr/bin/env bash
docker run -d \
--restart unless-stopped \
--name bitwarden \
-v bitwarden:/data \
-e DOMAIN=https://vault.home.rekahsoft.ca \
-e ADMIN_TOKEN=82HHZZImGbiZ2WaOybVvIM9ug+MgGO/VhMG5t16DbwpsRrTe3jUlOD76VPUXctB5 \
-e SIGNUPS_ALLOWED=false \
-p 80:80 \
docker.nexus.home.rekahsoft.ca/vaultwarden/server:1.27.0

View File

@ -1,30 +0,0 @@
# File: .tmux.conf
# Author: Collin J. Doering <rekahsoft@gmail.com>
# Date: Jan 18, 2014
# Set prefix key to C-t instead of default C-b
unbind C-b
set -g prefix C-t
# Mimic 256 colors
set -g default-terminal "screen-256color"
# Toggle last window like screen
bind-key C-t last-window
# Rebind clock-mode to "prefix T"
unbind t
bind-key T clock-mode
# Send prefix to underlying application using "prefix t"
bind-key t send-prefix
# Setup pane movement
bind-key j command-prompt -p "join pane from:" "join-pane -s '%%'"
bind-key s command-prompt -p "send pane to:" "join-pane -t '%%'"
# session initialization
#new -s default -n zsh zsh
#neww -n weechat weechat-curses
#neww -n emacs emacsclient
#selectw -t 1

View File

@ -1,73 +0,0 @@
# Display time
SPACESHIP_TIME_SHOW=true
# Don't display username
SPACESHIP_USER_SHOW=false
# Do not truncate path in repos
SPACESHIP_DIR_TRUNC_REPO=false
SPACESHIP_PROMPT_ADD_NEWLINE=false
SPACESHIP_PROMPT_SEPARATE_LINE=true
SPACESHIP_KUBECONTEXT_SYMBOL="☸️ " # Two spaces are used instead of one in prompt; this forces use of only one
SPACESHIP_PROMPT_ASYNC=false
SPACESHIP_PROMPT_ORDER=(
time # Time stamps section
user # Username section
dir # Current directory section
host # Hostname section
git # Git section (git_branch + git_status)
hg # Mercurial section (hg_branch + hg_status)
package # Package version
node # Node.js section
bun # Bun section
deno # Deno section
ruby # Ruby section
python # Python section
elm # Elm section
elixir # Elixir section
xcode # Xcode section
swift # Swift section
golang # Go section
perl # Perl section
php # PHP section
rust # Rust section
haskell # Haskell Stack section
scala # Scala section
kotlin # Kotlin section
java # Java section
lua # Lua section
dart # Dart section
julia # Julia section
crystal # Crystal section
docker # Docker section
docker_compose # Docker section
aws # Amazon Web Services section
gcloud # Google Cloud Platform section
azure # Azure section
venv # virtualenv section
conda # conda virtualenv section
dotnet # .NET section
ocaml # OCaml section
vlang # V section
zig # Zig section
purescript # PureScript section
erlang # Erlang section
kubectl # Kubectl context section
ansible # Ansible section
terraform # Terraform workspace section
pulumi # Pulumi stack section
ibmcloud # IBM Cloud section
nix_shell # Nix shell
gnu_screen # GNU Screen section
exec_time # Execution time
async # Async jobs indicator
line_sep # Line break
battery # Battery level and status
jobs # Background jobs indicator
exit_code # Exit code section
sudo # Sudo indicator
char # Prompt character
)

View File

@ -1,5 +0,0 @@
# Setup guix profile locales
export GUIX_LOCPATH=${HOME}/.guix-home/profile/lib/locale
# Add local binaries to PATH
export PATH="${PATH}:$HOME/.bin"

View File

@ -1,9 +0,0 @@
# All commands in this file MUST not produce output
# Default editor
export EDITOR="emacsclient -t -a emacs"
export VISUAL="emacsclient -a emacs"
# Set aws-vault default backend
export AWS_VAULT_BACKEND=pass
export AWS_VAULT_PASS_PREFIX=aws-vault

View File

@ -1,216 +0,0 @@
# File: ~/.zshrc
# Description: zsh configuration file
source ~/.guix-home/profile/bin/z.sh
precmd () {
z --add "$(pwd -P)"
}
# Use zsh-autosuggestions (requires pacman package)
source ~/.guix-home/profile/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
# TODO: temporary
fpath=( ~/.guix-home/profile/share/zsh/site-functions "${fpath[@]}" )
# The following lines were added by compinstall
zstyle ':completion:*' completer _list _expand _complete _ignored _match _correct _approximate _prefix
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
zstyle ':completion:*' matcher-list '' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|[._-/,+]=** r:|=**' 'l:|=* r:|=*'
zstyle ':completion:*' max-errors 5
zstyle ':completion:*' preserve-prefix '//[^/]##/'
zstyle :compinstall filename '/home/collin/.zshrc'
autoload -Uz compinit
compinit
autoload -U promptinit; promptinit
prompt spaceship
# End of lines added by compinstall
# Lines for zsh setup
HISTFILE="$HOME/.zsh_history"
HISTSIZE=10000000
SAVEHIST=10000000
setopt AUTO_CD # Change directories without cd
setopt BANG_HIST # Treat the '!' character specially during expansion.
setopt EXTENDED_HISTORY # Write the history file in the ":start:elapsed;command" format.
setopt INC_APPEND_HISTORY # Write to the history file immediately, not when the shell exits.
setopt SHARE_HISTORY # Share history between all sessions.
setopt HIST_EXPIRE_DUPS_FIRST # Expire duplicate entries first when trimming history.
setopt HIST_IGNORE_DUPS # Don't record an entry that was just recorded again.
setopt HIST_IGNORE_ALL_DUPS # Delete old recorded entry if new entry is a duplicate.
setopt HIST_FIND_NO_DUPS # Do not display a line previously found.
setopt HIST_IGNORE_SPACE # Don't record an entry starting with a space.
setopt HIST_SAVE_NO_DUPS # Don't write duplicate entries in the history file.
setopt HIST_REDUCE_BLANKS # Remove superfluous blanks before recording entry.
setopt HIST_VERIFY # Don't execute immediately upon history expansion.
setopt HIST_BEEP # Beep when accessing nonexistent history.
setopt COMPLETE_ALIASES # Complete command line switches for aliases
# End of zsh history setup
# Use emacs keybindings
bindkey -e
# Lines to add fzf fuzzy completion widgets supplied by fzf package
source ~/.guix-home/profile/share/fzf/key-bindings.zsh
source ~/.guix-home/profile/share/fzf/completion.zsh
# Rebind C-t for fzf-file-widget to ESC-t
bindkey -r '^T'
bindkey '\et' fzf-file-widget
# Rebind C-r for ffz-history-widget to ESC-r
bindkey -r '^R'
bindkey '\er' fzf-history-widget
export FZF_DEFAULT_OPTS='--no-height --no-reverse'
export FZF_ALT_C_COMMAND="find -L . -mindepth 1 \\( -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune -o -type d -print 2> /dev/null | cut -b3-"
#export FZF_CTRL_T_COMMAND="find -L . -mindepth 1 \\( -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune -o -type f -print -o -type d -print -o -type l -print 2> /dev/null | cut -b3-"
export FZF_CTRL_T_COMMAND="ag --hidden --ignore .git -g '' 2> /dev/null"
export FZF_CTRL_T_OPTS="--preview '(highlight -O ansi -l {} 2> /dev/null || cat {} || tree -C {}) 2> /dev/null'"
export FZF_CTRL_R_OPTS="--preview 'echo {}' --preview-window down:3:hidden --bind '?:toggle-preview'"
# End of zsh fzf widget setup
# Check for a tramp session and set a compatible PS1
# See: https://www.emacswiki.org/emacs/TrampMode
[[ $TERM == "tramp" ]] && unsetopt zle && PS1='$ ' && return
# Check for an interactive session
[ -z "$PS1" ] && return
# Preferably, setup of man/info would be automatically be handled by 'guix shell' itself,
# however this is not the case, as the profile hook for man/info pages will not be triggered
# unless man or info respectively is also explicitly included in the profile.
if [ ! -z "$GUIX_ENVIRONMENT" ]; then
# When using guix shell (formally environment) command, automatically add the temporary
# environments man page directory to MANPATH, if it exists.
if [ -d "$GUIX_ENVIRONMENT/share/man" ]; then
export MANPATH="$GUIX_ENVIRONMENT/share/man:$MANPATH"
fi
# Similarly to man, automatically add the temporary environments info page directory to
# INFOPATH, if it exists.
if [ -d "$GUIX_ENVIRONMENT/share/info" ]; then
export INFOPATH="$GUIX_ENVIRONMENT/share/info:$INFOPATH"
fi
fi
# Alias' to make command output prettier (use color with some commands by default)
alias ls='ls --color=auto'
alias ll='ls -l'
alias la='ls -a'
alias lla='ls -al'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
alias f='find'
compdef f='find'
alias b='bat'
# #compdef b='bat' # No completions for bat installed/available
alias x='eza'
alias xs='eza'
alias xl='eza -l'
alias xla='eza -la'
alias xx='x -alT --git'
compdef x='eza'
compdef xs='eza'
compdef xl='eza'
compdef xla='eza'
compdef xx='eza'
alias e='emacsclient -t'
alias kssh='kitty +kitten ssh'
alias qemu="qemu-system-$(uname -m) -enable-kvm"
alias lock='cmatrix; clear; vlock'
alias vv="remote-viewer --connect qemu:///session"
alias xc="xclip -selection clipboard"
# alias mplayer-ascii='mplayer -vo aa:driver=curses -monitorpixelaspect 0.5 -really-quiet'
alias s='sudo'
alias si='sudo -i'
compdef s='sudo'
compdef si='sudo'
# Turn off noscroll
stty stop undef
# Setup direnv hook
eval "$(direnv hook zsh)"
# Use zsh-source-highlight
source ~/.guix-home/profile/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
# Access pem ssh keys from password store
pass-ssh() {
psw="$1"
shift
key_file="$(mktemp)"
pass "$psw" > "$key_file"
ssh -i "$key_file" $@
rm "$key_file"
}
# Required for emacs vterm
# See: https://github.com/akermu/emacs-libvterm
vterm_printf(){
if [ -n "$TMUX" ]; then
# Tell tmux to pass the escape sequences through
# (Source: http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1324)
printf "\ePtmux;\e\e]%s\007\e\\" "$1"
elif [ "${TERM%%-*}" = "screen" ]; then
# GNU screen (screen, screen-256color, screen-256color-bce)
printf "\eP\e]%s\007\e\\" "$1"
else
printf "\e]%s\e\\" "$1"
fi
}
# Ease message passing to vterm
vterm_cmd() {
local vterm_elisp
vterm_elisp=""
while [ $# -gt 0 ]; do
vterm_elisp="$vterm_elisp""$(printf '"%s" ' "$(printf "%s" "$1" | sed -e 's|\\|\\\\|g' -e 's|"|\\"|g')")"
shift
done
vterm_printf "51;E$vterm_elisp"
}
if [[ "$INSIDE_EMACS" = 'vterm' ]]; then
# Override man to run emacs man
man() {
vterm_cmd man "$@"
}
# Override info to run emacs info
info() {
vterm_cmd info "$@"
}
find-file() {
vterm_cmd find-file "$@"
}
message() {
vterm_cmd message "$@"
}
vterm-clear-scrollback() {
vterm_cmd vterm-clear-scrollback "$@"
}
# For emacs vterm directory and prompt tracking
# https://github.com/akermu/emacs-libvterm#directory-tracking-and-prompt-tracking
vterm_prompt_end() {
vterm_printf "51;A$(whoami)@$(hostname):$(pwd)";
}
setopt PROMPT_SUBST
PROMPT=$PROMPT'%{$(vterm_prompt_end)%}'
fi