A => .makeimg.modes +22 -0
@@ 1,22 @@
+644 files/etc/apk/repositories
+644 files/etc/conf.d/sshd.makeimg.patch
+600 files/etc/doas.d/doas.conf
+644 files/etc/hostname.makeimg.template
+644 files/etc/inittab.makeimg.patch
+644 files/etc/knot-resolver/kresd.conf
+644 files/etc/knot/knot.conf.makeimg.template
+644 files/etc/motd.makeimg.template
+644 files/etc/network/interfaces.makeimg.template
+644 files/etc/ssh/sshd_config.makeimg.patch
+600 files/etc/wireguard/wg0.conf.makeimg.template
+644 files/home/conrad/.bash_profile
+644 files/home/conrad/.bashrc
+644 files/home/conrad/.inputrc
+644 files/home/conrad/.ssh/authorized_keys
+644 files/root/.ssh/authorized_keys
+600 files/root/mdb.makeimg.template
+660 files/var/lib/knot/anemos.io.zone.makeimg.template
+660 files/var/lib/knot/bitfehler.com.zone.makeimg.template
+660 files/var/lib/knot/bitfehler.net.zone.makeimg.template
+660 files/var/lib/knot/bitfehler.org.zone.makeimg.template
+640 files/var/lib/knot/keys/keys/92af24eece7f8570f712dac98f2f80911266452c.pem.makeimg.template
A => IMGBUILD +153 -0
@@ 1,153 @@
+# The name of this image. Mostly cosmetic, e.g. for output file naming.
+imgname=bfy
+
+# Build an Alpine Linux image
+target=alpine
+
+# The image format to generate. See also the man page for options.
+# Generate raw image with msdos partition table and a single partition
+#format="raw 4G msdos ext4"
+# Generate xz-compressed tarball
+#format="tar xz"
+# Generate a directory
+#format="dir"
+# Custom: the IMGBUILD has to implement setup() and cleanup()
+#format="custom"
+format="custom"
+
+# Specify config items to be copied over from the host building the image.
+#
+# Add 'keyring' to install the host's `/etc/apk/keys` on the image. Note that
+# apk will always copy the keys used to bootstrap the sytem.
+# Add 'mirrorlist' to install the host's `/etc/apk/repositories` file.
+# Otherwise the repositories file must be installed manually via files or in
+# the provision script.
+#
+# Default is to not use anything from the host.
+# hostconf=""
+hostconf=""
+
+# The packages to install
+packages="
+ alpine-base
+ bash
+ coreutils
+ curl
+ doas
+ e2fsprogs
+ ifupdown-ng
+ knot
+ knot-resolver
+ lmdb-tools
+ linux-virt
+ openssh
+ syslinux
+ tzdata
+ util-linux
+ wireguard-tools
+ zstd
+"
+
+setup() {
+ # Repartition, in case the disk das been reset to a vendor image
+ parted -s -- /dev/vda mklabel msdos \
+ mkpart primary 2048s 256MiB \
+ mkpart primary 256MiB -1s \
+ set 1 boot on
+ partprobe /dev/vda
+ # wait for hotplug events to settle...
+ sleep 1 && mdev -sf
+ uuidr=$(uuidgen)
+ uuidb=$(uuidgen)
+ mkfs.ext2 -q -F -U "$uuidb" /dev/vda1
+ mkfs.ext4 -q -F -U "$uuidr" /dev/vda2
+ mount /dev/vda2 "${imgroot}"
+ mkdir "${imgroot}/boot"
+ mount /dev/vda1 "${imgroot}/boot"
+ mkdir "${imgroot}/etc"
+ opts=$(findmnt -no OPTIONS /dev/vda2)
+ printf "UUID=%s\t/\t%s\t%s\t0 1\n" "${uuidr}" "ext4" "${opts}" > "${imgroot}/etc/fstab"
+ # Keep b
+ opts=$(findmnt -no OPTIONS /dev/vda1)
+ printf "UUID=%s\t/boot\t%s\t%s\t0 2\n" "${uuidb}" "ext2" "${opts},noauto" >> "${imgroot}/etc/fstab"
+}
+
+cleanup() {
+ umount "${imgroot}/boot"
+ umount "${imgroot}"
+}
+
+# The provisioning function. It is executed in the context of the new image.
+# Files have been copied, patches have been applied, templates have been
+# rendered (see the folders in this directory and the makeimg man page).
+provision() {
+ ln -sf "/etc/zoneinfo/UTC" /etc/localtime
+ echo 'root:$6$HeNIeePBsBYda6jt$ete/lsPvVjmR.S8R1Bu/PEMZFMSP5eD.Nc0YNkKPADKdmw2FIuDqnyLo39vm079VZER1ErYObophKXJJv.b7j1' | chpasswd -e
+
+ adduser -g conrad -s /bin/bash -D conrad
+ addgroup conrad wheel
+ echo 'conrad:$6$3KiaTcELvHqntx8E$uEqAGdUQzTwrVR7/319QgJsbCmZSwjLPF2yUOw2FqWWuoYzs/o8pXXfjzqo/cyfXfLowCmzPsaC7gviYrlGhI/' | chpasswd -e
+ # This is needed because the files copied here are owned by root
+ chown -R conrad:conrad /home/conrad
+
+ # Set up Knot MDB
+ mdb_load /var/lib/knot/keys < /root/mdb
+ rm /root/mdb
+ chown -R knot:knot /var/lib/knot/
+
+ # Set up bootloader.
+ uuid=$(lsblk -rno UUID /dev/vda2)
+ sed -e "s|^root=|root=/dev/disk/by-uuid/${uuid}|" -i /etc/update-extlinux.conf
+ # This would enable the serial port:
+ #sed -e 's|^default_kernel_opts=quiet|default_kernel_opts="quiet console=tty0 console=ttyS0,115200"|' -i /etc/update-extlinux.conf
+ #sed -e "s|^serial_port=|serial_port=0|" -i /etc/update-extlinux.conf
+ dd bs=440 count=1 conv=notrunc if=/usr/share/syslinux/mbr.bin of="${BLKDEV}"
+ extlinux --install /boot
+ update-extlinux -v
+}
+
+# Performed last as services may have been installed via custom files/commands
+#
+# ALPINE: for Alpine (open-rc) services, the special syntax
+# `<SERVICE>:<RUNLEVEL>` is supported. If the runlevel part is omitted, the
+# default runlevel will be used.
+services="
+ devfs:sysinit
+ dmesg:sysinit
+ mdev:sysinit
+ hwdrivers:sysinit
+ modules:boot
+ hwclock:boot
+ sysctl:boot
+ bootmisc:boot
+ networking:boot
+ hostname:boot
+ seedrng:boot
+ syslog:boot
+ loadkmap:boot
+ acpid
+ crond
+ knotd
+ kresd
+ sshd
+"
+
+# Custom stuff
+case "$BF_HOST" in
+x)
+ hostname="x"
+ host_ipv4="81.171.24.121"
+ host_ipv6="2001:1af8:4700:a129:a::23"
+ host_ipv6_gw="2001:1af8:4700:a129::1"
+ ;;
+y)
+ hostname="y"
+ host_ipv4="185.17.144.15"
+ host_ipv6="2a00:c98:2200:af09:a::23"
+ host_ipv6_gw="2a00:c98:2200:af09::1"
+ ;;
+*)
+ printf "BF_HOST must be 'x' or 'y' (is '%s')!\n" "$BF_HOST"
+ exit 1
+ ;;
+esac
A => Makefile +49 -0
@@ 1,49 @@
+# This Makefile does not _build_ the IMGBUILD, it provides the targets to
+# deploy this IMGBUILD to my VPS using Anemos.
+
+# There is two almost identical hosts, x.bitfehler.net and y.bitfehler.net
+# This must be set to determine which one to deploy ('x' or 'y').
+ifndef BF_HOST
+$(error BF_HOST is not set)
+endif
+
+# Use this after re-imaging so my ssh config won't interfere
+IP_x=81.171.24.121
+IP_y=185.17.144.15
+INIT_SSH_OPTS=-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
+INIT_SSH_TO=root@$(IP_$(BF_HOST))
+
+default: payload.tar.gz
+
+# This file is sourced by Anemos and will set the required env var.
+anemos.env:
+ test "$(BF_HOST)" = "x" || test "$(BF_HOST)" = "y"
+ echo "BF_HOST=$(BF_HOST)" > $@
+
+# Create the Anemos payload: a zipped tarball of the IMGBUILD including the
+# revealed secrets.
+payload.tar.gz: anemos.env
+ makeimg -R anemos-secrets
+ tar czf $@ IMGBUILD anemos.env files anemos-secrets keys repositories
+ rm -rf anemos-secrets anemos.env
+
+# Used after reprovisioning the server with a Leaseweb Debian image
+init: payload.tar.gz
+ scp $(INIT_SSH_OPTS) payload.tar.gz anemos_init.conf $(INIT_SSH_TO):
+ rm payload.tar.gz
+ ssh $(INIT_SSH_OPTS) $(INIT_SSH_TO) env DEBIAN_FRONTEND=noninteractive apt-get -q -y install zstd kexec-tools
+ ssh $(INIT_SSH_OPTS) $(INIT_SSH_TO) wget https://git.sr.ht/~bitfehler/anemos-cli/blob/master/anemos
+ ssh $(INIT_SSH_OPTS) $(INIT_SSH_TO) chmod +x anemos
+ ssh $(INIT_SSH_OPTS) $(INIT_SSH_TO) ./anemos -c anemos_init.conf
+
+# Used for a regular redeploy (i.e. server already running Alpine, ssh set up)
+deploy: payload.tar.gz
+ scp payload.tar.gz anemos.conf $(BF_HOST):
+ rm payload.tar.gz
+ # Replace this with an installed version at some point
+ ssh $(BF_HOST) wget https://git.sr.ht/~bitfehler/anemos-cli/blob/master/anemos
+ ssh $(BF_HOST) chmod +x anemos
+ ssh $(BF_HOST) doas mount /boot
+ ssh $(BF_HOST) doas ./anemos -c anemos.conf
+
+.PHONY: default init anemos.env payload.tar.gz
A => README.md +75 -0
@@ 1,75 @@
+# bitfehler.net DNS infrastructure
+
+This repository contains the full code (minus the secrets) used to deploy
+`x.bitfehler.net` and `y.bitfehler.net`, the authoritative name servers for
+bitfehler.net, anemos.io, and a few other zones.
+
+All aspects of the systems are described in code in the form of a
+[makeimg][makeimg] _IMGBUILD_. [Anemos][anemos] is used for deployment.
+Besides the obvious utility of this repository its main purpose is to serve as
+a demo for these projects.
+
+[makeimg]: https://sr.ht/~bitfehler/makeimg
+[anemos]: https://sr.ht/~bitfehler/anemos
+
+## How it is being used
+
+A server is redeployed by running e.g. `make BF_HOST=y deploy`. This assumes it
+is already running the system as described in this repo.
+
+If one of the servers has to be remotely re-imaged (e.g. because something
+broke beyond repair) or a new server is brought in, using the `init` target
+instead of `deploy` can achieve the same thing off of a stock Leaseweb Debian
+image (they do not offer Alpine).
+
+## How it works
+
+In rough terms, this is what happens:
+
+* `makeimg` is used to reveal all used secrets - these secrets are only
+ accessible on my laptop and need to be shipped somehow.
+* A tarball is prepared containing the entire _IMGBUILD_ (i.e. the `IMGBUILD`
+ file plus additional input files), an Anemos env file, and the secrets
+* The tarball and an appropriate Anemos config are sent to the server
+* Anemos is "installed" on the server (downloaded, as there are no packages
+ yet)
+* Anemos is executed on the server
+
+The execution of Anemos will lead to the following events:
+
+* Anemos prepares a special initramfs, based on the Anemos base image but
+ including the prepared tarball (the payload in Anemos terms)
+* Anemos reboots the server into the prepared initramfs
+* The initramfs executes `makeimg`, bootstrapping a system exactly as described
+ in the _IMGBUILD_
+* The server is rebooted one more time, booting into the newly deployed system
+
+## What is notable about this?
+
+### Entire system defined in code
+
+The system description includes low-level details like disk partitioning, file
+systems, and boot loader setup. These things can be changed because the deploy
+is performed by an initramfs.
+
+### Secrets
+
+In this case, the secrets are resolved on the workstation triggering the deploy
+and then transferred to the server with the _IMGBUILD_. In larger environments
+that feature network-based secrets management systems, this step could be
+performed on the host itself.
+
+### Network usage
+
+A deployment requires relatively little bandwidth for the client triggering it.
+Only the _IMGBUILD_ definition has to transferred to the server. All the
+packages are then pulled from the server, which presumably has a decent
+connection.
+
+### Shit can blow up
+
+It might be obvious, but still worth pointing out: this method of deployment
+provides ample opportunity to render a system unbootable. You should not
+attempt this on systems unless you have some means to restore an unbootable
+system, e.g. physical access, recovery systems, or vendor-supplied remote
+re-imaging.
A => anemos.conf +63 -0
@@ 1,63 @@
+#!/hint/sh
+#
+# Anemos config to use after the server was re-imaged with a Leasweb Debian
+
+# Kernel and base initramfs
+#
+# The URL is fetched with curl(1). Can be e.g. "http://", "file://", etc.
+ANEMOS_INITRAMFS_URL="https://anemos.io/initramfs/master/initramfs-anemos"
+ANEMOS_KERNEL_URL="https://anemos.io/initramfs/master/vmlinuz-anemos"
+
+# Network configuration for the initramfs
+#
+# Must be a valid Alpine network configuration, see
+# https://wiki.alpinelinux.org/wiki/Configure_Networking#Interface_Configuration
+# Debian-style (interfaces.d/*, etc) is not supported.
+# Default if not specified: dhcp on eth0
+#ANEMOS_NETWORK_URL="file:///etc/network/interfaces"
+
+# The payload describing the deployment.
+#
+# Currently only .tar.gz is supported. Can contain either an IMGBUILD or a
+# custom script/executable called `deploy` along with other files needed.
+# See e.g. https://git.sr.ht/~bitfehler/anemos-demo-payload
+ANEMOS_PAYLOAD_URL="file:///home/conrad/payload.tar.gz"
+
+# How to execute the initramfs. Must be either "destructive" or "kexec".
+# Destructive means overwriting the system's kernel and initramfs, then
+# performing a regular reboot. For kexec, see kexec(8).
+#
+# NOTE: Alpine does not support kexec unless you have taken specific measures
+# to enable it.
+ANEMOS_EXEC="destructive"
+
+# If ANEMOS_EXEC is set to "destructive":
+#
+# Autodetection is planned, but for now the kernel and initramfs to be
+# overwritten have to be specified.
+#
+# This _should_ work for Arch Linux:
+#ANEMOS_OVERWRITE_KERNEL="/boot/vmlinuz-virt"
+#ANEMOS_OVERWRITE_INITRAMFS="/boot/initramfs-virt"
+#
+# This _should_ work on a reasonably standard Debian:
+#ANEMOS_OVERWRITE_KERNEL="$(cat /proc/cmdline | tr ' ' '\n' | grep BOOT_IMAGE= | cut -c 12-)"
+#ANEMOS_OVERWRITE_INITRAMFS="$(echo "${ANEMOS_OVERWRITE_KERNEL}" | sed -e s/vmlinuz/initrd.img/)"
+#
+# And this _should_ work on a reasonably standard Alpine:
+ANEMOS_OVERWRITE_KERNEL="/boot/$(cat /proc/cmdline | tr ' ' '\n' | grep BOOT_IMAGE= | cut -c 12-)"
+ANEMOS_OVERWRITE_INITRAMFS="$(echo "${ANEMOS_OVERWRITE_KERNEL}" | sed -e s/vmlinuz/initramfs/)"
+
+# If ANEMOS_EXEC is set to "kexec":
+#
+# Autodetection is planned, but for now the reboot command has to be specified.
+#
+# Arch/Debian:
+ANEMOS_KEXEC_REBOOT_CMD="systemctl kexec"
+#
+# Alpine:
+#ANEMOS_KEXEC_REBOOT_CMD="rc shutdown && kexec -e"
+#
+# The default is to use "--reuse-cmdline" but for advanced use cases this can
+# be overridden, e.g. with "--append=" or "--command-line="
+#ANEMOS_KEXEC_LOAD_ARGS="--append='console=ttyS0,115200'"
A => anemos_init.conf +63 -0
@@ 1,63 @@
+#!/hint/sh
+#
+# Anemos config to use after the server was re-imaged with a Leasweb Debian
+
+# Kernel and base initramfs
+#
+# The URL is fetched with curl(1). Can be e.g. "http://", "file://", etc.
+ANEMOS_INITRAMFS_URL="https://anemos.io/initramfs/master/initramfs-anemos"
+ANEMOS_KERNEL_URL="https://anemos.io/initramfs/master/vmlinuz-anemos"
+
+# Network configuration for the initramfs
+#
+# Must be a valid Alpine network configuration, see
+# https://wiki.alpinelinux.org/wiki/Configure_Networking#Interface_Configuration
+# Debian-style (interfaces.d/*, etc) is not supported.
+# Default if not specified: dhcp on eth0
+#ANEMOS_NETWORK_URL="file:///etc/network/interfaces"
+
+# The payload describing the deployment.
+#
+# Currently only .tar.gz is supported. Can contain either an IMGBUILD or a
+# custom script/executable called `deploy` along with other files needed.
+# See e.g. https://git.sr.ht/~bitfehler/anemos-demo-payload
+ANEMOS_PAYLOAD_URL="file:///root/payload.tar.gz"
+
+# How to execute the initramfs. Must be either "destructive" or "kexec".
+# Destructive means overwriting the system's kernel and initramfs, then
+# performing a regular reboot. For kexec, see kexec(8).
+#
+# NOTE: Alpine does not support kexec unless you have taken specific measures
+# to enable it.
+ANEMOS_EXEC="kexec"
+
+# If ANEMOS_EXEC is set to "destructive":
+#
+# Autodetection is planned, but for now the kernel and initramfs to be
+# overwritten have to be specified.
+#
+# This _should_ work for Arch Linux:
+#ANEMOS_OVERWRITE_KERNEL="/boot/vmlinuz-virt"
+#ANEMOS_OVERWRITE_INITRAMFS="/boot/initramfs-virt"
+#
+# This _should_ work on a reasonably standard Debian:
+#ANEMOS_OVERWRITE_KERNEL="$(cat /proc/cmdline | tr ' ' '\n' | grep BOOT_IMAGE= | cut -c 12-)"
+#ANEMOS_OVERWRITE_INITRAMFS="$(echo "${ANEMOS_OVERWRITE_KERNEL}" | sed -e s/vmlinuz/initrd.img/)"
+#
+# And this _should_ work on a reasonably standard Alpine:
+#ANEMOS_OVERWRITE_KERNEL="$(cat /proc/cmdline | tr ' ' '\n' | grep BOOT_IMAGE= | cut -c 12-)"
+#ANEMOS_OVERWRITE_INITRAMFS="$(echo "${ANEMOS_OVERWRITE_KERNEL}" | sed -e s/vmlinuz/initramfs/)"
+
+# If ANEMOS_EXEC is set to "kexec":
+#
+# Autodetection is planned, but for now the reboot command has to be specified.
+#
+# Arch/Debian:
+ANEMOS_KEXEC_REBOOT_CMD="systemctl kexec"
+#
+# Alpine:
+#ANEMOS_KEXEC_REBOOT_CMD="rc shutdown && kexec -e"
+#
+# The default is to use "--reuse-cmdline" but for advanced use cases this can
+# be overridden, e.g. with "--append=" or "--command-line="
+#ANEMOS_KEXEC_LOAD_ARGS="--append='console=ttyS0,115200'"
A => files/etc/apk/repositories +2 -0
@@ 1,2 @@
+http://dl-cdn.alpinelinux.org/alpine/v3.17/main
+http://dl-cdn.alpinelinux.org/alpine/v3.17/community
A => files/etc/conf.d/sshd.makeimg.patch +11 -0
@@ 1,11 @@
+--- sshd.orig 2023-04-05 22:13:23.438079225 +0200
++++ sshd.new 2023-04-05 22:14:10.514127969 +0200
+@@ -13,7 +13,7 @@
+ #
+ # Example: "ed25519 rsa".
+ #
+-#key_types_to_generate=""
++key_types_to_generate="ed25519"
+
+ # The number of bits to use for a generated ECDSA SSH host key.
+ # Defaults to 256 bits if not set.
A => files/etc/doas.d/doas.conf +2 -0
@@ 1,2 @@
+permit nopass :wheel
+permit nopass root
A => files/etc/hostname.makeimg.template +1 -0
A => files/etc/inittab.makeimg.patch +11 -0
@@ 1,11 @@
+--- inittab.orig 2022-09-05 21:53:04.021100286 +0200
++++ inittab 2022-09-05 21:52:46.877847668 +0200
+@@ -13,7 +13,7 @@
+ tty6::respawn:/sbin/getty 38400 tty6
+
+ # Put a getty on the serial port
+-#ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100
++ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100
+
+ # Stuff to do for the 3-finger salute
+ ::ctrlaltdel:/sbin/reboot
A => files/etc/knot-resolver/kresd.conf +17 -0
@@ 1,17 @@
+-- SPDX-License-Identifier: CC0-1.0
+-- vim:syntax=lua:set ts=4 sw=4:
+-- Refer to manual: https://knot-resolver.readthedocs.org/en/stable/
+
+-- Network interface configuration
+-- Only listen on the internal VPN address
+net.listen('10.8.1.1', 53, { kind = 'dns', freebind = true })
+
+-- Load useful modules
+modules = {
+ 'hints > iterate', -- Allow loading /etc/hosts or custom root hints
+ 'stats', -- Track internal statistics
+ 'predict', -- Prefetch expiring/frequent records
+}
+
+-- Cache size
+cache.size = 100 * MB
A => files/etc/knot/knot.conf.makeimg.template +34 -0
@@ 1,34 @@
+# Knot DNS configuration file for bitfehler.net.
+# See knot.conf(5) or refer to the server documentation.
+
+server:
+ user: knot:knot
+ listen: [ ${host_ipv4}@53, ${host_ipv6}@53 ]
+
+log:
+ - target: /var/log/knotd.log
+ any: info
+
+policy:
+ - id: manual
+ manual: on
+ single-type-signing: on
+
+mod-stats:
+ - id: default
+ edns-presence: on
+ query-type: on
+
+template:
+ - id: default
+ storage: "/var/lib/knot"
+ file: "%s.zone"
+ module: mod-stats/default
+
+zone:
+ - domain: bitfehler.net
+ - domain: bitfehler.org
+ - domain: bitfehler.com
+ - domain: anemos.io
+ dnssec-signing: on
+ dnssec-policy: manual
A => files/etc/motd.makeimg.template +4 -0
@@ 1,4 @@
+Welcome to bitfehler!
+
+Build date: $(date -Idate)
+Build state: $(makeimg -S build_state)
A => files/etc/network/interfaces.makeimg.template +22 -0
@@ 1,22 @@
+auto lo
+iface lo inet loopback
+
+auto eth0
+iface eth0 inet dhcp
+iface eth0 inet6 static
+ address ${host_ipv6}/64
+ gateway ${host_ipv6_gw}
+ pre-up echo 0 > /proc/sys/net/ipv6/conf/eth0/accept_ra
+
+auto wg0
+iface wg0 inet static
+ requires eth0
+ use wireguard
+ address 10.8.1.1/24
+ pre-up echo 1 > /proc/sys/net/ipv4/ip_forward
+ post-up iptables -A FORWARD -o eth0 -i wg0 -m conntrack --ctstate NEW -j ACCEPT
+ post-up iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
+ post-up iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
+ pre-down iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
+ pre-down iptables -D FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
+ pre-down iptables -D FORWARD -o eth0 -i wg0 -m conntrack --ctstate NEW -j ACCEPT
A => files/etc/ssh/sshd_config.makeimg.patch +29 -0
@@ 1,29 @@
+--- sshd_config.orig 2023-04-05 22:21:22.637752112 +0200
++++ sshd_config.new 2023-04-05 22:23:00.584183987 +0200
+@@ -10,7 +10,7 @@
+ # possible, but leave them commented. Uncommented options override the
+ # default value.
+
+-#Port 22
++Port 23022
+ #AddressFamily any
+ #ListenAddress 0.0.0.0
+ #ListenAddress ::
+@@ -29,7 +29,7 @@
+ # Authentication:
+
+ #LoginGraceTime 2m
+-#PermitRootLogin prohibit-password
++PermitRootLogin no
+ #StrictModes yes
+ #MaxAuthTries 6
+ #MaxSessions 10
+@@ -54,7 +54,7 @@
+ #IgnoreRhosts yes
+
+ # To disable tunneled clear text passwords, change to no here!
+-#PasswordAuthentication yes
++PasswordAuthentication no
+ #PermitEmptyPasswords no
+
+ # Change to no to disable s/key passwords
A => files/etc/wireguard/wg0.conf.makeimg.template +11 -0
@@ 1,11 @@
+[Interface]
+ListenPort = 51820
+PrivateKey = $(makeimg -S +wg_server_key)
+
+[Peer]
+PublicKey = 62s+XKUXqbZFGlbmpEWia5NdaXNU4XvXBdi4sUmmnyo=
+AllowedIPs = 10.8.1.2/32
+
+[Peer]
+PublicKey = YY+5eg9nm0Eg3jRA3ePNjsviQ3kSuN8Qzhbr1qYrlUA=
+AllowedIPs = 10.8.1.3/32
A => files/home/conrad/.bash_profile +5 -0
@@ 1,5 @@
+#
+# ~/.bash_profile
+#
+
+[[ -f ~/.bashrc ]] && . ~/.bashrc
A => files/home/conrad/.bashrc +21 -0
@@ 1,21 @@
+#
+# ~/.bashrc
+#
+
+# If not running interactively, don't do anything
+[[ $- != *i* ]] && return
+
+export HISTCONTROL="ignoreboth:erasedups"
+export HISTSIZE=10000
+export HISTFILESIZE=200000
+shopt -s histappend
+export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
+
+alias ls='ls --color=auto'
+alias gcd='cd "$(git rev-parse --show-toplevel)"'
+alias crl='curl -Ss -D - -o /dev/null'
+
+PS1="\[\e[0;32m\]\u\[\e[0m\]@\[\e[0;32m\]\h\[\e[m\] \[\e[1;34m\]\w\[\e[m\] \$(if [[ \$? == 0 ]]; then echo \"\[\033[0;32m\]\"; else echo \"\[\033[0;31m\]\"; fi)\\$\[\033[00m\]\[\e[1;37m\]\[\e[0m\] "
+
+export PATH="$PATH:/home/conrad/.local/bin"
+export EDITOR=vi
A => files/home/conrad/.inputrc +4 -0
@@ 1,4 @@
+"\e[Z": menu-complete
+"\e[A": history-search-backward
+"\e[B": history-search-forward
+"\C-e": forward-search-history
A => files/home/conrad/.ssh/authorized_keys +1 -0
@@ 1,1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK0G3N+8UOKOhCmFt9n4K3/T2OqsV1ucapPe1Qkdl04P
A => files/root/.ssh/authorized_keys +1 -0
@@ 1,1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK0G3N+8UOKOhCmFt9n4K3/T2OqsV1ucapPe1Qkdl04P
A => files/root/mdb.makeimg.template +1 -0
@@ 1,1 @@
+$(makeimg -S +knot_mdb)
A => files/var/lib/knot/anemos.io.zone.makeimg.template +13 -0
@@ 1,13 @@
+\$TTL 86400
+@ IN SOA x.bitfehler.net. hostmaster (
+ $(makeimg -S dns_zone_serial) ; serial
+ 14400 ; refresh
+ 1800 ; retry
+ 604800 ; expire
+ 86400 ) ; minimum
+anemos.io. 86400 SOA x.bitfehler.net. hostmaster.anemos.io. 2023000047 14400 1800 604800 86400
+anemos.io. 300 A 213.239.215.47
+anemos.io. 14400 NS x.bitfehler.net.
+anemos.io. 14400 NS y.bitfehler.net.
+anemos.io. 300 AAAA 2a01:4f8:a0:84cb:b64:0:178:178
+anemos.io. 14400 CAA 0 issue "letsencrypt.org"
A => files/var/lib/knot/bitfehler.com.zone.makeimg.template +16 -0
@@ 1,16 @@
+\$TTL 86400
+@ IN SOA x.bitfehler.net. hostmaster (
+ $(makeimg -S dns_zone_serial) ; serial
+ 14400 ; refresh
+ 1800 ; retry
+ 604800 ; expire
+ 86400 ) ; minimum
+@ 300 IN A 213.239.215.47
+@ 300 IN AAAA 2a01:4f8:a0:84cb:b64:0:178:178
+@ 14400 IN CAA 0 issue "letsencrypt.org"
+@ 14400 IN NS x.bitfehler.com.
+@ 14400 IN NS y.bitfehler.com.
+x 14400 IN A 81.171.24.121
+x 14400 IN AAAA 2001:1af8:4700:a129:a::23
+y 14400 IN A 185.17.144.15
+y 14400 IN AAAA 2a00:c98:2200:af09:a::23
A => files/var/lib/knot/bitfehler.net.zone.makeimg.template +28 -0
@@ 1,28 @@
+\$TTL 86400
+@ IN SOA x.bitfehler.net. hostmaster (
+ $(makeimg -S dns_zone_serial) ; serial
+ 14400 ; refresh
+ 1800 ; retry
+ 604800 ; expire
+ 86400 ) ; minimum
+@ 14400 IN A 213.239.215.47
+@ 14400 IN AAAA 2a01:4f8:a0:84cb:b64:0:178:178
+@ 14400 IN CAA 0 issue "letsencrypt.org"
+@ 14400 IN MX 10 mx.bitfehler.net.
+@ 14400 IN NS x.bitfehler.net.
+@ 14400 IN NS y.bitfehler.net.
+@ 14400 IN TXT "v=spf1 mx ip4:138.201.162.180/32 ip4:213.239.215.46/32 ip6:2a01:4f8:251:94f:0:74:180:0/112 ip6:2a01:4f8:a0:84cb:b64:0:180:0/112 -all"
+_dmarc 14400 IN TXT "v=DMARC1; p=quarantine; ruf=mailto:dmarc-feedback@bitfehler.net"
+default._domainkey 14400 IN TXT "v=DKIM1; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqnKRYE4BAB84MFdDmlSK6IiocLGrGH38Tg5kZgyhPi1Nl7eGgxKq0o/uqF0l2RwW/Xh5jdpwSI45kYGXGmU/akVAE9EiKz2mDkjyZp5msiAQXdiRE6pu1sdzi3/gRjMCLM8MezE3A1V/FojVK3121JuEh3yRS1udHGlNVICsiwyZ9v40WAMVOj3gHDAAcX0QhXEQiH2+2yrT7FO+sP9UJTaPNgODvnk4en08VXbawp6igquqJcWyLgHBAm98lcgRnOSY9Jg4c9z9vxGRW5VjMwgyafvfgrMu9cV5gE+aL20iuoUxdsK1Qo9e8J36dudu7pFHC53nCIBc0JTDC8z/3QIDAQAB"
+_mta-sts 14400 IN TXT "v=STSv1; id=202204260001;"
+mta-sts 14400 IN A 213.239.215.47
+mta-sts 14400 IN AAAA 2a01:4f8:a0:84cb:b64:0:178:178
+mx 14400 IN A 213.239.215.46
+mx 14400 IN AAAA 2a01:4f8:a0:84cb:b64:0:180:180
+apk 14400 IN CNAME bitfehler.net.
+ntfy 14400 IN CNAME bitfehler.net.
+www 14400 IN A 213.239.215.47
+x 14400 IN A 81.171.24.121
+x 14400 IN AAAA 2001:1af8:4700:a129:a::23
+y 14400 IN A 185.17.144.15
+y 14400 IN AAAA 2a00:c98:2200:af09:a::23
A => files/var/lib/knot/bitfehler.org.zone.makeimg.template +16 -0
@@ 1,16 @@
+\$TTL 86400
+@ IN SOA x.bitfehler.net. hostmaster (
+ $(makeimg -S dns_zone_serial) ; serial
+ 14400 ; refresh
+ 1800 ; retry
+ 604800 ; expire
+ 86400 ) ; minimum
+@ 300 IN A 213.239.215.47
+@ 300 IN AAAA 2a01:4f8:a0:84cb:b64:0:178:178
+@ 14400 IN CAA 0 issue "letsencrypt.org"
+@ 14400 IN NS x.bitfehler.org.
+@ 14400 IN NS y.bitfehler.org.
+x 14400 IN A 81.171.24.121
+x 14400 IN AAAA 2001:1af8:4700:a129:a::23
+y 14400 IN A 185.17.144.15
+y 14400 IN AAAA 2a00:c98:2200:af09:a::23
A => files/var/lib/knot/keys/keys/92af24eece7f8570f712dac98f2f80911266452c.pem.makeimg.template +1 -0
@@ 1,1 @@
+$(makeimg -S +knot_key_92af24e)
A => keys/alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub +9 -0
@@ 1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1yHJxQgsHQREclQu4Ohe
+qxTxd1tHcNnvnQTu/UrTky8wWvgXT+jpveroeWWnzmsYlDI93eLI2ORakxb3gA2O
+Q0Ry4ws8vhaxLQGC74uQR5+/yYrLuTKydFzuPaS1dK19qJPXB8GMdmFOijnXX4SA
+jixuHLe1WW7kZVtjL7nufvpXkWBGjsfrvskdNA/5MfxAeBbqPgaq0QMEfxMAn6/R
+L5kNepi/Vr4S39Xvf2DzWkTLEK8pcnjNkt9/aafhWqFVW7m3HCAII6h/qlQNQKSo
+GuH34Q8GsFG30izUENV9avY7hSLq7nggsvknlNBZtFUcmGoQrtx3FmyYsIC8/R+B
+ywIDAQAB
+-----END PUBLIC KEY-----
A => keys/alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub +9 -0
@@ 1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwlzMkl7b5PBdfMzGdCT0
+cGloRr5xGgVmsdq5EtJvFkFAiN8Ac9MCFy/vAFmS8/7ZaGOXoCDWbYVLTLOO2qtX
+yHRl+7fJVh2N6qrDDFPmdgCi8NaE+3rITWXGrrQ1spJ0B6HIzTDNEjRKnD4xyg4j
+g01FMcJTU6E+V2JBY45CKN9dWr1JDM/nei/Pf0byBJlMp/mSSfjodykmz4Oe13xB
+Ca1WTwgFykKYthoLGYrmo+LKIGpMoeEbY1kuUe04UiDe47l6Oggwnl+8XD1MeRWY
+sWgj8sF4dTcSfCMavK4zHRFFQbGp/YFJ/Ww6U9lA3Vq0wyEI6MCMQnoSMFwrbgZw
+wwIDAQAB
+-----END PUBLIC KEY-----
A => keys/alpine-devel@lists.alpinelinux.org-6165ee59.rsa.pub +14 -0
@@ 1,14 @@
+-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAutQkua2CAig4VFSJ7v54
+ALyu/J1WB3oni7qwCZD3veURw7HxpNAj9hR+S5N/pNeZgubQvJWyaPuQDm7PTs1+
+tFGiYNfAsiibX6Rv0wci3M+z2XEVAeR9Vzg6v4qoofDyoTbovn2LztaNEjTkB+oK
+tlvpNhg1zhou0jDVYFniEXvzjckxswHVb8cT0OMTKHALyLPrPOJzVtM9C1ew2Nnc
+3848xLiApMu3NBk0JqfcS3Bo5Y2b1FRVBvdt+2gFoKZix1MnZdAEZ8xQzL/a0YS5
+Hd0wj5+EEKHfOd3A75uPa/WQmA+o0cBFfrzm69QDcSJSwGpzWrD1ScH3AK8nWvoj
+v7e9gukK/9yl1b4fQQ00vttwJPSgm9EnfPHLAtgXkRloI27H6/PuLoNvSAMQwuCD
+hQRlyGLPBETKkHeodfLoULjhDi1K2gKJTMhtbnUcAA7nEphkMhPWkBpgFdrH+5z4
+Lxy+3ek0cqcI7K68EtrffU8jtUj9LFTUC8dERaIBs7NgQ/LfDbDfGh9g6qVj1hZl
+k9aaIPTm/xsi8v3u+0qaq7KzIBc9s59JOoA8TlpOaYdVgSQhHHLBaahOuAigH+VI
+isbC9vmqsThF2QdDtQt37keuqoda2E6sL7PUvIyVXDRfwX7uMDjlzTxHTymvq2Ck
+htBqojBnThmjJQFgZXocHG8CAwEAAQ==
+-----END PUBLIC KEY-----
A => repositories +1 -0
@@ 1,1 @@
+files/etc/apk/repositories<
\ No newline at end of file
A => secrets/+knot_key_92af24e +1 -0
@@ 1,1 @@
+pass show bitfehler/dns/keys/92af24eece7f8570f712dac98f2f80911266452c.pem
A => secrets/+knot_mdb +1 -0
@@ 1,1 @@
+pass show bitfehler/dns/mdb
A => secrets/+wg_server_key +1 -0
@@ 1,1 @@
+pass show bitfehler/wireguard/server.key
A => secrets/build_state +3 -0
@@ 1,3 @@
+# Not really a secret, but needs to be run before the IMGBUILD
+# is packed up into a tarball for deployment
+echo "$(git rev-list HEAD --count)-$(git rev-parse --short HEAD)"
A => secrets/dns_zone_serial +6 -0
@@ 1,6 @@
+# Not really a secret, but needs to be run before the IMGBUILD
+# is packed up into a tarball for deployment
+serial_date=$(git log --format="%cd" --date="format:%Y%m%d" -1 -- files/var/lib/knot)
+commit_date=$(git log --format="%cd" --date="format:%Y-%m-%d" -1 -- files/var/lib/knot)
+count=$(git log --after="$commit_date 00:00" --oneline -- files/var/lib/knot | wc -l)
+printf "%s%02d" "$serial_date" "$count"