Raspberry Pi netboot

[post in progress]

Promise: this post will not be another rewrite of the official documentation. Here I will deal with issues you might run into but no one of these people actually did because they’re not actually using it.

The company I work for has a very simple need: display on large monitors some data on a web page with huge size fonts in full screen.

Currently we have 20 very old machines, bought as thin clients for VDI and then, when their flash disk (think of an SSD actually slower than a spinning HDD) got fried, converted to netboot via PXE. Not difficult as the CPU is an x86 VIA Eden. The PSU though are a bit custom and only last ~3 years. We bought 20 spare PSU in 2013 and another 20 in 2016;  it’s now 2019 and the PSUs for the now obsolete thin clients are out of production. Time for a change. 

The perfect solution is indeed a Raspberry Pi 3 B+ with PoE HAT – no PSU to fry, netbootable out of the box (with those pesky netboot bugs solved, such as the inability to boot from a TFTP server on a different network), no microSD to take care of, central management (being NFS rooted), small and nice.

First caveat: don’t be a cheapskate, buy the right case. The cost is >3x, but the absolute value is not that much – you can afford 17€ vs 5€.

Second issue: don’t buy a Pi 4 yet: the dramatic changes in the internal structure of the SoC make it so different that the bootstrap firmware is now on an internal 512Kb EEPROM rather than on the boot flash/TFTP server and had to be completely rewritten. However it is still (as of October 2019) lacking the netboot code. Of course you can boot just the kernel and cmdline.txt off a microSD ad NFS mount the root fs, but you’ll end up needing a microSD anyway so part of the advantages in netbooting it would be gone.

Let’s start.

Our x86 thin clients boot off initrd – actually an initramfs – which is nice since the client becomes completely independent from the network, but eats up precious runtime RAM and has size limits. So we decided to go for readonly NFS, with sensible writeable private parts overmounted on tmpfs. The backbone for the old x86 clients is based on DSL; on rPi we’re using dietPi.

Now, if you, like me, live in a structured network you might find that most “tutorials” for netbooting a rPi are nothing more than useless paraphrases of the sparse docs. The point is that you don’t and can’t have a do-it-all dnsmasq; you’ll probably have a centralized DHCP server with failover and relays, a TFTP server, an NFS server, and so on. So here’s some details about setting it all up.

Notes on setting up a NFS filesystem


Issue you’ll run into and how to solve them

DHCP on Windows

You can have a Windows DHCP server in lieu of the dnsmasq server or isc-dhcpd all tutorials suggest. This is rather frequent in the real, corporate world. Nothing really fancy to do here, you only need to set up option 66 as a string holding the IP address of the TFTP server. IP address, not hostname: the rPi bootload doesn’t have name resolving capabilities.

TFTP boot

Your TFTP server folder must hold the same content as the boot folder on your SD – that is the FAT32 partition that usually gets mounted under /boot – you can also mount it later but there’s no real need for that as the whole system will be readonly if you’re sane.

The actual files needed to boot a Pi are: bootcode.bin (except for the 4) (which can’t netboot yet anyway but whatever), start.elf, config.txt, (cmdline.txt

It seems there’s no real way to specify a boot path, ie to request files from a custom subfolder rather than from / – so to avoid me

NFS latency

If your NFS server is on a different subnet your NFS packets *will* be fragmented. Period. The default packet size is 8192 and there is no way a rPi can do jumbo frames. Handle fragmentation and your CPU usage will skyrocket. Plus your UDP packets will never go back and forth in the correct order, so retransmissions and timeouts are guaranteed. Just freaking lower the wsize and rsize values, on the kernel command line parameter nfsroot (after the path). You’ll have to modify cmdline.txt for that but I guess you already knew that. Maybe lowering the timeout could help as well, but I measured that just setting the NFS packet size to 1400 does wonders to your NFS performance.

PoE HAT fan

The fun part here is the whole devtree concept.



Avaya J129 – VoIP on the cheap

One of our sister companies decided not to jump on the Cisco UC bandwagon the rest of the group is happily using and instead went for a very cheap solution that involved an used Avaya IPoffice 500 v2 PABX and a mix of Avaya 16xx (H.323) and J129 (SIP) phones.

I will not discuss voice quality or other stuff here – my post is all about the phonebook and as usual I’m only doing it because of the scarcity of information available.

At startup the Avaya phones request their IP address via DHCP and some parameters as well; beside the classic network stuff (mask, router, etc.) and accessories (NTP, syslog…) itlooks for Options 55 and 242 which are two strings. Option 55 is a list of comma-separated number of options to request from DHCP (wicked!) and option 242 is a string with the basic L2 and L3 parameters (VLAN separation, HTTP server, et al).

Once started the J129 asks the host specified as HTTPSRVR for the J100Supgrade.txt file, which generally includes a reference to the settings file – by default J100settings.txt

Our problem, as I said, is the phonebook. Avaya 16xx phones use the H.323 protocol to manage phonebooks, while the cheap, SIP-only J129 does an HTTP request every time the “Contacts” softkey is pressed at the URL //personal_dir – where is defined in the J100settings.txt as USER_STORE_URI (the default is http://:80/user) and is a long hash (apparently) of something. The file must be an XML file with a very simple structure:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<personal_dir xmlns="http://www.avaya.com/ipoffice/personaldirectory" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.avaya.com/ipoffice/personaldirectory personal_dir.xsd">
<data_source>IPOFFICE/ build 237 x.x.x.x</data_source>
<name>Contact Name</name>
<sdial>speed dial key</sdial>


Old friends /2

Two small updates on the Amiga restoration project.

First: it seems there’s no simple way to get a flatscreen TV to display an Amiga video output in color, so I got myself an A520 modulator from eBay. Not for the modulator part, of course, but for its ability to produce color composite output.

Second: my old friend Marcello let me borrow his A500. We were hoping it was still working (he hasn’t tried turning it on since 1998) and in that case I could use it to ADFize my floppies and if the mobos are compatible to swap chips with mine as a rough component tester. Well, turns out it’s not only in almost perfect working condition (only the FDD button is missing, but it turns on and boots from floppy disks) but almost identical to mine, being a rev. 6a mobo with Big Agnus (8372A). The keyboard is slightly different (LEDs are red for power and green floppy instead of green and yellow, and the floppy is clickier than mine), but it’s definitely the same sub model, albeit produced one year before.

I’m gonna run some tests this weekend.

Old friends

Finally got my hands on my Amiga 500 that had been stored in my parents garage for the last 23 years or so.

I bought this amazing machine back on January 2 1991 from a reseller who also was a hardware engineer specializing in Amiga accessories. With it I got a Philips CMxxxx 14″ monitor with SCART input (the unbadged version of the CBM 1084S), a DB23 to SCART cable, and a NEC P20 printer. Oh, and a Hardital RAM expansion with RTC. Hardital was the name of the reseller/manufacturer, entirely run by an engineer whose pieces of hardware weren’t exactly of the highest quality, but cheap enough for a 16yo whose passion wasn’t weel seen by his parents (remember Springsteen’s “goddammit guitar” intro to “Growin’ up” in the Live 75-85 album? At my home, it was the goddammit computer. And yes, there was a goddammit guitar as well. But I digress.).

The Philips monitor blew up after a couple years and I got a Philips TV to replace it. I kept using this machine until 1994, when I inherited my first DOS machine, a 2Mb RAM, 60Mb HDD 386SX 1992 laptop that belonged to my grand-uncle, and stopped using the A500 altogether.

I did and learned many things with the A500. C. BASIC. A68k. Hacks – software and hardware. First experiments with an audio digitizer – self built, connected to parallel port, at a ridiculous sample rate, mono only – but hearing Freddie Mercury singing “We are the Champions” from a file, albeit full of jitter because of how bad I was (am) at soldering, sent shivers down my spine back in 1992. I was the guy who published the high school magazine. Published means I typed it (often with a little help from my friends), pageset with a painfully slow software using my single floppy drive, and preprinted it on Postscript files which then I transferred to DOS floppies and printed to a friend’s dad Postscript printer. Tough times.

Sometime between 1997 and 2000 I tried to power the Amiga back on to recover some data (mostly said high school magazine’s stuff) but got stuck on a color error code – can’t remember which one, might have been red/purple – some years later I managed to save the data using a Windows software and two FDU and never thought of the machine again.

After toying for some months with the idea of getting my hands on the machine again, I finally did a trip to my parents garage today and found the machine still in its original box. Disks are long gone but some manuals I still have them.

I didn’t remember I had swapped the original mouse with a Boeder aftermarket one but as soon as I saw it I remembered it was because the ball on the original one had become so slick it didn’t move the rollers anymore. Screws are missing everywhere – I did some experiments with hardware from time to time, including a funny modification on the FDU flat cable that was supposed to make some sound in case of disk writes – if I remember correctly the original circuit was for a LED but somehow I decided I could put a buzzer instead. I was young and stupid.

There’s a LOGICA board as well to supply the machine with 512Kb Kickstart (2.04 37.175, unlicensed so to speak); it has a couple jumpers to set the motherboard release and the ROM default.

Well, unsurprisingly the machine doesn’t work: it powers up but the power LED stays half-lit. I have lost the SCART cable somewhere so I can only use the composite mono output and thus can’t see the color check, but I don’t think the color really changes and this could mean a fried CPU, CIA or ROM (as the color changes are a routine in ROM). Given that the LOGICA board has a wire that should be put on the ODD CIA pin #8 this is highly possible. I only tried putting the original 1.3 ROM back in its socket removing the ROM board but since nothing has changed I should try putting the board back in changing the jumpers to force using the other kickstart.

Getting a 520 also would be good, or a way to feed color signal from the RGB port into a digital TV…

More to follow.


The thing that amazes me the most is that the box is intact.


With all its polystyrene and stuff.


Trapdoor RTC/RAM expansion removed, this is it. Notice the hack on the FDD cable and the ROM piggyboard.


Close up of the piggy board. The blue wire was supposed to go on pin 8 of the odd CIA, so that you can switch ROM by pressing both mouse keys while powering on.


Better light, worse focus.

Ugly but useful: VMware VI Perl Tools on Debian

If you need to connect Perl (ugh!) to Vsphere, with a Nagios Perl plugin for example, you’ll need the VMware VI Perl Tools SDK. It’s a .tar.gz (be sure to download the x86_64 unless you’re still on 32 bit architecture, but then you’ll have different priorities I guess). Unpack it, and, if you’re on Debian, open the vmware-install.pl file and change “ubuntu” to “debian” (don’t say anything).

Should work well. At least, it does for me, YMMV.

Publish Windows printers to DNS-SD

Problem: given a Windows server with a number of installed printers, publish them to DNS so that they can be used from macos/iOS (et al).

No free software exists AFAIK to automate this trivial but annoying task.

An AWK script can of course process a list of printers into a batch of dnscmd commands.

Usual disclaimers apply: done in 30 minutes, trivial, works with en_us versions only, and so on. I’m not liable for anything, from the script no working to destroying your AD. UAYOR, YMMV, etc.

In short: for a mac/iOS to list printer as Bonjour printers you need broadcast, mDNS or DNS-SD. Which means:

  • five PTR records that “enable” the zone for DNS-SD
  • for every printer, three records in the _printer._tcp.zone.tld subzone:
    • a PTR for the zone that says “there’s a printer with this name”
    • a SRV for the printer’s name that says “and this is its hostname”
    • a TXT for the printer’s name that explains the printer’s capabilities, queue name, and so on.

The printer can be shared as IPP, IPPS, IPP-TLS and, most important, LPD. Windows has had LPD service available since Windows 2000, on server and workstation, and thus that’s simpler than using IPP. My script, having been conceived with Windows in mind, uses LPD. Of course you need to install LPD service and the printers must have been shared. I won’t show you how to do that – it’s trivial and if you need to know how to do it you can google it – or change job altogether.

The script won’t “just work” I guess: the tricky part is the “ty” line in the TXT record, which tells the mac which driver to use. I’m just using the Windows driver’s name, YMMV but I’m positive you’ll have to edit the TXT records if you want the mac to install the printer automatically (and not asking you for the driver to use).

Full specifications on how to fill the TXT record with significant data can be found on Apple’s website. Google for “bonjour priniting specification” site:developer.apple.com


might have once again reinvented the wheel. Square. And lost my ability to properly google for stuff. So if you know of a better way to do this, free (no pesky unmantained $29 software to install on a little innocent MS DC) please come forward and tell your story.

Let’s get it on:

  1. Get the list of printers from the server:
    cscript prnmngr.vbs -l -s FQDN.domain.tld > %temp%\prtlist.txt

    (must be run from the folder where the VBS is; in 2008R2 %windir%\system32\printing_admin_scripts\xx-XX – like en-US)

  2. Process the list with AWK. IMPORTANT: if you’re not using AWK on Windows but are moving the list and the script back and forth from/to a *nix machine, you MUST take care of CR/LF conversion.
    ./prnmngr2dnscmd.awk prtlist.txt > dnssd.cmd
  3. Run the script and hope for the best.

The script itself. You need to CHANGE domain.tld with your zone FQDN. Again, I assume you’re not a dummy but a decently experienced sysadmin.

#!/usr/bin/awk -f


 split("b db dr lb t", sr);
 for (rr in sr) printf "dnscmd . /RecordAdd %s %s._dns-sd._udp PTR %s\n", dom, sr[rr], dom;

/^Server name/{
 getline name; gsub("Printer name ", "", name);
 n=name; gsub(" ", "_", n);
 getline rp; gsub("Share name ", "", rp);
 getline ty; gsub("Driver name ", "", ty);
 getline note; gsub("Location ", "", note);
 product="(" ty ")";
 printf "dnscmd . /RecordAdd %s _printer._tcp PTR %s._printer._tcp.%s\n", dom, n, dom;
 printf "dnscmd . /RecordAdd %s %s._printer._tcp SRV 0 0 515 %s.%s\n", dom, n, srv, dom;
 printf "dnscmd . /RecordAdd %s %s._printer._tcp TXT \"txtvers=1\" \"qtotal=1\" \"rp=%s\" \"ty=%s\" \"note=%s\" \"priority=0\" \"product=%s\" \"printer-state=3\" \"printer-type=0x809056\" \"pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png\"\n", dom, n, rp, ty, note, product;