Diskless
Posted
So, recently, I wanted to start dual-booting Windows and Linux. I mainly use Windows for playing vidya. All coding is remote through an SSH client. I wanted a better local testing solution than spinning up a VM in VirtualBox…
But, everyone knows that trying to install Linux alongside Windows is a horrible idea. Most times, installing Linux after Windows will manage to clobber the Windows bootloader and give you many, many issues (source: experience). How can we solve this?
I’ve heard “oh just run Linux in a VM, it will work fine!” > Nope. Not gonna happen. Been there already.
So I had a neat thought. I’ve got a NAS (WD EX2). I’ve got a pfSense router that serves DNS. The EX2 supports iSCSI, NFS, etc… pfSense has a TFTP package and some advance DHCP options…. I’m sure you see where this is going…
So, I decided to build a “diskless” Linux environment that I can netboot via PXE and run on my tower without touching my local disks. I’m going to document this a little bit to help other people get this stuff together, because it was a tedious process.
Here’s a brief overview of the process:
- Set pfSense for TFTP and PXE
- Build an iSCSI target on the NAS
- Set up the iPXE configuration suite
- Partition the iSCSI target in a way that allows GRUB to work properly
- Mount the iSCSI target on a “bootstrapping” machine (I chose Debian | requires
open-iscsi
) - Mount the new root partition and set up your OS of choice (easiest option is to
debootstrap
the chroot) - Install necessary packages on the chroot (
debootstrap
takes care of base-system, seetasksel
,grub
,initramfs-tools
) - Install a DM/DE/whatever (
tasksel
, again) - Set up your
/etc/
:fstab
,mtab
,initiatorname.iscsi
,default/grub
,network/interfaces
- Set up kernel modules:
/etc/modules
,/etc/initramfs-tools/modules
- Generate your GRUB config and update your
initrd
- Unmount the chroot, logout of the iSCSI session
- Test and boot!
So, here’s the “long” version:
Setting up pfSense for TFTP and PXE.
This step should be swift and relatively “easy”, as pfSense’s UI is pretty fabulous and straight-forward.
First, install the System Patches
and TFTPd
packages from the pfSense package manager.
Set up the TFTPd
package to serve on the LAN and upload your iPXE undionly.kpxe
can be generated here (with the UNDI only
/ kpxe
output option).
Next, we need to patch the DHCPd to classify users for iPXE. We want to make sure the boot agent doesn’t go into a recursive fetch loop, which will happen without the DHCP PXE agent classification.
DHCPd Patch (via System -> Patches
):
--- dhcpd.conf 2016-01-20 16:25:28.000000000 -0600
+++ dhcpd.conf.override 2016-01-20 16:25:12.000000000 -0600
@@ -24,6 +24,8 @@
option tftp-server-name "10.0.1.1";
next-server 10.0.1.1;
+
+ include "/etc/pxe-class.conf";
}
host s_lan_0 {
--- /dev/null 2016-01-20 16:26:26.000000000 -0600
+++ pxe-class.conf 2016-01-16 16:54:38.000000000 -0600
@@ -0,0 +1,5 @@
+if exists user-class and option user-class = "iPXE" {
+ filename "tftp://10.0.1.1/default.ipxe";
+} else {
+ filename "undionly.kpxe";
+}
--- /dev/null 2016-01-20 16:26:26.000000000 -0600
+++ /usr/local/etc/rc.d/dhcpoverride.sh 2016-01-16 16:35:03.000000000 -0600
@@ -0,0 +1,5 @@
+#!/usr/local/bin/bash
+
+killall -3 dhcpd
+cp -vf /var/dhcpd/etc/dhcpd.conf.override /var/dhcpd/etc/dhcpd.conf
+/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot /var/dhcpd -cf /etc/dhcpd.conf -pf /var/run/dhcpd.pid re0
NOTE: You may need to modify the TFTP server location to point to your router. The DHCPd configuration patch may need to be modified to insert the
pxe-class.conf
into thedhcpd.conf
properly.
Next, you’ll want to patch the TFTPd to work properly.
TFTP Patch (via System -> Patches
):
--- /usr/local/pkg/tftp.inc 2016-01-16 12:48:29.000000000 -0600
+++ /usr/local/pkg/tftp.inc 2016-01-16 10:53:39.000000000 -0600
@@ -88,7 +88,7 @@
// Add tftpd daemon to inetd
$inetd_fd = fopen("/var/etc/inetd.conf", "a+");
- fwrite($inetd_fd, "tftp\t\tdgram\tudp\twait\t\troot\t/usr/libexec/tftpd\ttftpd /tftpboot\n");
+ fwrite($inetd_fd, "tftp\t\tdgram\tudp\twait\t\troot\t/usr/libexec/tftpd\ttftpd -w -s /tftpboot -u nobody -l -d DEBUG_SIMPLE|DEBUG_ACCESS /\n");
fclose($inetd_fd);
if (!empty($config['installedpackages']['tftpd']['config'][0]['tftpdinterface'])) {
NOTE: Make sure auto-apply is enabled on both of these patches, as pfSense will regenerate the configurations on service restart and system reboot.
Build an iSCSI target on the NAS.
Simple, handled through the EX2 web UI. Differs based on your NAS model. The lower-end WD MyCloud NAS devices do not have iSCSI support, but they may have NFS support which may also work. Depends on OS support and NFS quirks.
Setting up the iPXE configuration suite.
This part is relatively simple. First, you’ll need to generate an UNDI-only iPXE image, which you can generate here through the Standard page.
Place that in your TFTP server root and point your DHCP server’s next-server
and network boot settings here. Your network boot settings should look like this:
Next, in your TFTP root, create a default.ipxe
with the following contents:
#!ipxe
# Global variables used by all other iPXE scripts
chain boot.ipxe.cfg ||
# Boot <boot-url>/<boot-dir>/hostname-<hostname>.ipxe
# if hostname DHCP variable is set and script is present
isset ${hostname} && chain ${boot-dir}hostname-${hostname}.ipxe ||
# Boot <boot-url>/<boot-dir>/uuid-<UUID>.ipxe
# if SMBIOS UUID variable is set and script is present
isset ${uuid} && chain ${boot-dir}uuid-${uuid}.ipxe ||
# Boot <boot-url>/<boot-dir>/mac-010203040506.ipxe if script is present
chain ${boot-dir}mac-${mac:hexraw}.ipxe ||
# Boot <boot-url>/<boot-dir>/pci-8086100e.ipxe if one type of
# PCI Intel adapter is present and script is present
chain ${boot-dir}pci-${pci/${busloc}.0.2}${pci/${busloc}.2.2}.ipxe ||
# Boot <boot-url>/<boot-dir>/chip-82541pi.ipxe if one type of
# PCI Intel adapter is present and script is present
chain ${boot-dir}chip-${chip}.ipxe ||
# Boot <boot-url>/menu.ipxe script if all other options have been exhausted
chain ${menu-url} ||
As well as a boot.cfg.ipxe
like this, but modified to your liking:
#!ipxe
# OPTIONAL: NFS server used for menu files and other things
# Must be specified as IP, as some distros don't do proper name resolution
set nfs-server 10.0.1.14
set nfs-root /nfs/boot
# OPTIONAL: Base URL used to resolve most other resources
# Should always end with a slash
#set boot-url nfs://${nfs-server}${nfs-root}
set boot-url tftp://10.0.1.1/
# OPTIONAL: What URL to use when sanbooting
# Usually ${boot-url} is used, but required until NFS supports block device API
# Should always end with a slash
set sanboot-url http://10.0.1.14/
# OPTIONAL: Relative directory to boot.ipxe used to
# override boot script for specific clients
set boot-dir boot/
# REQUIRED: Absolute URL to the menu script, used by boot.ipxe
# and commonly used at the end of simple override scripts
# in ${boot-dir}.
set menu-url ${boot-url}menu.ipxe
# OPTIONAL: iSCSI server location and iSCSI IQNs
# Must be specified as an IP, some clients have issues with name resolution
# Initiator IQN is also calculated to use hostname, if present
set iscsi-server 10.0.1.14
set base-iqn iqn.2013-03.com.wdc
set base-iscsi iscsi:${iscsi-server}::::${base-iqn}
isset ${hostname} && set initiator-iqn ${base-iqn}:${hostname} || set initiator-iqn ${base-iqn}:${mac}
Follow that up with a menu.ipxe
:
#!ipxe
# Variables are specified in boot.ipxe.cfg
# Some menu defaults
set menu-timeout 5000
set submenu-timeout ${menu-timeout}
isset ${menu-default} || set menu-default exit
# Figure out if client is 64-bit capable
cpuid --ext 29 && set arch x64 || set arch x86
cpuid --ext 29 && set archl amd64 || set archl i386
###################### MAIN MENU ####################################
:start
menu iPXE boot menu for ${initiator-iqn}
item --gap -- ------------------------- Operating systems ------------------------------
item --key t testenv Boot testing environment from iSCSI
item --key l menu-live Live environments...
item --gap -- ------------------------- Tools and utilities ----------------------------
item --key b netboot-xyz Chain to boot.netboot.xyz
item --gap -- ------------------------- Advanced options -------------------------------
item --key c config Configure settings
item shell Drop to iPXE shell
item reboot Reboot computer
item
item --key x exit Exit iPXE and continue BIOS boot
choose --timeout ${menu-timeout} --default ${menu-default} selected || goto cancel
set menu-timeout 0
goto ${selected}
:cancel
echo You cancelled the menu, dropping you to a shell
:shell
echo Type 'exit' to get the back to the menu
shell
set menu-timeout 0
set submenu-timeout 0
goto start
:failed
echo Booting failed, dropping to shell
goto shell
:reboot
reboot
:exit
exit
:config
config
goto start
:back
set submenu-timeout 0
clear submenu-default
goto start
############ MAIN MENU ITEMS ############
:testenv
echo Booting testing environment from iSCSI for ${initiator-iqn}
set root-path ${base-iscsi}:cloud:linbox
sanboot ${root-path} || goto failed
goto start
:netboot-xyz
echo Booting to boot.netboot.xyz...
chain http://boot.netboot.xyz
Your PXE setup is mostly done! Make sure you change the boot.cfg.ipxe
to reflect your environment setup. Same goes for the menu items in menu.ipxe
.
Partitioning & bootstrapping the iSCSI Target.
Now we’re getting into the funner steps as we get closer to the finish line. We’ll start with partitioning first, as it seems to be the logical first step.
First, make sure you’ve got open-iscsi
installed on your bootstrapper machine. Obviously, this differs between package managers, but it should be something similar.
Start by making sure your LUN is configured and exposed properly by your NAS:
# iscsiadm -m discovery -t sendtargets -p 10.0.1.14
10.0.1.14:3260,1 iqn.2013-03.com.wdc:cloud:linbox
If you see your LUN listed like the above, you’re going in the right direction. Next, open a session with the iSCSI portal:
# iscsiadm -m node -T 'iqn.2013-03.com.wdc:cloud:linbox' -p 10.0.1.14 -l
Logging in to [iface: default, target: iqn.2013-03.com.wdc:cloud:linbox, portal: 10.0.1.14,3260] (multiple)
Login to [iface: default, target: iqn.2013-03.com.wdc:cloud:linbox, portal: 10.0.1.14,3260] successful.
Now that we’re logged in to the LUN, your system will be able to pick up the disk. dmesg
will show output like the following (just without the sdc* partitions and most likely, a different drive letter):
[508455.879000] scsi12 : iSCSI Initiator over TCP/IP
[508456.140857] scsi 12:0:0:0: Direct-Access WD FILEIO 4.0 PQ: 0 ANSI: 5
[508456.141503] sd 12:0:0:0: Attached scsi generic sg2 type 0
[508456.142478] sd 12:0:0:0: [sdc] 250000001 512-byte logical blocks: (128 GB/119 GiB)
[508456.145915] sd 12:0:0:0: [sdc] Write Protect is off
[508456.145927] sd 12:0:0:0: [sdc] Mode Sense: 3b 00 10 00
[508456.147142] sd 12:0:0:0: [sdc] Write cache: enabled, read cache: enabled, supports DPO and FUA
[508456.196057] sdc: sdc1 sdc2 sdc3 sdc4
[508456.201907] sd 12:0:0:0: [sdc] Attached SCSI disk
Start partitioning! I chose to partition the main disk with btrfs
because I like the snapshotting and other advanced capabilities it has. I attempted to follow the “typical” Linux partitioning style, although it may not be completely necessary. Start by opening gdisk
on your iSCSI disk:
# gdisk /dev/sdc
GPT fdisk (gdisk) version 0.8.8
Type device filename, or press <Enter> to exit: /dev/sdc
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Command (? for help):
Your partition table scan may look a little different, but we’ll fix that real quick. Type o
into the gdisk
prompt to create a new GPT and give it confirmation that you want to burn away what’s not on your iSCSI LUN:
Command (? for help): o
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): y
Now, your partition table scan will look remarkably similar to the above! Start by adding a BIOS boot partition. You don’t need a particularly large BIOS boot partition, just enough space for GRUB to store all of its data.
Command (? for help): n
Partition number (1-128, default 1):
First sector (34-14680030, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-14680030, default = 14680030) or {+-}size{KMGTP}: +64K
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): ef02
Changed type of partition to 'BIOS boot partition'
If you’ve got space to spare and want a separate /boot
partition, we’d set that up now. Remember, you’ll need space to store some configs and kernel updates, so it should be a little bit bigger than the BIOS boot partition. 1G should be enough, but I recommend going a little bigger in case you have extra space handy.
Command (? for help): n
Partition number (2-128, default 2):
First sector (34-14680030, default = 4096) or {+-}size{KMGTP}:
Last sector (4096-14680030, default = 14680030) or {+-}size{KMGTP}: +1G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'
Next, we’ll be creating the main root filesystem. It’s a lot like the /boot
partition setup, but we’ll be doing some extra stuff to it afterwards.
Command (? for help): n
Partition number (3-128, default 3):
First sector (34-67108830, default = 2101248) or {+-}size{KMGTP}:
Last sector (2101248-67108830, default = 67108830) or {+-}size{KMGTP}: -4G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'
Next is swap, which is optional but recommended.
Command (? for help): n
Partition number (4-128, default 4):
First sector (34-67108830, default = 58720256) or {+-}size{KMGTP}:
Last sector (58720256-67108830, default = 67108830) or {+-}size{KMGTP}:
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8200
Changed type of partition to 'Linux swap'
Now, review our partitioning scheme and write it if everything looks good.
Command (? for help): p
Disk /dev/sdc: 67108864 sectors, 32.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 7E16CC34-B216-4A70-AA02-A873C1805A5A
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 67108830
Partitions will be aligned on 2048-sector boundaries
Total free space is 3967 sectors (1.9 MiB)
Number Start (sector) End (sector) Size Code Name
1 2048 2175 64.0 KiB EF02 BIOS boot partition
2 4096 2101247 1024.0 MiB 8300 Linux filesystem
3 2101248 58720222 27.0 GiB 8300 Linux filesystem
4 58720256 67108830 4.0 GiB 8200 Linux swap
Command (? for help): w
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!
Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sdc.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.
The operation has completed successfully.
And we’re done partitioning! Now all you should need to do is issue the following commands and we’ll be in business:
# sync
# partprobe /dev/sdc
### Verify with:
# ls -la /dev/sdc*
brw-rw---- 1 root disk 8, 32 Jan 24 16:54 /dev/sdc # Raw disk device
brw-rw---- 1 root disk 8, 33 Jan 24 16:50 /dev/sdc1 # BIOS boot
brw-rw---- 1 root disk 8, 34 Jan 24 16:50 /dev/sdc2 # /boot
brw-rw---- 1 root disk 8, 35 Jan 24 16:50 /dev/sdc3 # /
brw-rw---- 1 root disk 8, 36 Jan 24 16:50 /dev/sdc4 # swap
Now, we need to actually create the filesystems on the disk. We don’t need to touch sdc1
as GRUB will handle that.
# mkfs.ext4 /dev/sdc2
mke2fs 1.42.9 (4-Feb-2014)
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
65536 inodes, 262144 blocks
13107 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=268435456
8 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
# mkfs.btrfs /dev/sdc3 # OR, use `mkfs.ext4` if you're not feeling risky.
WARNING! - Btrfs v3.12 IS EXPERIMENTAL
WARNING! - see http://btrfs.wiki.kernel.org before using
Performing full device TRIM (27.00GiB) ...
Turning ON incompat feature 'extref': increased hardlink limit per file to 65536
fs created label (null) on /dev/loop0p3
nodesize 16384 leafsize 16384 sectorsize 4096 size 27.00GiB
Btrfs v3.12
# mkswap /dev/sdc4
Setting up swapspace version 1, size = 4194280 KiB
no label, UUID=de3863e9-9926-4ebb-8d2c-b4c987efa8ee
Setting up your OS on the Chroot.
Filesystems are up and going! Now, let’s do our mounts and debootstrap
the system. I used Debian Testing/Stretch because I like to be on the bleeding edge, but feel free to use jessie
or wheezy
instead if you want a more stable experience.
# cd /mnt
# mkdir chroot
# mount /dev/sdc3 chroot
# debootstrap testing chroot
I: Keyring file not available at /usr/share/keyrings/debian-archive-keyring.gpg; switching to https mirror https://mirrors.kernel.org/debian
I: Retrieving Release
I: Retrieving Packages
--- snip ---
I: Base system installed successfully.
### Set up the chroot
# cd chroot
# mount /dev/sdc2 boot
# mount -t proc none proc
# mount -t sysfs none sys
# mount --bind /dev dev
# chroot . /bin/bash
### Install some extra packages
# apt-get install -y locales tasksel open-iscsi initramfs-tools grub2 vim-nox openssh-server
### Reconfigure timezone and locales
# dpkg-reconfigure tzdata
# dpkg-reconfigure locales
NOTE: Make sure that you install GRUB to the correct disk… For example, our LUN’s block device,
/dev/sdc
.
Configuring your OS.
There’s a bit of setup that has to go in to configuring the OS for disless boot. Obviously, I’m going to use Debian here as the example since that is what I’m running.
NOTE: This needs to be done before you can boot your OS for the first time.
Set up your mtab
:
# cp /proc/mounts /etc/mtab
# sed -i '\|^/dev/sdc3|,$!d' /etc/mtab
NOTE: Remember to replace
sdc3
with your partition node, if it is different..
Set up fstab
:
# blkid /dev/sdc{2,3,4}
/dev/sdc2: UUID="70f7d8de-68de-4b25-9f9d-d57348be6c12" TYPE="ext4" PARTLABEL="Linux filesystem" PARTUUID="e608b54d-0985-4879-984f-4ce879dcf930"
/dev/sdc3: UUID="042e69f8-b0d6-410d-8f1d-febcd584dde3" UUID_SUB="a444d825-5969-4bba-9f42-db2ed21f4f8b" TYPE="btrfs" PARTLABEL="Linux filesystem" PARTUUID="cc434614-f42d-4cc7-833b-59660ef7f7aa"
/dev/sdc4: UUID="9970794d-0a2c-4c0e-9d8b-0fcd3c33234f" TYPE="swap" PARTLABEL="Linux swap" PARTUUID="4dae3e79-c371-4c89-b9da-63bca1cb1663"
# echo "UUID=042e69f8-b0d6-410d-8f1d-febcd584dde3 / btrfs defaults,_netdev 0 1" >> /etc/fstab
# echo "UUID=70f7d8de-68de-4b25-9f9d-d57348be6c12 /boot ext4 defaults,_netdev 0 1" >> /etc/fstab
# echo "UUID=9970794d-0a2c-4c0e-9d8b-0fcd3c33234f none swap sw,_netdev 0 0" >> /etc/fstab
# cat fstab
UUID=042e69f8-b0d6-410d-8f1d-febcd584dde3 / btrfs defaults,_netdev 0 1
UUID=70f7d8de-68de-4b25-9f9d-d57348be6c12 /boot ext4 defaults,_netdev 0 1
UUID=9970794d-0a2c-4c0e-9d8b-0fcd3c33234f none swap sw,_netdev 0 0
Set up the iSCSI initiator:
# echo "InitiatorName=iqn.2016-01.com.maiome.roaming:client" > /etc/iscsi/initiatorname.iscsi
Change the following in your /etc/default/grub
:
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="root=UUID=042e69f8-b0d6-410d-8f1d-febcd584dde3 ip=dhcp ipby=dhcp" # Set root to your / UUID!
GRUB_GFXMODE=1920x1080 # Set to your native screen resolution.
NOTE: Debian Sid adds support for consistent network device naming. I had issues with this for some reason. It can be disabled with
biosdevname=0
andnet.ifnames=0
. If you have one interface, you shouldn’t have problems with device name allocation. For Docker and Radeon, I’ve also got these kernel boot options:cgroup_enable=memory swapaccount=1 radeon.dpm=1
.
Configure your iSCSI target options (/etc/iscsi/iscsi.initramfs
):
ISCSI_INITIATOR=iqn.2016-01.com.maiome.roaming:client
ISCSI_TARGET_NAME=iqn.2013-03.com.wdc:cloud:linbox
ISCSI_TARGET_IP=10.0.1.14
ISCSI_TARGET_PORT=3260
# ISCSI_TARGET_GROUP
# ISCSI_USERNAME
# ISCSI_PASSWORD
# ISCSI_IN_USERNAME
# ISCSI_IN_PASSWORD
Do some research on your hardware and make sure the drivers you need get loaded on boot via /etc/modules
and /etc/initramfs-tools/modules
. In my case, both my modules
files look like this:
alx
drm
radeon modeset=1
libiscsi
libiscsi_tcp
iscsi_tcp
scsi_transport_iscsi
Configure the initramfs-tools
(/etc/initramfs-tools/initramfs.conf
):
#
# initramfs.conf
# Configuration file for mkinitramfs(8). See initramfs.conf(5).
#
# Note that configuration options from this file can be overridden
# by config files in the /etc/initramfs-tools/conf.d directory.
#
# MODULES: [ most | netboot | dep | list ]
#
# most - Add most filesystem and all harddrive drivers.
#
# dep - Try and guess which modules to load.
#
# netboot - Add the base modules, network modules, but skip block devices.
#
# list - Only include modules from the 'additional modules' list
#
MODULES=most
#
# BUSYBOX: [ y | n ]
#
# Use busybox if available.
#
BUSYBOX=y
#
# KEYMAP: [ y | n ]
#
# Load a keymap during the initramfs stage.
#
KEYMAP=n
#
# COMPRESS: [ gzip | bzip2 | lzma | lzop | xz ]
#
COMPRESS=gzip
#
# NFS Section of the config.
#
#
# DEVICE: ...
#
# Specify a specific network interface, like eth0
# Overridden by optional ip= bootarg
#
DEVICE=eth1 # Set this to your boot interface!
#
# NFSROOT: [ auto | HOST:MOUNT ]
#
NFSROOT=auto
Configure your network interfaces (/etc/network/interfaces
):
# interfaces(5) file used by ifup(8) and ifdown(8)
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
auto eth0
iface eth0 inet manual
auto eth1
iface eth1 inet manual
NOTE: Make sure your boot interface is set to manual in your network interfaces config. Otherwise, this will blow things up.
Now, update your initrd and grub!
# update-initramfs -u
# update-grub
Next steps…
Your “diskless” system should be ready to boot now. Unmount the chroot from your “helper” machine and give it a shot.
NOTE: If you have problems unmounting the chroot, make sure nothing is still running within the chroot. If necessary, force your helper system to “lazy unmount” the chroot:
umount -lfv /mnt/chroot/{proc,dev,sys,}
To complete your install, remember that you should set up your graphics drivers for X11 (xserver-xorg-video-intel
, xserver-xorg-video-radeon
, xserver-xorg-video-nouveau
, etc). That process is left as an exercise for the reader.
For troubleshooting, check some of the references (or Google) below.
References
These resources were instrumental in getting this setup built. I simply took bits and pieces of this information and compiled it all in one place to make things easier.
Edits
2/6/16 - Added some modules to both lists, moved ISCSI params out of /etc/default/grub
.
8/21/16 - With the newest updates to pfSense (2.3.x+), the TFTP package is no longer maintained and is gone from the package repository. It also seems that restarting the DHCP service from the web panel rewrites the DHCP config, making the pxe-class
patch worthless. It seems that the better solution would be to configure a TFTP server on a Raspberry Pi with the same iPXE scripts and use Rom-o-Matic to build a KPXE build with an embedded script which chains the default.ipxe
from the TFTP server. Here is an example config. Good luck!
5/1/17 - A while back, I created a Docker image (pirogoeth/rpi-tftpd-hpa) to provide a TFTP server on a RPi. This is what I use now instead of the old pfSense TFTP package. It has been very stable, at least in my usage.