#+title: Server configuration #+author: winter Sparkles #+property: header-args :mkdirp yes :padline no This is a work-in-progress recreation of our server's configuration in the form of a literate Org file, plus a makefile that installs it for you. To use it, you can run =make && doas make install= on an existing Alpine system that has (GNU) Emacs installed, or, you can run =make distrib.tar.xz= on some other system with Emacs, then move the file =distrib.tar.xz= to an Alpine system, unpack it over there, and run =doas make install=, which doesn't require Emacs to be available on the target system. * Package management ** apk repositories We're using the default CDN mirror (change this if you want a different one): #+begin_src plain :noweb-ref apk-mirror http://dl-cdn.alpinelinux.org/alpine #+end_src The standard main and community repos for the latest stable release: #+begin_src conf :tangle sys/etc/apk/repositories :noweb yes <>/latest-stable/main <>/latest-stable/community #+end_src Plus, extra ones for community and testing on the edge branch, to allow installing more software and newer versions of certain packages: #+begin_src conf :tangle sys/etc/apk/repositories :noweb yes @community-edge <>/edge/community @testing <>/edge/testing #+end_src * System utilities ** cron daemon We're just using the busybox cron daemon, it gets the job done. #+begin_src shell :tangle scripts/enable-services rc-update add crond #+end_src By default, the system comes with a crontab that executes scripts under =/etc/periodic/= every so often. * Networking ** tinc VPN TODO ** DNS #+begin_src conf :tangle sys/etc/resolvconf.conf :exports none resolv_conf=/etc/resolv.conf #+end_src We run a local DNS server, which uses unbound, therefore install and enable unbound: #+begin_src conf :tangle sys/etc/apk/world unbound unbound-doc #+end_src #+begin_src shell :tangle scripts/enable-services :tangle-mode o755 :shebang #!/bin/sh rc-update add unbound #+end_src Point the system resolver at the unbound server (in resolvconf.conf): #+begin_src conf :tangle sys/etc/resolvconf.conf name_servers=127.0.0.1 #+end_src *** Authoritative zone for internal VPN addresses Since we use [[*tinc VPN][tinc mesh VPN]], all of our machines have internal IP addresses, and it's nice have them be resolvable by their hostnames. So there is this zonefile: #+begin_src zone :tangle sys/etc/unbound/zones/infra.zone $ORIGIN infra.xn--80andq.net. $TTL 3600 @ IN SOA celestine.infra.xn--80andq.net. contact.xn--80andq.net. 2026072202 10800 3600 604800 3600 amber.infra.xn--80andq.net. IN AAAA fd8c:4ea1:9a24:1::4 amber.infra.xn--80andq.net. IN A 10.101.1.4 neptunite.infra.xn--80andq.net. IN AAAA fd8c:4ea1:9a24:1::5 neptunite.infra.xn--80andq.net. IN A 10.101.1.5 selenite.infra.xn--80andq.net. IN AAAA fd8c:4ea1:9a24:1::2 selenite.infra.xn--80andq.net. IN A 10.101.1.2 celestine.infra.xn--80andq.net. IN AAAA fd8c:4ea1:9a24:1::1 celestine.infra.xn--80andq.net. IN A 10.101.1.1 ametrine.infra.xn--80andq.net. IN AAAA fd8c:4ea1:9a24:1::3 ametrine.infra.xn--80andq.net. IN A 10.101.1.3 #+end_src unbound also needs to be told about it: #+begin_src conf :tangle sys/etc/unbound/unbound.conf.d/authority.conf auth-zone: name: infra.xn--80andq.net. zonefile: /etc/unbound/zones/infra.zone #+end_src Finally, resolvconf can be told about it as a 'search domain' so it's possible to just write the short hostnames: #+begin_src conf :tangle sys/etc/resolvconf.conf search_domains=infra.xn--80andq.net #+end_src *** More miscellaneous unbound config snippets **** Be accessible on the appropriate interfaces Again, this is necessary because we want unbound to be visible to other devices in the tinc network. #+begin_src conf :tangle sys/etc/unbound/unbound.conf.d/interfaces.conf server: interface: winternet interface: lo access-control: 10.101.0.0/16 allow access-control: 127.0.0.1 allow #+end_src **** Recursively resolve upstream zones Here we're using the 9.9.9.9 public recursive DNS server. #+begin_src conf :tangle sys/etc/unbound/unbound.conf.d/upstream.conf forward-zone: name: "." forward-addr: 9.9.9.9 #+end_src **** Rehike TODO: move this section to the actual section for rehike, whenever we write that #+begin_src conf :tangle sys/etc/unbound/unbound.conf.d/youtube.conf server: local-zone: "youtube.com." redirect local-data: "youtube.com. A 10.101.1.1" #+end_src ** TLS certificates *** Let's Encrypt Obviously we can't put the full and entire configuration here because it might let you impersonate us. But! Here are some parts: We're using certbot because we're lazy, and also the PowerDNS plugin for it so that we can use it with [[https://servfail.network/][servfail]]: #+begin_src conf :tangle sys/etc/apk/world certbot certbot-dns-pdns@testing #+end_src Then, after getting certificates for the first time (consult certbot docs on how to do that), this script in =/etc/periodic/weekly= makes sure they're renewed as needed, and informs us when it does so using [[*sendmail-fancy][sendmail-fancy]]: #+begin_src shell :tangle sys/etc/periodic/weekly/certbot-renew.sh :tangle-mode o755 #!/bin/bash { printf "it's that time of the week again...\n\n" certbot renew } | sendmail-fancy crond@celestine winter "certbot renew output" #+end_src ** Email We use [[https://www.opensmtpd.org/][OpenSMTPD]] as an email server, since it's easy to configure. Plus the dkimsign filter for it, to allow signing outbound emails with our DKIM key. #+begin_src conf :tangle sys/etc/apk/world opensmtpd opensmtpd-doc opensmtpd-filter-dkimsign opensmtpd-filter-dkimsign-doc #+end_src TODO: smtpd config and dovecot config *** sendmail-fancy Super simple shell script that makes it easier to send emails programmatically: #+begin_src shell :tangle sys/usr/local/bin/sendmail-fancy #!/bin/bash if [ $# -ne 3 ]; then echo "usage: $0 " 1>&2 exit 1 fi { echo "Subject: $3" echo "To: $2" echo "From: $1" echo "Date: $(date -R)" echo cat } | sendmail -t #+end_src