(use-modules (gnu) (curth0) (srfi srfi-26) (gnu packages ssh) (gnu services certbot) (gnu services mcron) (gnu services mail) (gnu services networking) (gnu services ssh) (gnu services web)) (define ssh.conf #"""- ClientAliveInterval 30 ClientAliveCountMax 20 MaxSessions 20 Host suyin HostName ch-s010.rsync.net User 16686 """#) (define profile-extra (plain-file "profile-extra" #"""- export BORG_REMOTE_PATH='borg1' export BORG_PASSPHRASE_FD='/opt/secrets/borg-passphrase.txt' """#)) (define bashrc-extra (plain-file "bashrc-extra" #"""- alias l='ls -lahF --color' alias info='info --init-file /etc/infokey' export EDITOR=vi """#)) (define ps1.sh (plain-file "ps1.sh" #"""- end="\033[0m" gray() { printf "\033[0;90m$1$end" } yellow() { printf "\033[1;33m$1$end" } red() { printf "\033[1;31m$1$end" } redl() { printf "\033[0;31m$1$end" } error_marker() { STATUS=$? if [ "$STATUS" != 0 ]; then red " (!! $STATUS !!) " fi } export PS1='`error_marker`'$(gray '\T')' '$(yellow '\w/')'\n'$(redl '\\u@\h')'\$ ' """#)) (define infokey (plain-file "infokey" #"""- ^e down-line ^y up-line """#)) (define with-email.sh (plain-file "with-email.sh" #"""- #!/bin/sh set -u while getopts 's:' flag; do case "$flag" in s) SUBJECT="$OPTARG" ;; *) exit 2 ;; esac done shift $((OPTIND - 1)) now() { date '+%Y-%m-%dT%H:%M:%S%Z' } uuid() { # Taken from: # https://serverfault.com/a/799198 od -xN20 /dev/urandom | head -n1 | awk '{OFS="-"; print $2$3,$4,$5,$6,$7$8$9}' } mkstemp() { name="${TMPDIR:-/tmp}/uuid-tmpname with spaces.$(uuid)" touch "$name" echo "$name" } OUT="$(mkstemp)" printf 'Running command: %s\nStarting at: %s\n\n' "$*" "$(now)" >> "$OUT" ("$@" 2>&1) >> "$OUT" STATUS="$?" printf '\nFinished at: %s\n' "$(now)" >> "$OUT" mail \ -a 'Content-Type: text/plain; charset=UTF-8' \ -a 'From:cron@arrobaponto.org' \ -s "(exit status: $STATUS) - ${SUBJECT:-NO SUBJECT}" \ eu@euandre.org < "$OUT" cat "$OUT" """#)) (define backup.sh (plain-file "backup.sh" #"""- #!/bin/sh set -eux . /etc/profile-extra finish() { STATUS=$? printf '\n>>>\n>>> exit status: %s\n>>>\n\n' "$STATUS" >&2 } trap finish EXIT borg init -e repokey-blake2 suyin:borg/toph ||: borg key export suyin:borg/toph /opt/secrets/borg-key.txt borg create \ --exclude /root/.cache/ \ --stats \ --compression lzma,9 \ suyin:borg/toph::{hostname}-{now}-${1:-cronjob}" \ /root/ \ /home/ \ /etc/letsencrypt/ \ /var/lib/certbot/ \ /var/lib/letsencrypt \ /opt/ borg check \ --verbose \ suyin:borg/toph borg prune \ --verbose \ --list \ --keep-within=6m \ --keep-weekly=52 \ --keep-monthly=24 \ suyin:borg/toph """#)) (define vi.exrc (plain-file "vi.exrc" #"""- " set number set autoindent set tabstop=8 set shiftwidth=8 set ruler set showmode set showmatch """#)) (define opensmtpd.conf (plain-file "opensmtpd.conf" #"""- listen on 0.0.0.0 action inbound mbox match for local action inbound action outbound relay match from local for any action outbound """#)) (define opensmtpd.conf1 (plain-file "opensmtpd.conf" #"""- table aliases file:/etc/aliases table creds { } pki mail.arrobaponto.org cert "/etc/letsencrypt/live/arrobaponto.org/fullchain.pem" pki mail.arrobaponto.org key "/etc/letsencrypt/live/arrobaponto.org/privkey.pem" listen on eth0 filter check_dyndns phase connect match rdns regex { '.*\.dyn\..*', '.*\.dsl\..*' } junk filter check_rdns phase connect match !rdns junk filter check_fcrdns phase connect match !fcrdns junk accept from any for domain "arrobaponto.org" alias deliver to maildir accept for local alias deliver to maildir accept for any relay """#)) (define cronjobs (list #~(job "0 30 * * 0" "guix gc -d 1m -F 10G"))) (define admin-user "andreh") (define andreh-pk "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDnUv7iWOejQNa3fZ6v4lkHT6qFRp2+NuzIpFJ2Vy7eP58XZoiz6HJPcCU8Hf95JXwaXEwS4S7mXdw1x60hd8JIe058Ek6MZSSVQmlLfocGsAYj1wTrLmnQ8+PV0IeQlNj1aytBI1fL+v3IPt+JdLt6b+g3vwcEUU9efzxx2E0KZ5GIpb2meiCQ6ha+tcd7XqegB53eQj/h/coE2zLJodpaJ3xbj894pE/OJCNC0+4d0Sv7oHhY7QoLYldTQbSgPyhyfl4iZpJf6OEPZxK2cJaB+cbeoBB6aGNyU+CIJToM+uAJJ7H7EpvxfcnfJQ1PuY5szTdvFbW820euiUEKEW69mW4uaFNPSc6D4Z8tZ5hXQIqBD40irULhF0CYNkIILmyNV/KJIZ5HkbQ1q+UrCFHJyvuH/3aCTjj9OSfE7xHPQ3xd3Xw8vvj0Mjie09xFbbcklBTw5WRzH7cw8c+Q0O69kZZ8b+ykcdzWTeZeWNdnzptNqnMjfheig90rUIJ7DN0c+53jCUcGpWJxJhcYF9Uk1RNHmSE5+VzK1y+20t0grVFX90nApm4Tl35QPrX7Qxp9C81cWiUB8xCAE6jYrmd4x+P/3wSQfc1Xg0Eg3QjJB+6JD7cbyDJpzDR3ja+CLZCAr9I0B4rDKD2d6et/z67iXPnZUWMyZ8RVVZPFbBMOTw== openpgp:0xF727046D") (define users `(((#:username . "andreh") (#:extra-groups . ("wheel")) (#:public-keys . (,andreh-pk))))) (define user-accounts (map (lambda (user) (let ((name (assoc-ref user #:username)) (groups (or (assoc-ref user #:extra-groups) '()))) (user-account (name name) (comment name) (group "users") (supplementary-groups groups)))) users)) (define authorized-keys (map (lambda (user) (let* ((name (assoc-ref user #:username)) (pk-strs (assoc-ref user #:public-keys)) (pk-files (map (cut plain-file "id_rsa.pub" <>) pk-strs))) `(,name . ,pk-files))) users)) (define toph (operating-system (locale "fr_FR.utf8") (timezone "America/Sao_Paulo") (host-name "toph") (users (append user-accounts %base-user-accounts)) (sudoers-file (plain-file "sudoers" #"""- root ALL=(ALL) ALL %wheel ALL=NOPASSWD: ALL """#)) (packages (append (map (compose list specification->package+output symbol->string) '(nss-certs ; required for guix pull git-minimal borg)) %base-packages)) (services (append (list (service openssh-service-type (openssh-configuration (port-number 38123) (openssh openssh-sans-x) (password-authentication? #f) (subsystems '()) (log-level 'verbose) (authorized-keys authorized-keys) (extra-content ssh.conf))) (service dhcp-client-service-type) (service mcron-service-type (mcron-configuration (jobs cronjobs))) (simple-service 'extra-etc-file etc-service-type `(("backup.sh" ,backup.sh) ("profile-extra" ,profile-extra) ("bashrc-extra" ,bashrc-extra) ("ps1.sh" ,ps1.sh) ("vi.exrc" ,vi.exrc) ("infokey" ,infokey) ("with-email.sh" ,with-email.sh))) (service certbot-service-type (certbot-configuration (email "eu@euandre.org") (certificates (list (certificate-configuration (domains '("arrobaponto.org")) (deploy-hook (program-file "nginx-deploy-hook" #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read))) (kill pid SIGHUP))))))))) (service nginx-service-type (nginx-configuration (run-directory "/var/run/nginx") (server-blocks (list (nginx-server-configuration (server-name '("arrobaponto.org")) (listen '("[::]:443 ssl http2" "443 ssl http2")) (root "/opt/www/arrobaponto.org/static/") (ssl-certificate "/etc/letsencrypt/live/arrobaponto.org/fullchain.pem") (ssl-certificate-key "/etc/letsencrypt/live/arrobaponto.org/privkey.pem") (raw-content '(#"""- autoindex on; add_header Strict-Transport-Security 'max-age=86400; includeSubdomains' always; """#))))))) (service mail-aliases-service-type `(("webmaster" ,admin-user) ("abuse" ,admin-user) ("root" ,admin-user) ("postmaster" ,admin-user))) (service opensmtpd-service-type (opensmtpd-configuration (config-file opensmtpd.conf)))) (modify-services %base-services (guix-service-type config => (guix-configuration (inherit config) (authorized-keys (append (list (local-file "/etc/guix/signing-key.pub")) %default-authorized-guix-keys))))))) (bootloader (bootloader-configuration (bootloader grub-bootloader) (targets '("/dev/vda")))) (swap-devices (list (swap-space (target (uuid "30122738-f2f6-4f93-a37c-62023f56c73b"))))) (file-systems (append (list (file-system (mount-point "/") (device (uuid "455682d0-7ce7-4144-9728-a6d07beb049a" 'btrfs)) (type "btrfs"))) %base-file-systems)))) (list (machine (operating-system toph) (environment managed-host-environment-type) (configuration (machine-ssh-configuration (host-name "toph") (system "x86_64-linux") (user admin-user) (port 38123) (host-key "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILoz1gFl6chY91vQ5SrZXSP5yHqRI3TdYy2ccEDpS7Z4")))))