Artisanal Filesystem Hacking With systemd
A service I started running some instances of a while ago is RIPE Atlas, a distributed dns/ping/traceroute probing tool run by RIPE. It is pretty easy to deploy - they provide an apt repository, that has a package in it
that installs an apt config that gives you access to the packages. Once it's installed, it produces an SSH public key
that you paste into a web page and away it goes.
It is however not super flexible to operate. One thing I wanted to do was configure it to use an external
resolver instead of the local
unbound instance I have that is full of weird config hax for my internal network. As far as I
could tell there's no config option anywhere for this and I really wanted to avoid editing any of the files in
the package. Once again, systemd saves the day - just put the resolver config in /etc/ripe-atlas/resolv.conf and a drop-in file in /etc/systemd/system/ripe-atlas.service.d/dns.conf:
[Service]
BindReadOnlyPaths=/etc/ripe-atlas/resolv.conf:/etc/resolv.conf
et voila. Once again a thing I would probably not have bothered to do in the pre-systemd era - it
is easy to add a "mount --bind" line to a sysvinit script but that would mean hacking a shell
script from a package (albeit a conffile), which is annoying going forward (telling dpkg to leave it alone) and much more annoying to automate - telling Ansible to insert a line into a
text file in roughly the right place is much more annoying than just dropping two files on disk:
- name: Deploy RIPE Atlas custom resolv.conf
ansible.builtin.template:
src: ripe-atlas-resolv.conf.j2
dest: /etc/ripe-atlas/resolv.conf
owner: root
group: root
mode: '0644'
notify:
- "RIPE Atlas : restart service"
- name: Create ripe-atlas service override directory
ansible.builtin.file:
path: /etc/systemd/system/ripe-atlas.service.d
state: directory
owner: root
group: root
mode: '0755'
- name: Deploy ripe-atlas DNS override
ansible.builtin.template:
src: ripe-atlas-dns.conf.j2
dest: /etc/systemd/system/ripe-atlas.service.d/dns.conf
owner: root
group: root
mode: '0644'
notify:
- "RIPE Atlas : daemon-reload"
- "RIPE Atlas : restart service"
Which is actually quite verbose, but is extremely straight-forward and depends on the systemd
configuration merge semantics rather than luck at automatically hacking shell scripts. I actually started
writing out an equivalent attempt using ansible.builtin.lineinfile
to edit an init script to add a mount --bind line after the header (not correctly in the start and torn down in stop since that seems way too hard), then remembered that in that
world I'd first need to write enough sh to put this service in a chroot to begin
with, so that I could customise the /etc/resolv.conf it saw.