saklas.scm (22674B)
1 (define-module (epistemia systems saklas) 2 #:use-module (gnu) 3 #:use-module (gnu packages bash) 4 #:use-module (gnu packages emacs) 5 #:use-module (gnu packages golang-crypto) 6 #:use-module (gnu packages linux) 7 #:use-module (gnu packages mail) 8 #:use-module (gnu packages messaging) 9 #:use-module (gnu packages rsync) 10 #:use-module (gnu packages version-control) 11 #:use-module (gnu services certbot) 12 #:use-module (gnu services cgit) 13 #:use-module (gnu services dns) 14 #:use-module (gnu services file-sharing) 15 #:use-module (gnu services linux) 16 #:use-module (gnu services mail) 17 #:use-module (gnu services messaging) 18 #:use-module (gnu services networking) 19 #:use-module (gnu services security) 20 #:use-module (gnu services shepherd) 21 #:use-module (gnu services ssh) 22 #:use-module (gnu services vpn) 23 #:use-module (gnu services web) 24 #:use-module (gnu system accounts) 25 #:use-module (guix) 26 #:use-module (guix gexp) 27 #:use-module (guix transformations) 28 #:use-module (guix utils) 29 #:use-module (nongnu packages linux) 30 #:use-module (nongnu system linux-initrd) 31 #:use-module (epistemia bootloader) 32 #:use-module (epistemia systems base-system) 33 #:use-module (epistemia systems linux-initrd) 34 #:use-module (epistemia services age-secret) 35 #:use-module (epistemia services zfs) 36 #:use-module (epistemia packages bittorrent) 37 #:use-module (epistemia packages zfs) 38 #:use-module (ice-9 format)) 39 40 (define %nginx-badboi 41 (plain-file "nginx-badboi.conf" 42 "\ 43 set $bad_boi 0; 44 if ($http_user_agent ~* \"(AI2Bot|Ai2Bot\\-Dolma|aiHitBot|Amazonbot|Andibot|anthropic\\-ai|Applebot|Applebot\\-Extended|bedrockbot|Brightbot\\ 1\\.0|Bytespider|CCBot|ChatGPT\\-User|Claude\\-SearchBot|Claude\\-User|Claude\\-Web|ClaudeBot|cohere\\-ai|cohere\\-training\\-data\\-crawler|Cotoyogi|Crawlspace|Diffbot|DuckAssistBot|FacebookBot|Factset_spyderbot|FirecrawlAgent|FriendlyCrawler|Google\\-CloudVertexBot|Google\\-Extended|GoogleOther|GoogleOther\\-Image|GoogleOther\\-Video|GPTBot|iaskspider/2\\.0|ICC\\-Crawler|ImagesiftBot|img2dataset|ISSCyberRiskCrawler|Kangaroo\\ Bot|meta\\-externalagent|Meta\\-ExternalAgent|meta\\-externalfetcher|Meta\\-ExternalFetcher|MistralAI\\-User/1\\.0\\|MJ12|NovaAct|OAI\\-SearchBot|omgili|omgilibot|Operator|PanguBot|Panscient|panscient\\.com|Perplexity\\-User|PerplexityBot|PetalBot|PhindBot|QualifiedBot|QuillBot|quillbot\\.com|SBIntuitionsBot|Scrapy|SemrushBot\\-OCOB|SemrushBot\\-SWA|Sidetrade\\ indexer\\ bot|TikTokSpider|Timpibot|VelenPublicWebCrawler|Webzio\\-Extended|wpbot|YandexAdditional|YandexAdditionalBot|YouBot)\") { 45 set $bad_boi 1; 46 } 47 if ($request_uri = \"/robots.txt\") { 48 set $bad_boi 0; 49 } 50 if ($bad_boi = 1) { 51 return 307 https://planet.openstreetmap.org/pbf/planet-latest.osm.pbf; 52 } 53 ")) 54 55 (define %opensmtpd-config 56 (mixed-text-file "opensmtpd.conf" 57 "table domains { vineetk.net, 13f0.net, vinbiz.ca }\n" 58 "table virtuals file:/run/secrets/saklas_smtpd_virtuals\n" 59 "table passwd file:/run/secrets/saklas_smtpd_passwd\n" 60 "\n" 61 "pki mail.vineetk.net cert \"/etc/certs/vineetk.net/fullchain.pem\"\n" 62 "pki mail.vineetk.net key \"/etc/certs/vineetk.net/privkey.pem\"\n" 63 "\n" 64 "filter check_dyndns phase connect match rdns regex { '.*\\.dyn\\..*', '.*\\.dsl\\..*' } disconnect \"550 no residential connections\"\n" 65 "filter check_rdns phase connect match !rdns disconnect \"550 no connections without an rDNS\"\n" 66 "filter check_fcrdns phase connect match !fcrdns disconnect \"550 no connections without an FCrDNS\"\n" 67 "#filter sendscore proc-exec \"filter-sendscore -blockBelow 10 -junkBelow 70 -slowFactor 5000\"\n" 68 "filter dkimsign_rsa proc-exec \"" 69 (file-append opensmtpd-filter-dkimsign "/libexec/opensmtpd/filter-dkimsign") 70 " -d 13f0.net -d vinbiz.ca -d vineetk.net -s mail -k /run/secrets/saklas_smtpd_dkim\"" 71 " user smtpd group nogroup\n" 72 "\n" 73 "listen on socket\n" 74 "listen on eth0 port 25 tls pki mail.vineetk.net filter { check_dyndns, check_rdns, check_fcrdns }\n" 75 "listen on eth0 port 465 smtps pki mail.vineetk.net auth <passwd> filter dkimsign_rsa\n" 76 "\n" 77 "action \"inbound\" lmtp \"/var/run/dovecot/lmtp\" rcpt-to virtual <virtuals>\n" 78 "action \"outbound\" relay helo mail.vineetk.net\n" 79 "\n" 80 "match from local for local action \"inbound\"\n" 81 "match from any for domain <domains> action \"inbound\"\n" 82 "match from local for any action \"outbound\"\n" 83 "match from any auth for any action \"outbound\"\n")) 84 85 ;; adapted from my pf.conf 86 (define %nftables-ruleset 87 (plain-file "nftables.conf" "\ 88 define ext_if = \"eth0\" 89 define vpn_if = \"wg0\" 90 91 define tcp_ports = { 92 http, https, 93 smtp, smtps, imaps, 94 xmpp-client, xmpp-server, 5281, 5201, 95 6060 96 } 97 98 define udp_ports = { 99 3478, 5201, 51413, 51820 100 } 101 102 table inet filter { 103 set ssh_whitelist_ipv4 { 104 type ipv4_addr 105 flags interval 106 elements = { 107 47.201.69.0/24, 108 185.157.162.25/24 109 } 110 } 111 112 set ssh_whitelist_ipv6 { 113 type ipv6_addr 114 flags interval 115 elements = { 116 2001:470:d851:b0ba::/64, 117 2a07:a880:3101:102a:2b39:4fb9:4975:4c1d 118 } 119 } 120 121 chain input { 122 type filter hook input priority 0; policy drop; 123 124 # set skip on lo 125 iifname lo accept 126 # drop connections to lo not coming from lo 127 iif != lo ip daddr 127.0.0.1/8 drop 128 iif != lo ip6 daddr ::1/128 drop 129 130 # early drop of invalid connections 131 ct state invalid drop 132 # allow established/related connections 133 ct state { established, related } accept 134 135 # unblock pings 136 ip protocol icmp icmp type echo-request accept 137 ip6 nexthdr icmpv6 icmpv6 type { packet-too-big, echo-request } accept 138 ip6 nexthdr icmpv6 icmpv6 \ 139 type { echo-request, nd-router-solicit, nd-router-advert, 140 nd-neighbor-solicit, nd-neighbor-advert, nd-redirect } accept 141 142 iifname $ext_if tcp dport $tcp_ports ct state new accept 143 iifname $ext_if udp dport $udp_ports ct state new accept 144 145 iifname $vpn_if tcp dport { 9090, 9100 } ct state new accept 146 147 # allow public ssh only to my normal home address and mullvad ips 148 iifname $ext_if tcp dport ssh ip saddr @ssh_whitelist_ipv4 ct state new log prefix \"SSH_V4: \" accept 149 iifname $ext_if tcp dport ssh ip6 saddr @ssh_whitelist_ipv6 ct state new log prefix \"SSH_V6: \" accept 150 151 iifname wg1 accept 152 153 # reject everything else 154 reject with icmpx type port-unreachable 155 } 156 157 chain forward { 158 type filter hook forward priority 0; policy drop; 159 } 160 161 chain output { 162 type filter hook output priority 0; policy accept; 163 } 164 } 165 ")) 166 167 168 (operating-system 169 (inherit base-system) 170 (host-name "saklas.epistemia") 171 172 (users (cons* (user-account 173 (name "vin") 174 (comment "Vineet") 175 (shell (file-append bash "/bin/bash")) 176 (group "users") 177 (supplementary-groups '("wheel" "git" "torrents"))) 178 (user-account 179 (name "git") 180 (comment "git account") 181 (group "git") 182 (shell (file-append bash "/bin/bash")) 183 (home-directory "/data/src/bare") 184 (system? #t)) 185 (user-account 186 (name "torrents") 187 (comment "torrenting account") 188 (group "torrents") 189 (shell "/dev/null") 190 (home-directory "/var/empty") 191 (system? #t)) 192 (user-account 193 (name "vmail") 194 (comment "virtual mail account") 195 (group "vmail") 196 (shell "/dev/null") 197 (home-directory "/var/vmail") 198 (system? #t)) 199 %base-user-accounts)) 200 (groups (cons* (user-group 201 (name "git")) 202 (user-group 203 (name "torrents")) 204 (user-group 205 (name "vmail")) 206 %base-groups)) 207 208 (kernel linux-6.18) 209 (kernel-arguments (list "net.ifnames=0" "nomodeset")) 210 (kernel-loadable-modules (list (list zfs-linux "module"))) 211 212 (initrd (lambda (file-systems . args) 213 (apply microcode-initrd file-systems 214 #:initrd epistemia-zfs-initrd 215 #:zfs-package zfs-linux 216 args))) 217 (firmware (cons* amdgpu-firmware %base-firmware)) 218 219 (bootloader (bootloader-configuration 220 (bootloader grub-zfs-bios) 221 (targets '("/dev/sda")))) 222 223 (file-systems (append 224 (list (file-system 225 (device "zroot/root") 226 (mount-point "/") 227 (type "zfs") 228 (check? #f) 229 (needed-for-boot? #t)) 230 (file-system 231 (device "zroot/gnu") 232 (mount-point "/gnu") 233 (type "zfs") 234 (check? #f) 235 (needed-for-boot? #t)) 236 (file-system 237 (device "zroot/var") 238 (mount-point "/var") 239 (type "zfs") 240 (check? #f) 241 (needed-for-boot? #t)) 242 (file-system 243 (device "zroot/home") 244 (mount-point "/home") 245 (type "zfs") 246 (check? #f) 247 (needed-for-boot? #t))) 248 %base-file-systems)) 249 250 (packages (append (list emacs-no-x 251 git 252 rsync 253 zfs-linux) 254 %base-packages)) 255 256 (services (modify-services (append (list (service age-secret-service-type 257 (age-secret-configuration 258 (secrets (list 259 (age-secret 260 (name "wg1_saklas") 261 (file (local-file "../secrets/wg1_saklas.age"))) 262 (age-secret 263 (name "saklas_smtpd_dkim") 264 (file (local-file "../secrets/saklas_smtpd_dkim.age")) 265 (owner "smtpd") 266 (group "nogroup") 267 (mode #o400)) 268 (age-secret 269 (name "saklas_smtpd_virtuals") 270 (file (local-file "../secrets/saklas_smtpd_virtuals.age")) 271 (owner "smtpd") 272 (group "nogroup") 273 (mode #o400)) 274 (age-secret 275 (name "saklas_smtpd_passwd") 276 (file (local-file "../secrets/saklas_smtpd_passwd.age")) 277 (owner "smtpd") 278 (group "dovecot") 279 (mode #o440)))))) 280 (simple-service 'zfs-loader 281 kernel-module-loader-service-type 282 '("zfs")) 283 (simple-service 'zfs-shepherd-services 284 shepherd-root-service-type 285 zfs-shepherd-services) 286 (simple-service 'zfs-shepherd-services-user-processes 287 user-processes-service-type 288 '(zfs-automount)) 289 (service nftables-service-type 290 (nftables-configuration 291 (ruleset %nftables-ruleset))) 292 (service static-networking-service-type 293 ;; TODO hurricane electric for ipv6 /48. ovh vps only gets /128. 294 (list (static-networking 295 (addresses 296 (list (network-address 297 (device "eth0") 298 (value "141.95.52.111/24")))) 299 (routes 300 (list (network-route 301 (destination "default") 302 (gateway "141.95.52.1"))))))) 303 (simple-service 'resolv-configuration 304 etc-service-type 305 `(("resolv.conf" 306 ,(plain-file "resolv.conf" 307 (string-append 308 "nameserver 127.0.0.1\n" 309 "search epistemia\n"))))) 310 (service openssh-service-type 311 (openssh-configuration 312 (permit-root-login 'prohibit-password) 313 (password-authentication? #f) 314 (authorized-keys 315 `(("vin" ,(local-file "/data/ssh/id_ed25519.pub")) 316 ("git" ,(local-file "/data/ssh/id_ed25519.pub")) 317 ("root" ,(local-file "/data/ssh/id_ed25519.pub")))))) 318 (service unbound-service-type 319 (unbound-configuration 320 (server 321 (unbound-server 322 (interface '("127.0.0.1" 323 "::1" 324 "10.0.13.1")) 325 (hide-version #t) 326 (hide-identity #t))) 327 (extra-content "\ 328 server: 329 access-control: 127.0.0.0/8 allow 330 access-control: 10.0.13.0/24 allow 331 access-control: ::1 allow 332 333 ip-freebind: yes 334 aggressive-nsec: no 335 module-config: \"respip validator iterator\" 336 337 local-data: \"saklas.epistemia. 86400 IN A 10.0.13.1\" 338 local-data: \"saklas.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::1\" 339 local-data: \"demiurge.epistemia. 86400 IN A 10.0.13.2\" 340 local-data: \"demiurge.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::2\" 341 local-data: \"hastur.epistemia. 86400 IN A 10.0.13.3\" 342 local-data: \"hastur.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::3\" 343 local-data: \"iphonebob.epistemia. 86400 IN A 10.0.13.4\" 344 local-data: \"iphonebob.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::4\" 345 local-zone: \"saklas.epistemia.\" redirect 346 local-zone: \"demiurge.epistemia.\" redirect 347 local-zone: \"hastur.epistemia.\" redirect 348 local-zone: \"iphonebob.epistemia.\" redirect 349 350 rpz: 351 name: \"hagezi.ultimate\" 352 zonefile: \"hagezi.ultimate\" 353 url: https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/ultimate.txt"))) 354 (service wireguard-service-type 355 (wireguard-configuration 356 (interface "wg1") 357 (addresses '("10.0.13.1/24" "fd00:b0ba:cafe:babe::1/64 ")) 358 (port 51820) 359 (bootstrap-private-key? #f) 360 (private-key "/run/secrets/wg1_saklas") 361 (peers 362 (list 363 (wireguard-peer 364 (name "demiurge.epistemia") 365 (public-key "FMLvbSxY6vA8CRV4S1vl4+pMeCr/kR9n0G5w9buNqh4=") 366 (allowed-ips '("10.0.13.2/32" "fd00:b0ba:cafe:babe::2/128")) 367 (keep-alive 25)) 368 (wireguard-peer 369 (name "hastur.epistemia") 370 (public-key "1ketYziRhoUmpbrj/60O5DYbcPacvmEoFQqa/NntSnc=") 371 (allowed-ips '("10.0.13.3/32" "fd00:b0ba:cafe:babe::3/128")) 372 (keep-alive 25)) 373 (wireguard-peer 374 (name "iphonebob.epistemia") 375 (public-key "Xn0EmeRZdpMejBgzr98mYtb/2f5O58GAzQLNZV/SS30=") 376 (allowed-ips '("10.0.13.4/32" "fd00:b0ba:cafe:babe::4/128")) 377 (keep-alive 25)) 378 (wireguard-peer 379 (name "lab.epistemia") 380 (public-key "iMDEwvXjPAlQH8ZCmP63FM5ICYIFIX5XIyGxjnXoNVE=") 381 (allowed-ips '("10.0.13.5/32" "fd00:b0ba:cafe:babe::5/128")) 382 (keep-alive 25)))))) 383 (service certbot-service-type 384 (certbot-configuration 385 (email "postmaster@vineetk.net") 386 (certificates 387 (list 388 (certificate-configuration 389 (deploy-hook (program-file 390 "import-prosody-certs" 391 #~(begin 392 (let ((prosodyctl (string-append #$prosody "/bin/prosodyctl"))) 393 (system* prosodyctl "--root" "cert" "import" "/etc/certs"))))) 394 (domains '("vineetk.net" 395 "git.vineetk.net" 396 "mail.vineetk.net" 397 "u.vineetk.net" 398 "xmpp.vineetk.net"))) 399 (certificate-configuration 400 (domains '("13f0.net" 401 "m.13f0.net" 402 ;"snac.13f0.net" 403 ))) 404 (certificate-configuration 405 (domains '("vinbiz.ca"))))))) 406 (service nginx-service-type 407 (nginx-configuration 408 (extra-content "limit_req_zone $binary_remote_addr zone=git_rate:10m rate=30r/m;") 409 (server-blocks 410 (list (nginx-server-configuration 411 (server-name '("vineetk.net")) 412 (listen '("443 ssl")) 413 (ssl-certificate "/etc/certs/vineetk.net/fullchain.pem") 414 (ssl-certificate-key "/etc/certs/vineetk.net/privkey.pem") 415 (root "/var/www/site_vineetk") 416 (raw-content (list "include " %nginx-badboi ";"))) 417 (nginx-server-configuration 418 (server-name '("13f0.net")) 419 (listen '("443 ssl")) 420 (ssl-certificate "/etc/certs/13f0.net/fullchain.pem") 421 (ssl-certificate-key "/etc/certs/13f0.net/privkey.pem") 422 (root "/var/www/site_13f0") 423 (raw-content (list "include " %nginx-badboi ";"))) 424 (nginx-server-configuration 425 (server-name '("vinbiz.ca")) 426 (listen '("443 ssl")) 427 (ssl-certificate "/etc/certs/vinbiz.ca/fullchain.pem") 428 (ssl-certificate-key "/etc/certs/vinbiz.ca/privkey.pem") 429 (root "/var/www/site_vinbiz") 430 (raw-content (list "include " %nginx-badboi ";"))))))) 431 ;; git folder needs to be readable by nginx/cgit, gets reset to 700 on reconfigure otherwise 432 (simple-service 'git-home-permissions 433 activation-service-type 434 #~(when (file-exists? "/data/src/bare") 435 (chmod "/data/src/bare" #o775))) 436 (simple-service 'git-mirror-update 437 shepherd-root-service-type 438 (list (shepherd-timer 439 '(git-mirror-update) 440 "0 */8 * * *" ; vixie cron doesn't support random/tilde. I'm sorry codeberg and other mirrors :( 441 #~("/run/privileged/bin/su" "git" "-c" 442 "for i in $(dirname $(grep -l Mirrors /data/src/bare/*.git/cgitrc)); do (cd \"$i\"; git fetch upstream --prune); done") 443 #:requirement '(networking) 444 #:documentation "Update git mirrors every 8 hours."))) 445 (service fcgiwrap-service-type 446 (fcgiwrap-configuration 447 (user "git") 448 (group "git") 449 (socket "tcp:127.0.0.1:9000"))) 450 (service cgit-service-type 451 (cgit-configuration 452 (enable-index-links? #t) 453 (enable-log-filecount? #t) 454 (enable-log-linecount? #t) 455 (enable-git-config? #t) 456 (remove-suffix? #t) 457 (root-desc "") 458 (root-title "Vineet's git repos") 459 (repository-directory "/data/src/bare") 460 (section-from-path 1) 461 (side-by-side-diffs? #t) 462 (nginx 463 (list 464 (nginx-server-configuration 465 (server-name '("git.vineetk.net")) 466 (listen '("443 ssl")) 467 (root cgit) 468 (try-files (list "$uri" "@cgit")) 469 (ssl-certificate "/etc/certs/vineetk.net/fullchain.pem") 470 (ssl-certificate-key "/etc/certs/vineetk.net/privkey.pem") 471 (raw-content (list "include" %nginx-badboi ";")) 472 (locations 473 (list 474 (nginx-location-configuration 475 (uri "~ \"^/(?<repo>.+?)(\\.git)?/(?<gitpath>(?:HEAD|info/refs|objects/(?:info/[^/]+|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\\.(?:pack|idx))|git-upload-pack))$\"") 476 (body (list #~(string-append "fastcgi_param SCRIPT_FILENAME " #$(file-append git "/libexec/git-core/git-http-backend") ";") 477 "fastcgi_param GIT_PROJECT_ROOT /data/src/bare;" 478 "fastcgi_param PATH_INFO /$repo.git/$gitpath;" 479 "fastcgi_param GIT_HTTP_EXPORT_ALL \"\";" 480 "fastcgi_param REMOTE_USER $remote_user;" 481 "fastcgi_param QUERY_STRING $args;" 482 "fastcgi_param REQUEST_METHOD $request_method;" 483 "fastcgi_param CONTENT_TYPE $content_type;" 484 "fastcgi_param CONTENT_LENGTH $content_length;" 485 "fastcgi_param HTTP_HOST $server_name;" 486 "fastcgi_pass 127.0.0.1:9000;"))) 487 (nginx-location-configuration 488 ;; mimics bad_boi behaviour for rate-limited abusers 489 (uri "@send_to_bigfile") 490 (body '("return 307 https://planet.openstreetmap.org/pbf/planet-latest.osm.pbf;"))) 491 (nginx-location-configuration 492 (uri "@cgit") 493 (body '("limit_req zone=git_rate burst=5 nodelay;" 494 "limit_req_status 429;" 495 "error_page 429 =307 @send_to_bigfile;" 496 "fastcgi_param SCRIPT_FILENAME $document_root/lib/cgit/cgit.cgi;" 497 "fastcgi_param PATH_INFO $uri;" 498 "fastcgi_param QUERY_STRING $args;" 499 "fastcgi_param HTTP_HOST $server_name;" 500 "fastcgi_pass 127.0.0.1:9000;")))))))))) 501 (service prosody-service-type 502 (prosody-configuration 503 (admins '("vin@vineetk.net")) 504 (allow-registration? #f) 505 (c2s-require-encryption? #t) 506 (s2s-require-encryption? #t) 507 (s2s-secure-auth? #t) 508 (authentication "internal_hashed") 509 (plugin-paths (list prosody-cloud-notify)) 510 (modules-enabled 511 ;; list from https://github.com/monal-im/Monal/wiki/Considerations-for-XMPP-server-admins#prosody 512 (cons* "sasl_ssdp" 513 ;; TODO update prosody to 13 514 ;; "sasl2" 515 ;; "sasl2_bind2" 516 ;; "sasl2_sm" 517 ;; "sasl2_fast" 518 "muc_notifications" 519 "smacks" 520 "mam" 521 "csi_simple" 522 "cloud_notify" 523 "bookmarks" 524 %default-modules-enabled)) 525 ;; I don't want my syslog flooded. can't control changes either in service yet 526 (log "/var/lib/prosody/prosody.log") 527 (virtualhosts 528 (list 529 (virtualhost-configuration 530 (domain "vineetk.net")))))) 531 (service opensmtpd-service-type 532 (opensmtpd-configuration 533 (config-file %opensmtpd-config))) 534 (service dovecot-service-type 535 (dovecot-configuration 536 (listen '("*" "::")) 537 (mail-location "maildir:/var/vmail/%d/%n") 538 (mail-uid "vmail") 539 (mail-gid "vmail") 540 (ssl? "required") 541 (ssl-cert "</etc/certs/vineetk.net/fullchain.pem") 542 (ssl-key "</etc/certs/vineetk.net/privkey.pem") 543 (namespaces 544 (list (namespace-configuration 545 (name "inbox") 546 (inbox? #t) 547 (location "") 548 (prefix "") 549 (mailboxes 550 (list (mailbox-configuration 551 (name "Drafts") 552 (special-use '("\\Drafts"))) 553 (mailbox-configuration 554 (name "Junk") 555 (special-use '("\\Junk"))) 556 (mailbox-configuration 557 (name "Sent") 558 (special-use '("\\Sent"))) 559 (mailbox-configuration 560 (name "Trash") 561 (special-use '("\\Trash")))))))) 562 (passdbs 563 (list (passdb-configuration 564 (driver "passwd-file") 565 (args '("scheme=CRYPT" "username_format=%u" "/run/secrets/saklas_smtpd_passwd"))))) 566 (userdbs 567 (list (userdb-configuration 568 (driver "static") 569 (args '("uid=vmail" "gid=vmail" "home=/var/vmail/%d/%n"))))) 570 (protocols 571 (list (protocol-configuration (name "imap")) 572 (protocol-configuration (name "lmtp")))) 573 (services 574 (list (service-configuration 575 (kind "lmtp") 576 (listeners 577 (list (unix-listener-configuration 578 (path "lmtp") 579 (group "vmail") 580 (user "vmail")))))))))) 581 %base-services) 582 (guix-service-type config => 583 (guix-configuration 584 (inherit config) 585 (authorized-keys 586 (append (list (local-file "../../demiurge.pub")) 587 %default-authorized-guix-keys)))))))