aboutsummaryrefslogtreecommitdiff
path: root/tw/system.scm
blob: 92eadeba3d0736e425d18357a700283c57776cad (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
(define-module (tw system)
  #:use-module (ice-9 format)
  #:use-module (ice-9 regex)
  #:use-module (ice-9 string-fun)
  #:use-module ((srfi srfi-1) #:select (append-map every))
  #:use-module ((srfi srfi-26) #:select (cut))
  #:use-module (gnu)
  #:use-module (gnu services)
  #:use-module (gnu system)
  #:use-module (gnu system keyboard)
  #:use-module (guix gexp))

(use-package-modules admin avahi certs curl disk file-systems linux lsof man
                     moreutils python rsync search shells version-control vpn)
(use-service-modules configuration mcron monitoring networking ssh vpn)

(define-public %base-system-packages
  (cons* acpi btrfs-progs cpupower curl efibootmgr exfat-utils git glibc-locales
         hddtemp htop lshw lsof man-db man-pages man-pages-posix mlocate
         moreutils nss-certs nss-mdns python rsync strace wireguard-tools
         %base-packages))

(define-public %british-keyboard
  (keyboard-layout
   "gb" #:options '("caps:swapescape"
                    "parens:swap_brackets"
                    "terminate:ctrl_alt_bksp"
                    "compose:rctrl"
                    "keypad:oss"
                    "kpdl:kposs")))

;; This is used for the servers, and also by (tw home) to generate the
;; appropriate ~/.ssh/config.
(define-public %ssh-ports
  '(("lud.twilken.net" . 22022)
    ("vin.twilken.net" . 22022)
    ("pi3.twilken.net" . 51022)))

(define-public (server-base-services host-name)
  (cons*
   ;; SSH login, allowing access only for me.  To give more public keys
   ;; access, extend `openssh-service-type'.
   (service openssh-service-type
     (openssh-configuration
      (port-number (assoc-ref %ssh-ports host-name))
      (password-authentication? #f)
      (accepted-environment '("LANG" "LC_*"))
      (authorized-keys
       `(("timo"
          ,(local-file "system/files/timo.pub")
          ,(local-file "system/files/timo-phone-gpg.pub"))))))

   ;; Prometheus node exporter
   (service prometheus-node-exporter-service-type
     (prometheus-node-exporter-configuration
      (web-listen-address
       (string-replace-substring
        (car   ; get the IPv4 address
         (wireguard-peer-allowed-ips
          (assoc-ref %wireguard-peers host-name)))
        "/32" ":9100"))))

   (simple-service 'disk-maintenance mcron-service-type
     (list #~(job "0 2 * * *" "guix gc -d 2w")
           #~(job "0 4 * * *"  ; after guix gc
                  (string-append #$(file-append util-linux "/sbin/fstrim")
                                 " --fstab --verbose"))))

   ;; Network setup
   (service dhcp-client-service-type)
   (service ntp-service-type)
   (service tw-wireguard-service-type
     (tw-wireguard-configuration
      (this-host host-name)))

   ;; Delete the annoying message on SSH login.  Beware when setting up a new
   ;; host, as `allow-empty-passwords' will block login and sudo execution for
   ;; all Guix-declared users (as these have no initial password).
   (modify-services %base-services
     (login-service-type
      config =>
      (login-configuration
       (inherit config)
       (motd (plain-file "no-motd" ""))
       (allow-empty-passwords? #f))))))

(define-public %server-base-user-accounts
  (cons* (user-account
          (name "timo")
          (comment "Timo Wilken")
          (group "users")
          (home-directory "/home/timo")
          (supplementary-groups '("wheel" "netdev" "audio" "video"))
          (shell (file-append zsh "/bin/zsh")))
         %base-user-accounts))

(define-public %wireguard-peers
  `(("lap.twilken.net" .
     ,(wireguard-peer
       (name "lap.wg")
       (public-key "lap/DvCb8xXLUCqcaPEx8kCRcoeV4ScTMVZW5hvvNzA=")
       (preshared-key "/etc/wireguard/lap.psk")
       (allowed-ips '("10.0.0.1/32" "fc00::1/128"))))
    ("lud.twilken.net" .
     ,(wireguard-peer
       (name "lud.wg")
       (endpoint "lud.twilken.net:58921")
       (public-key "lud/9sbXVdOYXxOkRgAB+b/17QxbwllfJY/pbA3/MkE=")
       (preshared-key "/etc/wireguard/lud.psk")
       (allowed-ips '("10.0.0.2/32" "fc00::2/128"))))
    ("vin.twilken.net" .
     ,(wireguard-peer
       (name "vin.wg")
       (endpoint "vin.twilken.net:58921")
       (public-key "vin/Im+sOszZFE01UF1+QlyxLP1PsPXJgTz4KmgvL3Y=")
       (preshared-key "/etc/wireguard/vin.psk")
       (allowed-ips '("10.0.0.3/32" "fc00::3/128"))))
    ("fp4.twilken.net" .
     ,(wireguard-peer
       (name "fp4.wg")
       (public-key "fp4/aLAVBADTy+UGmNh011w1CFOOwq70Df6EWlZRkAs=")
       (preshared-key "/etc/wireguard/fp4.psk")
       (allowed-ips '("10.0.0.4/32" "fc00::4/128"))))
    ("pi3.twilken.net" .
     ,(wireguard-peer
       (name "pi3.wg")
       (endpoint "pi3.twilken.net:58922")
       (public-key "pi3/ThUH4qDTuyvNQIiiyy2dbziF/xLRTwO0+vcUoVY=")
       (preshared-key "/etc/wireguard/pi3.psk")
       (allowed-ips '("10.0.0.5/32" "fc00::5/128"))))))

(define (wireguard-peers-list? object)
  (and (list? object)
       (every (compose string? car) object)
       (every (compose wireguard-peer? cdr) object)))

(export tw-wireguard-configuration)
(define-configuration/no-serialization tw-wireguard-configuration
  (this-host
   (string)
   "The host name of the machine being configured.")
  (peers
   (wireguard-peers-list %wireguard-peers)
   "An alist of WireGuard peers to install."))

(define (tw-wireguard-service config)
  "Create a full WireGuard config from the personal network CONFIG."
  (let ((own-peer (assoc-ref (tw-wireguard-configuration-peers config)
                             (tw-wireguard-configuration-this-host config))))
    (wireguard-configuration
     (addresses
      (map (lambda (cidr)
             (let ((ipv4 (string-match "/32$" cidr))
                   (ipv6 (string-match "/128$" cidr)))
               (cond
                (ipv4 (regexp-substitute #f ipv4 'pre "/24"))
                (ipv6 (regexp-substitute #f ipv6 'pre "/64"))
                (#t cidr))))
           (wireguard-peer-allowed-ips own-peer)))
     (port
      (let ((endpoint (wireguard-peer-endpoint own-peer)))
        (if endpoint
            (string->number (cadr (string-split endpoint #\:)))
            58921)))
     (private-key "/etc/wireguard/private.key")
     (peers (delq own-peer (map cdr (tw-wireguard-configuration-peers config)))))))

(define (peer->ips peer)
  "Extract IP addresses assigned to the given `wireguard-peer' PEER."
  (map (compose car (cut string-split <> #\/))
       (wireguard-peer-allowed-ips peer)))

(define (tw-wireguard-hosts config)
  "Generate a hosts file entries from the personal WireGuard network CONFIG."
  (append-map (lambda (peer)
                (map (cut host <> (wireguard-peer-name peer))
                     (peer->ips peer)))
              (map cdr (tw-wireguard-configuration-peers config))))

(define-public tw-wireguard-service-type
  (service-type
   (name 'tw-wireguard)
   (description "Set up my personal WireGuard network.")
   (extensions
    (cons* (service-extension hosts-service-type tw-wireguard-hosts)
           ;; FIXME: `wireguard-service-type' cannot be extended, so copy its
           ;; service-extensions directly.
           (map (lambda (ext)
                  (service-extension (service-extension-target ext)
                                     (compose (service-extension-compute ext)
                                              tw-wireguard-service)))
                (service-type-extensions wireguard-service-type))))))