Post

Building FreeBSD OVH VPS

This is based on 2016-11-06 Tim Chase blog page Installing FreeBSD on OVH. The method below is not using bsdinstall, but instead is based on bootstraping FreeBSD ZFS image from running system with make install(kernel,world,distribution). So it assumes that your FreeBSD world is rebuilt and ready to be deployed from /usr/src and /usr/obj. I use this method to update my FreeBSD systems.

Prepare OVH VPS

I will target 4€/month OVH Starter VPS, which comes with 20G disk. So, start by installing Linux OS from OVH VPS Dashboard, I tested Debian and CentOS, does not really matter, we will overwrite it with FreeBSD ZFS image. When installation done, reboot VPS in recovery mode. OVH will send you an email with ssh access details, IP and password. Log-in, and type lsblk, there should be a block device sdb of size 20G. This is our dd output target.

Local VPS configuration

I will prepare few local configuration files and store them in /root/ovh, they will go into the image file later on the next step.

/etc/localtime - copy this from my running system.

/etc/rc.conf

1
2
3
4
5
6
hostname=ovh-vps.uoga.net
zfs_enable="YES"
ifconfig_vtnet0=DHCP
dumpdev="AUTO"
ntpd_enable="YES"
sshd_enable="YES"

/etc/ssh/sshd_config - add following to the end :

1
2
3
4
5
6
7
8
9
10
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes

PrintMotd no
VersionAddendum AIX
X11Forwarding no

Bootstrap user account with SSH keys

go2.sh - shell script to create user account with wheel membership and SSH access keys, also prep /usr/local/etc/doas.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/sh

make_user() {
  NAME=$1
  ID=$2
  KEY=$3
  
  OUT=`pw usershow $NAME 2>/dev/null`
  if [ $? != 0 ]; then
    echo "creating user $NAME"
    pw groupadd -n $NAME -g $ID
    pw useradd  -n $NAME -u $ID -m -w no -M 750 -G wheel
  fi
  # always init .ssh dir and authkeys, even when user exists
  mkdir -p /home/$NAME/.ssh
  chmod 700 /home/$NAME/.ssh
  chown -R $NAME:$NAME /home/$NAME/.ssh
  printf "$KEY" > /home/$NAME/.ssh/authorized_keys
}

prep_envi() {
  mkdir -p /usr/local/etc
  echo "
# Permit members of the wheel group to perform actions as root.
permit :wheel

permit nopass user1 as root
" >/usr/local/etc/doas.conf
  chmod 600 /usr/local/etc/doas.conf
}

set "user1" "10001" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDrlq+MKiQxeiPQFaX2jXLtoRnbuWDveVg0uvuoCkFgZ key1@host1\nssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGxgZjma6sFSNb/u1YlaeiIiNnmUSgb8UA1NKj9w2e9l key2@host2\n"

make_user "$@"
prep_envi

Build ZFS image

I don’t have any other memory disks, so I know mdconfig will create md0 , otherwise double-check this.

The script will prompt to set initial root password, and then will create user account with SSH access keys with /root/go2.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/sh
mort() {
  echo "mort.." && exit
}

truncate -s 20G /root/ovh.img || mort
mdconfig -f /root/ovh.img -u 0  || mort
gpart create -s gpt md0  || mort
gpart add -t freebsd-boot -s 512K -i 1 md0  || mort
gpart add -t freebsd-swap -s 1G -i 2 md0  || mort
gpart add -t freebsd-zfs -i 3 md0  || mort
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 md0  || mort
export ZFSBOOT_POOL_NAME=rpoolovh
zpool create -R /mnt -O canmount=off -O mountpoint=/ -O atime=off -O compression=on ${ZFSBOOT_POOL_NAME} md0p3  || mort
zfs create -o mountpoint=none ${ZFSBOOT_POOL_NAME}/ROOT  || mort
zfs create -o mountpoint=/ ${ZFSBOOT_POOL_NAME}/ROOT/default  || mort
zpool set bootfs=${ZFSBOOT_POOL_NAME}/ROOT/default ${ZFSBOOT_POOL_NAME}  || mort
zfs create ${ZFSBOOT_POOL_NAME}/home  || mort
zfs create -o canmount=off ${ZFSBOOT_POOL_NAME}/usr  || mort
zfs create ${ZFSBOOT_POOL_NAME}/usr/obj  || mort
zfs create ${ZFSBOOT_POOL_NAME}/usr/src  || mort
zfs create ${ZFSBOOT_POOL_NAME}/jail  || mort
zfs create -o canmount=off ${ZFSBOOT_POOL_NAME}/var  || mort
zfs create ${ZFSBOOT_POOL_NAME}/var/log  || mort
zfs create ${ZFSBOOT_POOL_NAME}/var/tmp  || mort
zfs create ${ZFSBOOT_POOL_NAME}/tmp  || mort
cd /usr/src  || mort
make installkernel DESTDIR=/mnt  || mort
make installworld DESTDIR=/mnt  || mort
make distribution DESTDIR=/mnt  || mort
echo "/dev/da0p2 none swap sw 0 0" >/mnt/etc/fstab
echo "nameserver 213.186.33.99" >/mnt/etc/resolv.conf
cd /root/ovh || mort
cp localtime rc.conf /mnt/etc
cp sshd_config /mnt/etc/ssh
cp /root/ovh/go2.sh /mnt/root/go2.sh  || mort
chroot /mnt passwd
chroot /mnt /root/go2.sh
zpool export ${ZFSBOOT_POOL_NAME}
mdconfig -d -u 0
gzip --keep /root/ovh.img

Use the IP from OVH recovery mail, and pass to send and restore VPS image via SSH :

1
ssh root@X.X.X.X "gunzip | dd of=/dev/sdb bs=1M" </root/ovh.img.gz

Reboot VPS, and login via SSH with your user keys installed from /root/go2.sh.

To later reimport pool and temporarily mount it on /mnt :

1
mdconfig -f /root/ovh.img -u 0 && zpool import -R /mnt $ZFSBOOT_POOL_NAME