← Back to Blog

How I Install My Proxmox Server From Scratch on My Old Laptop

proxmoxhomelablinuxnetworking

So I had this old laptop just sitting around collecting dust. An Asus with 8GB RAM (upgraded from 4GB, thank you very much), an ADATA NVMe SSD, and a leftover Seagate HDD from the previous owner's era. Instead of letting it rot in a drawer, I decided to turn it into a homelab Proxmox server.

Spoiler alert: it wasn't a smooth ride. The install itself was the easy part. What almost broke me was getting WiFi working on a machine that, as it turns out, doesn't even have an Ethernet port. If you're about to do the same thing, buckle up. This guide covers everything, including every dumb mistake I made so you don't have to repeat them.

This write-up is broken down into these parts:

  1. Opening
  2. Brief Introduction About Proxmox
  3. Checking Hardware Before Diving In
  4. Installing Proxmox From Scratch
  5. The Drama Begins: Why Can't I Access This Thing
  6. The WiFi Nightmare (The Real Boss Fight)
  7. Assigning a Static IP
  8. Final Check: Proxmox Is Officially Alive
  9. Closing Thoughts

Opening

The whole point of this project was simple: I wanted a homelab to mess around with. VMs, containers, maybe some self-hosted stuff later. I had a laptop with decent-enough specs just sitting idle, so why not.

What I didn't expect was that the network setup alone would eat up way more time than the actual installation. If you've got a laptop with only a WiFi card (no built-in Ethernet), read the WiFi section very, very carefully. It's the meat of this whole post.

Brief Introduction About Proxmox

Quick context before we dive in. Proxmox VE is not some completely separate OS from Debian. It's literally built on top of Debian (the current version runs on Debian 13 "Trixie"). Same kernel lineage, same storage stack, same driver support. Proxmox just wraps it with a hypervisor layer (KVM + LXC), a web management UI, clustering, snapshots, and backup tooling on top.

So if you're coming from a "plain" Debian headless server background, know that you're not learning a completely alien system. You're learning Debian plus a virtualization layer.

Checking Hardware Before Diving In

Before touching the installer, I checked what disks I was working with:

lsblk

Result:

  • /dev/nvme0n1, ADATA SX series, SSD (NVMe is always SSD, no exceptions)
  • /dev/sda, Seagate ST500LT032, HDD, 500GB, 5400RPM laptop drive

Knowing this mattered a lot for planning. I wanted the OS and VM/container disks living on the fast NVMe drive, and reserve the old spinning HDD for secondary storage (backups, ISO images) where speed isn't critical.

If you're doing this yourself and you're not sure which of your drives is which, the model number is usually a dead giveaway. The ST prefix almost always means Seagate spinning disk, while NVMe device paths (nvme0n1, nvme1n1, etc.) are SSDs by definition.

Installing Proxmox From Scratch

The actual installation is genuinely straightforward. Here's the full flow:

  1. Download the ISO from the official Proxmox VE downloads page.

  2. Flash it to a USB stick using Rufus (Windows) or balenaEtcher (cross-platform). Use GPT partition scheme if your laptop boots UEFI (most modern laptops do).

  3. Boot from the USB. On Asus laptops, mash F8 or Esc during boot to get the boot menu. You might need to disable Secure Boot in BIOS first.

  4. Walk through the installer wizard, step by step:

    • Accept the EULA
    • Pick your target disk (I picked the NVMe SSD, not the old HDD)
    • Select your country, time zone, and keyboard layout
    • Set the root password and an admin email address
    • Configure the network: hostname, IP address, gateway, and DNS server

    That last point is the one that will make or break your life later. Set an IP address, gateway, and DNS that actually match your router's subnet, not something you guessed.

  5. Let it install, then reboot and remove the USB stick.

  6. Access the Web UI for the first time. From any device on the same network, open a browser and go to:

    https://<the-ip-you-set-during-install>:8006
    

    You'll get a self-signed certificate warning (that's normal, click through it), then land on the Proxmox login page. Log in with root and the password you set during install.

Sounds simple, right? It was, until I tried to actually reach the thing from another device.

The Drama Begins: Why Can't I Access This Thing

After a "successful" install, I tried opening https://<my-ip>:8006 from another device on the network. Nothing. Timeout.

First suspect: subnet mismatch. I had set the Proxmox IP to something like xxx.xxx.100.2 without actually checking what subnet my router was handing out. Classic mistake. If your router's LAN is 192.168.1.0/24 and your server sits on 192.168.100.x, they're simply not going to see each other.

I fixed the IP to 192.168.1.200, matched the gateway to 192.168.1.1, set DNS to 1.1.1.1, and it still didn't work. That's when I knew something deeper was broken.

The WiFi Nightmare (The Real Boss Fight)

This is the part you're really here for. Grab a coffee, this section has a lot of moving pieces, so I'm walking through each problem the way I actually hit it: what broke, how I found out, and how I fixed it.

Problem 1: The bridge points to nothing

What was wrong: even with the subnet fixed, the Proxmox UI was still unreachable.

How I found out: I checked the network config directly:

cat /etc/network/interfaces

Found the vmbr0 bridge configured with:

bridge-ports nic0

nic0 isn't a real interface name in Linux. It's a placeholder that somehow ended up in my config, pointing to nothing that actually exists on the system.

The fix (well, half a fix): I needed to find out what the real network interface name was supposed to be, which led straight into the next problem.

Problem 2: There's no Ethernet port at all

What was wrong: I assumed I just needed to swap nic0 for the real interface name. Should be quick.

How I found out: I ran:

ip link show

Expecting to find something like enp2s0 or eth0. Instead, all I got was:

lo
wlo1
vmbr0

wlo1, a WiFi interface, was the only physical network device on the entire machine. My laptop simply doesn't have a physical Ethernet port. All this time I'd been trying to bridge an Ethernet interface that never existed in the first place.

The fix: forget fixing the bridge for now. I needed to connect wlo1 directly to WiFi instead.

Problem 3: Bridging over WiFi doesn't really work anyway

Before going further, worth explaining why I didn't just point bridge-ports at wlo1 and call it a day. Even if I did, a standard Linux bridge over WiFi generally doesn't work properly, because the 802.11 protocol doesn't support multiple MAC addresses passing through a single frame the way Ethernet does. VM traffic routed through a WiFi-backed bridge tends to get silently dropped by the access point. So bridging was off the table entirely. wlo1 needed to be used directly, not bridged.

Problem 4: The chicken-and-egg loop

This is the core problem of this whole section, so let me spell it out plainly:

  1. I can't connect to WiFi, because I need wpa_supplicant installed to authenticate, and it isn't there.
  2. I can't install wpa_supplicant, because installing it requires internet access.
  3. The only internet connection available on this machine is WiFi. Which I can't connect to. Because I need wpa_supplicant. Which I can't install.

A genuine loop with no way out from inside the machine itself. I confirmed this by trying:

which wpa_supplicant
apt install wpasupplicant

No internet, so apt install just hung and failed. Classic homelab special.

Solution: bring in internet from somewhere else, temporarily

The only way out of a loop like this is to bring internet in from outside the loop entirely. Two options work:

Option A: USB tethering or a USB-to-Ethernet adapter connected to a phone hotspot. Plug it in, and Linux typically detects it as a new Ethernet-like interface without needing extra drivers (RNDIS/CDC-ECM support is built into the kernel). No wpasupplicant needed for this step at all, since it's not WiFi.

Option B: sideload the packages via USB flash drive. If tethering isn't available, download the needed .deb files manually from packages.debian.org on any other device that has internet, copy them onto a USB flash drive, then install offline:

mkdir /mnt/usb
mount /dev/sdb1 /mnt/usb
cd /mnt/usb/your-folder
apt install ./*.deb

apt (not raw dpkg) is the way to go here since it resolves dependency order automatically and skips anything already installed.

In my case, I ended up going with a USB-to-Ethernet adapter connected to a phone hotspot. It turned out to be the cleanest solution: real Ethernet, no bridging weirdness, and reusable long-term.

Installing wpasupplicant, iw, and wireless-tools

Once internet was flowing through the adapter:

apt update
apt install -y wpasupplicant iw wireless-tools
  • wpasupplicant: handles WPA/WPA2 authentication to WiFi
  • iw: modern tool for checking WiFi status, scanning, signal strength
  • wireless-tools: legacy tools like iwconfig, still occasionally useful

Problem 5: the route table gets confused

What was wrong: even after getting an IP from the hotspot adapter, ping still failed with the connection unreachable.

How I found out: I tried to manually add a default route and got an error:

ip route add default via 10.218.245.1 dev enx84a4155c2b91
# RTNETLINK answers: File exists

There was a leftover default route from the old, broken vmbr0 config still sitting in the routing table, conflicting with the new one.

The fix: use replace instead of add, which overwrites the existing default route regardless of which interface it was previously bound to:

ip route replace default via 10.218.245.1 dev enx84a4155c2b91

Problem 6: guessing the gateway wrong

What was wrong: I initially just guessed the gateway ended in .1, which happened to be correct this time, but that's not something to rely on.

The fix: pull the actual gateway value DHCP handed out instead of guessing:

cat /var/lib/dhcp/dhclient.leases | grep routers

Or just check ip route show after running dhclient. The default route usually populates itself correctly once nothing else is fighting for it.

Problem 7: DNS refuses to resolve anything

What was wrong: raw IP connectivity worked (ping 1.1.1.1 succeeded), but apt update failed with Temporary failure resolving deb.debian.org.

How I found out: checked the resolver config and it was essentially empty:

cat /etc/resolv.conf

The fix: set DNS manually:

echo "nameserver 1.1.1.1" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf

To make it stick permanently across reboots, I added it directly into the interface config in /etc/network/interfaces:

dns-nameservers 1.1.1.1 8.8.8.8

Problem 8: GPG signature verification failure

What was wrong: apt update complained that trixie-updates isn't signed, with a message along the lines of "updating from such a repository can't be done securely."

How I found out: this kind of error usually comes down to one of two causes, so I checked both:

  1. Wrong system clock. If the date is off, GPG signature validity checks fail outright.
  2. Outdated keyring package, missing the signing keys used for the current release.

The fix: corrected the clock first:

timedatectl set-time "2026-09-03 14:00:00"

Then refreshed the keyring just in case:

apt-get install --reinstall debian-archive-keyring

Finally connecting to home WiFi

With all the tools installed and internet flowing through the adapter, it was finally time to connect to the actual home WiFi (not the hotspot):

wpa_passphrase "YOUR_SSID" "YOUR_PASSWORD" > /etc/wpa_supplicant/wpa_supplicant-wlo1.conf

Then added this to /etc/network/interfaces:

auto wlo1
iface wlo1 inet dhcp
    wpa-conf /etc/wpa_supplicant/wpa_supplicant-wlo1.conf
    dns-nameservers 1.1.1.1 8.8.8.8

Applied it:

systemctl restart networking

Verified with:

iw dev wlo1 link
ip addr show wlo1
ping -c 4 192.168.1.1
ping -c 4 1.1.1.1

Cleaning up the old vmbr0

What was wrong: even with wlo1 working, the old vmbr0 was still marked auto with a static gateway, so it kept competing with wlo1 for the default route.

The fix: removed the auto flag and the gateway line from vmbr0, leaving wlo1 as the sole interface actually managing the default route:

#auto vmbr0
iface vmbr0 inet static
    address 192.168.1.200/24
    bridge-ports nic0
    bridge-stp off
    bridge-fd 0

Problem 9: 401 Unauthorized from the enterprise repo

What was wrong: apt update started throwing 401 Unauthorized specifically on enterprise.proxmox.com.

How I found out: this is Proxmox's paid subscription repository, enabled by default on a fresh install, useless without an actual subscription key.

The fix: disabled the enterprise repo:

# in /etc/apt/sources.list.d/pve-enterprise.sources
Enabled: false

And switched to the free no-subscription repo instead:

cat > /etc/apt/sources.list.d/pve-no-subscription.sources << 'EOF'
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF
apt update

Finally, a clean apt update with zero errors. Victory.

Assigning a Static IP

DHCP addresses can shift over time, which is annoying for something you want to reach reliably. The cleanest fix is a DHCP reservation on the router itself, rather than hardcoding a static config on the Proxmox side (which risks IP conflicts).

Grab the MAC address of wlo1:

ip link show wlo1
# or
cat /sys/class/net/wlo1/address

Then log into the router's admin page, find DHCP Reservation / Static Lease / Address Reservation (naming varies by router brand), and bind that MAC address to the IP wlo1 is already using. Save, and the IP stays locked from then on.

Final Check: Proxmox Is Officially Alive

With networking sorted, the moment of truth. Opened from another device on the same network:

https://<your-static-ip>:8006

And there it was, the Proxmox login screen. After all that, seeing it load felt disproportionately satisfying.

Quick sanity checklist before calling it done:

  • ping to gateway and 1.1.1.1 both succeed
  • apt update runs clean, no 401 or GPG errors
  • Reboot test: WiFi reconnects automatically without manual intervention
  • Web UI loads and login works from another device on the network

Closing Thoughts

If there's one thing I'd tell past me before starting this: just get a USB-to-Ethernet adapter from day one. WiFi-only laptops turned into Proxmox hosts are technically possible, but you'll fight wpa_supplicant, routing tables, and DNS resolution the entire way. A cheap adapter would've saved me hours of chicken-and-egg debugging.

That said, I did learn a ton about Linux networking internals I probably wouldn't have bothered learning otherwise, so silver lining.

Next up: setting up remote access to this thing from outside my home network, using Tailscale for admin access and Cloudflare Tunnel for anything I want to expose publicly. That's a story for another post.