For my NAS, I've been using a homebrew Gentoo install maintained in a virtual machine, which is then regularly imaged to a rotating pair of thumbdrives.

I've done a number of things to make this a bit more convenient, which I realized I hadn't written up.

nas.target

This one I did write-up before, but I mention it briefly here because it's important to the more resent steps.

In short, systemd replaces the legacy init concept of "runlevels" with "targets". There are some well-known runlevels that map to traditional concepts, such as "single", "multi-user" and "graphical".

For this setup, I've added nas.target, and configured systemd to make that the default target on boot.

This allows me to segregate all the services relevant to running as a NAS "for real" on the network from the very minimal set I need to maintain packages (really, just sshd).

virtual boot overrides

In my simple theme for machines, my firewall is 'fire', the wifi is 'air', my personal machine is 'water', and the NAS is 'earth'.

To avoid conflicts in local dns, when I start the virtual copy of earth for maintenance, I rename its hostname to 'terra'.

For a few years, my process for starting the vm was the following:

  • launch vm
  • jump into grub
  • 'e'dit the entry boot options
  • add 'single' to the linux kernel command line
  • wait for single-user prompt
  • root password
  • echo terra > /proc/sys/kernel/hostname
  • systemctl isolate multi-user
  • wait for sshd launch
  • ssh in for maintenance in my normal terminal

This was always a pain in the ass.

ConditionVirtualization=true hostname setting

I've very lazily learned how to write systemd units, and while solving some other problem, I became aware of the Condition* … uh … conditions.

This led to /etc/systemd/system/terra-hostname.service:


[Unit]
Description=Set the "earth-ng" hostname to "terra" when running virtualized
ConditionVirtualization=true

[Install]
WantedBy=sysinit.target

[Service]
Type=oneshot
ExecStart=/root/bin/set-terra-hostname

Life was suitably improved; now I only needed to edit the grub kernel command line.

I'm not sure when it happened, and I think it was actually quite recently, but at some point systemd-unit became a kernel command line option. So now all I needed to do is edit the command line to add systemd.unit=multi-user.target, and off it goes. Unless I misspell systemd, which I regularly do.

Ideally, I would find a way within systemd maybe with ConditionVirtualization to dynamically target multi-user rather than nas, and I wouldn't need to do anything. But, until then…

For every identified kernel, grub-mkconfig already creates two entries: the normal boot and a 'recovery' entry with the 'single' option added … why can't it just add a third entry per.

grub

Looking at /etc/grub.d/10_linux, it's pretty obvious where the change should be:


  # in linux_entry:

  if [ x$type != xsimple ] ; then
      case $type in
      recovery)
          title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;;
+         multi_user)
+             title="$(gettext_printf "%s, with Linux %s (multi-user.target)" "${os}" "${version}")" ;;
      *)
          title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;

  # in the main function:

  linux_entry "${OS}" "${version}" advanced \
              "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+ linux_entry "${OS}" "${version}" multi_user \
+             "${GRUB_CMDLINE_LINUX} systemd.unit=multi-user.target ${GRUB_CMDLINE_LINUX_DEFAULT}"
  if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
    linux_entry "${OS}" "${version}" recovery \
                "single ${GRUB_CMDLINE_LINUX}"
  fi


Published

Category

Posts

Tags

Contact