+++ title = "My server is now a virtual machine" author = ["MichaƂ Sapka"] date = 2024-09-26T21:29:00+02:00 categories = ["blog"] draft = false weight = 2001 image_dir = "blog/images" image_max_width = 600 abstract = "Memoir from a forced migation" listening = "Steve Kirk - Thimbleweed Park (Original Soundtrack)" listening_url = "https://thimbleweedpark.bandcamp.com/album/thimbleweed-park-original-soundtrack" listening_img = "steve-kirk-thimbleweed-park.jpg" +++ The unthinkable has happened - and by that, I mean it was a matter of time, but I wasn't expecting a week. The SD card used in Raspberry Pi behind [crys.site](https://crys.site) got corrupted beyond fixing. I tried, tried (I gave it good 30 mins) and failed. Super block was borked, fixing the filesystem was impossible. But I will not let go of my FreeBSD server! _Beastie or Bust!_. I have this quite modern Synology, so why not use it? The UI is not for me, but I can set up a virtual machine there and boom - everything will be all right with the world. On the host FreeBSD all I had to do was: - enable sshd(8) - install doas(1) And add a bridge to the network, which will be used by the jails: ```shell # /etc/rc.conf cloned_interfaces="bridge0" ifconfig_bridge0="addm em0 up" kld_list="if_bridge if_epair" ``` The SD card used UFS (default image for FreeBSD on Raspberry), so I lost it. But all my data, the sites and jails were stored on external thumb drive in a ZFS pool. This made the transition incredibly fast. First, I had to create a recursive (`-r`) snapshot of the root dataset. I found naming it `fun` funny. ```shell zfs snapsot -r extdata@fin ``` And I was able to transfer all descendant datasets to to the new machine ```shell zfs send -R extdata/jail@fin | ssh 10.0.7.0 zfs recv zroot/jail ``` Oh ZFS, we don't deserve you. Then I recreated my jail.conf[^fn:1] with DHCP VNET: ```shell # STARTUP/LOGGING exec.clean; exec.start = "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; exec.consolelog = "/var/log/jail_console_${name}.log"; # PERMISSIONS allow.raw_sockets; exec.clean; mount.devfs; devfs_ruleset = 5; vnet; allow.raw_sockets = 1; host.hostname = "${name}.dune.local"; path = "/usr/local/jails/containers/${name}"; $epair = "epair${id}"; $bridge = "bridge0"; vnet.interface = "${epair}b"; exec.start += "dhclient ${epair}b"; exec.prestart = "/sbin/ifconfig ${epair} create up"; exec.prestart += "/sbin/ifconfig ${epair}a up descr jail:${name}"; exec.prestart += "/sbin/ifconfig ${bridge} addm ${epair}a up"; exec.poststop = "/sbin/ifconfig ${bridge} deletem ${epair}a"; exec.poststop += "/sbin/ifconfig ${epair}a destroy"; nginx { $id=1; } sites { $id=10; } ``` and... nothing. Nada. The jails won't start. Raspberry Pi is ARM, my VM is x86. I had to create new jails - which is a breeze thanks to, again, ZFS. Since jails are normal directories, I was able to simply copy configs to new jails. In all, this forced migration took 2 hours. And that includes downloading data. Emacs made it very easy, since I can use `tramp` with `doas` to edit remote files as root: ```shell /sshx:mms@10.0.7.0|doas:: ``` The last missing puzzle was strange change from RPI, as jail's Mac addresses started changing after each start. Luckily, BSD is a community so [meka](https://bsd.network/@meka) provided me with config to force Mac address for jail, and I've added: ```shell exec.prestart += "/sbin/ifconfig ${epair}b ether ${mac}"; ``` Truly, FreeBSD is a gift that keeps on giving. [^fn:1]: This config is a combination of what [Ruben](https://rubenerd.com/starting-with-freebsd-jails/), [FreeBSD Guides](https://docs.freebsd.org/en/books/handbook/jails/), and [FreeBSD Wiki](https://wiki.freebsd.org/Jails) has thought me. I'll need to step up and buy [Jail Mastery](https://mwl.io/nonfiction/os#fmjail) book from MWL sometime in the near future.