If you landed here from a search engine, one of these is probably your problem:
- Windows 98 or Windows for Workgroups cannot see your file server, because SMB1 is disabled on every modern operating system and the NTLMv1 authentication it offers is refused.
- Mac OS 9 has no way to mount anything — AppleTalk is gone, and macOS stopped serving AFP years ago.
- A DOS machine needs a disk or a file share, but a 286 with 640 KB of RAM has no room for a network stack.
- Old software wants to print, and there is no driver on earth for your current printer.
- You do not want a 1998 machine, with no patches since 1998, sitting on your real LAN.
- Your emulator — QEMU, 86Box, PCem — can only reach the outside world through a root-owned bridge or TAP device you would rather not create.
What it builds
One small Linux machine with two network interfaces. The uplink faces the network you already have and takes its Internet access from your ordinary router. The isolated side faces the old machines, and nothing from outside can reach in.
Internet
│
your existing router
│
┌───────────┴────────────┐
│ uplink (eth0) │
│ │
│ alpine-vde-router │ DHCP · DNS · NAT
│ │ FTP · SMB · AFP
│ isolated (eth1) │ IPP/LPD → PDF
└───────────┬────────────┘ NetDrive
│ 10.1.0.0/24
┌───────────┬───┴────┬───────────┬──────────┐
Win98 WinXP Mac OS 9 DOS anything
On the isolated side the appliance is the router (10.1.0.1 by default), the DHCP server, the DNS server, the file server and the print server at once. An old machine needs no configuration beyond “obtain an address automatically”.
| service | port | used by |
|---|---|---|
| DHCP | 67/udp | everything |
| DNS | 53 | everything |
| NAT | — | everything that wants the Internet |
| FTP (anonymous) | 21 + 10000–10100 | DOS, Windows, anything scriptable |
| SMB / CIFS (SMB1) | 139, 445 | Windows for Workgroups 3.11, 95, 98, ME, NT, 2000, XP |
| AFP | 548 | Mac OS 8, 9, and OS X |
| IPP printing → PDF | 631 | Windows 98 and later, Linux |
| LPD printing → PDF | 515 | classic Mac OS, and anything with only LPR |
| NetDrive | 2002/udp | DOS, as a network hard disk |
One directory, three protocols
FTP, SMB1 and AFP all serve the same directory, so a Windows 98 box, a Mac OS 9 box and a DOS box are looking at the same files through whichever protocol each of them was born with. Drop a read-only folder underneath the share root and it appears in all three at once; on a VM those are usually virtiofs mounts from the host.
Every file service is guest access with no password, mapped onto a single Unix account. That is a deliberate choice, not a shortcut.
A printer that produces files
CUPS with the PDF backend gives the isolated network a queue reachable over IPP (port 631, for Windows 98 and later) and LPD (port 515, for classic Mac OS and anything that only speaks LPR). Print jobs land in the spool directory as PDF files — and because that directory is also shared over SMB and AFP, the same old machine can print a document and then pick up its own PDF.
SystemGroup sys root lpadmin in /etc/cups/cups-files.conf, running lpadmin from a root shell is refused with 403 Forbidden — a baffling error to get as root.A hard disk for DOS over the network
mTCP NetDrive serves a disk image over UDP: the DOS client loads a small TSR and the image appears as an ordinary drive letter with a full DOS filesystem, not a network redirector. It needs about 8 KB resident, which is why it works on machines where nothing else does — a 286 with no room for a file-sharing stack, or a laptop whose drive bay is dead. It is also fast, because the client is doing plain sector reads and writes instead of translating file operations.
The NetDrive server is Michael Brutman's work and is not included in this repository; it is downloaded from his site and dropped onto the appliance.
Emulators plug in without root
Run the appliance as a virtual machine and an optional VDE switch — a virtual ethernet segment that lives in user space — lets QEMU, 86Box and PCem join the isolated network with ordinary user privileges. No bridge, no TAP device, no changes to the host's network configuration, nothing owned by root.
On real hardware the VDE chapter simply does not apply: everything from the router chapter onward is identical, with the share paths pointing at real directories. An old ThinkPad with two network ports will do.
The same network without a virtual machine
This appliance runs the router inside a VM, which is the straightforward way and what the documentation describes. There is another way. VDE ships vde_router, a userspace IPv4 router whose interfaces are connections to VDE switches rather than kernel devices — so a whole routed network can run with no VM, no TAP device and no root at all. Paired with the slirp plugin for the uplink it is a single process:
connect /tmp/vde0
connect slirp:///addr=10.1.9.1/dhcp=10.1.9.20
ifconfig eth0 add 10.1.0.254 255.255.255.0
ifconfig eth1 add 10.1.9.2 255.255.255.0
route add default 10.1.9.1
dhcpd start eth0 10.1.0.20 10.1.0.40
The catch is that vde_router as shipped does not forward packets at all, and attaching it to a segment disturbs that segment: unused addresses appear reachable and duplicate address detection always reports a conflict — which a Windows 98 or Mac OS machine probing for its address at boot will notice.
A fixed build, with nine defect fixes, a rewritten manual page and a HOWTO, is at github.com/zirize/vde-2. The patches are submitted upstream as virtualsquare/vde-2#74 and #75; use upstream instead once those land.
It does not replace this appliance. vde_router routes and hands out addresses; it has no DNS, no file sharing and no print queue, so the services set up here still need somewhere to live. Take it as the answer to “can I have the network without running a VM for it”, not as a drop-in replacement.
Installing it
A VM with 512 MB of RAM, about 2 GB of disk, two network interfaces and an Alpine Linux ISO. Roughly fifteen minutes, most of it waiting for packages to download.
git clone https://github.com/zirize/alpine-vde-router
cd alpine-vde-router
cp config.example.sh config.sh
nano config.sh # addresses, shares, what to install
./scripts/host/vde-switch.sh install # optional: VDE switch for emulators
./scripts/host/create-vm.sh # define the VM
./scripts/host/install-alpine.py # unattended Alpine install
./scripts/host/push-scripts.sh # copy the setup scripts over
ssh root@<the address you set> 'cd /root/setup && ./install-all.sh'
Any service can be switched off in config.sh. A machine that only needs to be a router is a two-minute install.
If you would rather understand each step than run a script — which is the point of the repository — every chapter gives the individual commands to paste by hand. The scripts and the documentation are the same commands. Nothing happens off-screen. Each chapter is arranged the same way: what this does, do it, check it (with the output you should see), and the failures people actually hit.
The documentation
| 01 · Overview | how the pieces fit, and what to decide before you start |
| 02 · The VDE switch | host side; only for emulators, skip on real hardware |
| 03 · Creating the VM | libvirt domain, two NICs, shared folders |
| 04 · Installing Alpine | unattended, or by hand |
| 05 · Router | NAT, DHCP, DNS, firewall |
| 06 · File sharing | FTP, SMB1 for Windows 9x, AFP for classic Mac OS |
| 07 · Printing | IPP and LPD, printed output as PDF |
| 08 · NetDrive | a network hard disk for DOS |
| 09 · Connecting clients | Windows 98/XP, Mac OS 9, DOS, QEMU, 86Box |
| 10 · On a physical server | what changes on real hardware |
| 11 · Troubleshooting | symptoms, causes, fixes |
The troubleshooting chapter is organised as a symptom index: no DHCP, missing NAT, DNS leaking to the outside, Windows 98 not seeing the shares, Mac OS 9 error −50, netatalk reporting a crash, port 631 refused, printing that produces no PDF, an emulator that cannot join the switch.
Tested on
Built and verified end to end on Alpine 3.24.2 with libvirt/QEMU on Ubuntu. Every command in the documentation was run on a machine installed from scratch by following the repository.
MIT licensed for the scripts and documentation.