Guide: cURL in an initramfs environment (with HTTPS and DNS)
I recently found myself wishing to be able to remotely unlock my LUKS partitions on (re)boot. The Arch Linux wiki has some information on this, but this was not sufficient for my case, as my network assigns dynamic IP addresses, which I normally push to my DIY DDNS server using a cURL script. Therefore, it became necessary to be able to use cURL during in the initramfs/early userspace environment.
Deploying cURL
Create /etc/initcpio/hooks/hookname (where hookname is the name of your new hook where curl will be used) with the following contents:
run_hook () {
# Your code using curl here, e.g.
curl --insecure https://192.168.0.10/example/blahblah
}
cURL has difficulty with CA certificates in this environment, so we pass --insecure
to disable checking of CA certificates for now. Note also that cURL has difficulty resolving domain names, so we use the IP address for now.
Next, create /etc/initcpio/install/hookname with the following contents:
build ()
{
add_runscript
add_binary curl
}
help ()
{
echo Example hook using cURL
}
Finally, edit /etc/mkinitcpio.conf and add hookname to HOOKS in an appropriate place (for example, after netconf dropbear
but before encryptssh
).
Entropy and random number generation
As things are, this will result in cURL hanging for a considerable period of time on boot, as there is no entropy available for random number generation. Keyboard-mashing and mouse-movement can alleviate this problem, but this is obviously not possible remotely.
We can solve this by adding random.trust_cpu=on
to the Linux kernel parameters. For example, using GRUB, edit /etc/default/grub and add random.trust_cpu=on
to GRUB_CMDLINE_LINUX (that's on, not true!).
CA certificates
In order to allow cURL to check CA certificates, we need to include /etc/ssl/certs. As files here symlink into /etc/ca-certificates, we need to include that too. In /etc/initcpio/install/hookname, at the end of build
add:
add_full_dir /etc/ssl/certs
add_full_dir /etc/ca-certificates # /etc/ssl/certs files symlink into here
We can now omit --insecure
from the cURL command.
DNS lookups
To allow cURL to resolve domain names, we need to include libnss_{dns,files}.so. In /etc/initcpio/install/hookname, at the end of build
add:
for i in /usr/lib/libnss_dns* /usr/lib/libnss_files*; do
add_file $i
done
We also need to manually generate an /etc/resolv.conf file, as this is not done for us. In /etc/initcpio/hooks/hookname, before the cURL call add:
# Generate resolv.conf
source /tmp/net-eth0.conf
echo nameserver $IPV4DNS0 > /etc/resolv.conf
echo nameserver $IPV4DNS1 >> /etc/resolv.conf
Replace eth0
with the (kernel) name of your network device. We can now use domain names in the cURL command.
Applying our changes
Now run:
sudo mkinitcpio -p linux
sudo grub-mkconfig -o /boot/grub/grub.cfg
We are now complete, and can reboot the system to see our script in action!