DEV Community

Cover image for Part 1 — Proxmox VE: Installing and Configuring the Virtualization Host
Weronika Kawa
Weronika Kawa

Posted on Originally published at Medium

Part 1 — Proxmox VE: Installing and Configuring the Virtualization Host

1. The Mission: Opting Out of the Subscription Trap

We live in an era where we generate gigabytes of private data every day—photos, code, sensitive documents, and backups. The tech industry has conditioned us to choose the path of least resistance: sending everything to public clouds like Google Drive, OneDrive, or iCloud.

As a computer science student, this didn’t sit right with me. The modern world tries to convince us that absolutely everything has to be a subscription. I really dislike this model of continuously renting everything. I prefer to pay once for physical hardware and know it is truly my property—not a service that can go up in price or vanish at any moment.

But privacy and ownership are only part of the equation; the other part is risk management. On one hand, we face immediate threats like critical Zero-Day exploits in popular software and cloud services. On the other hand, there is the long-term, silent risk of Harvest Now, Decrypt Later (HNDL). Adversaries may collect encrypted data today, hoping to decrypt it in the future once quantum computers mature enough to break standard asymmetric encryption algorithms—a transition often referred to as Q-day. Entrusting corporate giants with my private files, passwords, and code under these conditions felt like too much of a compromise.

I wanted secure access to my resources from anywhere, while maintaining one personal rule: I want as much control over my data and infrastructure as reasonably possible, with physical hardware residing under my own roof.

My motivation was also deeply educational. I don't want to just be a passive user of ready-made tools; I want to understand them from the inside out. I wanted to build and manage a real server, learn routing, virtualization, and storage systems. Most of all, I wanted to break things, face real technical challenges, and debug the system outages that inevitably come with administration.

Why Proxmox VE?

To run a private cloud, a secure VPN gateway, a local DNS, and monitoring tools, I needed multiple independent environments. Installing them all directly on a single, monolithic OS would couple unrelated services together and make failures harder to isolate.

I needed a virtualization platform that could run both virtual machines and lightweight Linux containers directly on my hardware. Proxmox VE 9, built on Debian 13, was a natural choice for this project. Most importantly for my setup, Proxmox supports both Kernel-based Virtual Machines (KVM) and Linux Containers (LXC). On a machine with limited memory, the low overhead of lightweight LXC containers allows building a separated architecture with lower overhead than running multiple full virtual machines.

Budget-Friendly Hardware for Anyone

To many, a home server conjures up images of a massive, loud, and power-hungry server rack. I wanted to prove that a capable homelab could be built for the price of a nice dinner for two.

In March 2026, I started this project with a modest budget:

  • I bought a refurbished Lenovo ThinkCentre M73 Tiny (Intel Core i5-4570T, 4 GB RAM, 240 GB Crucial BX500 SSD, Windows 10 Pro) from a Polish refurbished-hardware store called rnew.pl for 169 PLN (~$42 USD at the exchange rate at the time). (Naturally, I had no use for the Windows 10 Pro license, but this specific spec happened to be the cheapest option available).
  • Since the mini PC came with a basic configuration, I gave it some breathing room by adding an 8 GB DDR3 RAM module for 95.90 PLN (~$24 USD at the exchange rate at the time).

In the end, for under 265 PLN (approximately $66 USD), I had a quiet, energy-efficient machine equipped with an Intel Core i5 processor and 12 GB of RAM. This compact setup became the physical heart of my homelab—ready to host my virtualization environment.

2. My Setup: Physical Specs and Storage Partitioning

  • Tested with: Proxmox VE 9.2.11 on September 2026
  • My Hardware: Lenovo ThinkCentre M73 Tiny (Intel Core i5-4570T, 12 GB RAM, 240 GB Crucial BX500 SSD)

To get started, I needed my mini PC, a spare USB flash drive to hold the installer, and an Ethernet cable to connect the server directly to my home router.

My Goal

The goal was simple: turn a $66 refurbished mini PC into a reliable virtualization host that I could manage remotely from my laptop.

To understand how the host operates once installation is complete, it helps to look at how Proxmox organizes its storage and networking by default:

1. Default Storage Partitioning (local vs. local-lvm)

With the default LVM-thin installation layout, Proxmox creates two main storage pools:

  • local (Directory): Used for file-based content. This is where I upload ISO installation images, LXC container templates, and host backup files.
  • local-lvm (LVM-thin): Dedicated LVM-thin block storage. It stores the virtual disks of future virtual machines and containers, supporting thin provisioning, snapshots, and cloning. (Note: The "localnetwork" entry with the grid icon visible in the sidebar is not a storage drive—it is Proxmox's default Software-Defined Networking (SDN) zone representing the local network interfaces).

2. The Linux Bridge (vmbr0)

My physical Ethernet interface is named enp0s25 (which my network configuration organizes under the logical interface name nic0). Because I will need to share this single network connection with all future virtual machines and containers, Proxmox creates a virtual switch called a Linux Bridge (vmbr0).

My physical Ethernet port connects directly into this bridge. This allows both my Proxmox host’s management dashboard and all future virtual guests to share the same physical Ethernet connection to my LAN.

⚠️ A Note on Resiliency and Backups

This setup is intentionally minimal and designed for hands-on learning. Running a single mini PC with a single SSD means this architecture has a Single Point of Failure (SPOF). If the SSD fails, the services fail. This is not a complete backup or high-availability strategy. In later parts of this series, I will address backup, recovery, and off-site replication separately.

With my setup mapped out, I was ready to prepare the installation media.


3. The Hands-On Guide: Installing Proxmox VE 9.2

My goal for this phase was to install Proxmox VE 9 on my mini PC and establish a working local management interface.

Here is the step-by-step documentation of how I prepared my media, configured the hardware, and completed the installation.

Step 1: Flashing the Installer

First, I downloaded the official Proxmox VE 9.2 ISO installer directly from the Proxmox downloads page (making sure to select the standard x86_64 version, not the newly released ARM64 image).

To turn my 16 GB USB flash drive into a bootable installer, I used a free utility called Rufus on my Windows laptop:

  1. I opened Rufus and selected my USB flash drive under the Device dropdown.
  2. Under Boot selection, I clicked SELECT and chose my downloaded Proxmox ISO file.
  3. I left the partition scheme as GPT and the target system as UEFI (non CSM).
  4. I clicked START.
  5. Rufus prompted me with a pop-up window asking how to write the image. For Proxmox, official documentation recommends writing the image in DD Image mode. This ensures the Debian installer recognizes the partition structure correctly.
  6. Once the progress bar turned green and showed READY, I safely ejected the flash drive.

Step 2: Connecting Peripherals & BIOS Setup

A home server is meant to run headlessly—meaning it sits silently on a shelf with only power and Ethernet cables attached, without a monitor, keyboard, or mouse. However, for the initial installation, I temporarily plugged in a monitor via DisplayPort, a USB keyboard, a mouse, and my bootable USB drive.

Before booting into the installer, I configured the hardware. I turned on the Lenovo M73 Tiny and repeatedly pressed the F1 key to enter the Lenovo BIOS Setup Utility.

I navigated to the Security -> Virtualization menu and verified two settings:

  1. Intel Virtualization Technology (VT-x): Enabled. This provides the hardware virtualization extensions required by KVM for efficient CPU virtualization.
  2. Intel VT-d: Enabled. This enables IOMMU functionality, which is required for certain forms of hardware passthrough (such as passing through USB controllers or PCIe devices directly to virtual machines).

Finally, I checked the boot settings. Modern Proxmox VE versions fully support Secure Boot, although I chose to disable it on this particular machine during my installation to simplify legacy boot troubleshooting.

I pressed F10 to save my changes and exit. As the system rebooted, I pressed F12 to bring up the temporary Boot Menu, selected my USB drive from the list, and pressed Enter.

Step 3: Navigating the Proxmox Installer

Once the Proxmox boot loader appeared, I selected Install Proxmox VE (Graphical) and followed the installation wizard:

  1. Target Harddisk: I selected my internal /dev/sda (the 240 GB Crucial SSD).
  2. Location and Time Zone: I selected Poland and Europe/Warsaw as my location and time zone, and configured the appropriate keyboard layout.
  3. Password and Email: I set a strong administrative password for the root user and entered my personal email to receive system alerts.
  4. Management Network Configuration:
    • Management Interface: I selected my physical network port (labeled enp0s25, mapped in my configuration under nic0).
    • Hostname: I entered pve.home.arpa (using the official RFC 8375 standard domain reserved for home networks to prevent local DNS conflicts).
    • IP Address: I chose a static IP address of 192.168.0.100/24 for my server. (Note: Ensure your chosen static IP is outside your router's active DHCP pool to prevent address conflicts, or configure a DHCP reservation on your router).
    • Gateway & DNS Server: I configured my router (192.168.0.1) to act as both the default gateway and temporary DNS resolver.

Once I verified all settings on the final Summary screen, I clicked Install. The installer formatted my SSD, extracted the base operating system, and rebooted.

At this point, I unplugged the USB drive, disconnected the monitor, keyboard, and mouse, and placed the Lenovo Tiny on my desk. I connected only the power cable and an Ethernet cable.

Step 4: First Login to the Dashboard

With my server now running headlessly, I returned to my main computer, opened a web browser, and navigated to the static address I had assigned:

<https://192.168.0.100:8006>
Enter fullscreen mode Exit fullscreen mode

Because Proxmox uses a self-signed SSL certificate out of the box, my browser showed a "Your connection is not private" warning. This warning was expected because the default certificate is not trusted by my browser. I clicked Advanced and bypassed the warning.

I was greeted by the Proxmox login screen, where I logged in with the username root and the password I established in Step 3.

Step 5: Opening the Console & Swapping to Community Repositories

Proxmox VE is open-source software and can be used without purchasing a subscription. Paid subscriptions provide access to the Enterprise repository and enterprise technical support.

By default, Proxmox configures commercial Enterprise repositories for both system updates and Ceph storage. Without a paid subscription key, APT will return an authorization error (401 Unauthorized) when attempting to update. For a homelab, Proxmox provides a No-Subscription repository.

First, I accessed the server's command-line interface. In the Proxmox Web UI, I clicked on my node name (pve) in the left-hand sidebar, and then clicked the >_ Shell button in the top-right toolbar. This opened a terminal session directly in my browser.

In Proxmox VE 9 (based on Debian 13), repository files use the modern deb822 block format (using .sources files). To disable the enterprise repositories, I commented out the active blocks:

# Disable main enterprise updates
sed -i 's/^/#/' /etc/apt/sources.list.d/pve-enterprise.sources

# Disable Ceph enterprise updates (I don't use Ceph in this single-node homelab)
sed -i 's/^/#/' /etc/apt/sources.list.d/ceph.sources
Enter fullscreen mode Exit fullscreen mode

(Note: In deb822 .sources format, you can also set Enabled: false inside the configuration block to achieve the same result).

Next, I created a new .sources configuration to enable the free, community-supported No-Subscription repository:

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
Enter fullscreen mode Exit fullscreen mode

Finally, I updated the package index and upgraded all installed packages:

apt update && apt dist-upgrade -y
Enter fullscreen mode Exit fullscreen mode

Now, my update pipeline was clean and running from the No-Subscription repository with zero errors.

Step 6: Silencing the Subscription Nag (Optional Cosmetic Tweak)

Even though the system was fully functional, every login greeted me with a pop-up warning reminding me that I did not have an active subscription. Since I chose to run the No-Subscription repository in my homelab, I decided to remove this cosmetic warning.

(Note: This is an optional UI-only patch. Because it modifies a core JavaScript file, this change may be overwritten whenever Proxmox updates the proxmox-widget-toolkit package).

In the shell, I executed a command to bypass the subscription check within the Proxmox management interface library:

sed -Ezi.bak "s/(Ext.Msg.show\(\{\s+title: gettext\('No valid sub)/void\(\{ \/\/\1/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
Enter fullscreen mode Exit fullscreen mode

To apply the changes, I restarted the web GUI management service:

systemctl restart pveproxy
Enter fullscreen mode Exit fullscreen mode

After clearing my browser cache and logging back in, the subscription pop-up was gone. The host was ready for the next stage of the setup.

4. Post-Install Tuning: SSH Hardening and Thermal Optimization

Once I installed and updated Proxmox on my mini PC, I wanted to address two practical configurations: hardening its security and optimizing its energy draw and thermal output.

Here is how I tuned my hardware to run quietly, safely, and efficiently on my desk.

1. Hardening SSH: Moving to Key-Only Authentication

By default, Proxmox allows you to log in as the root user using the password you created during installation. While this is fine for the initial setup, keeping password authentication enabled over SSH on a server is a security risk.

To secure my host, I decided to disable password-based SSH authentication and rely on cryptographic SSH keys.

(Note: While in enterprise settings it is standard practice to disable root SSH logins completely and use a standard user with sudo, I chose to keep key-based root SSH access enabled for this single-user homelab to simplify direct administration while blocking password brute-force attempts).

First, on my main laptop, I opened a terminal and generated an Ed25519 key pair:

ssh-keygen -t ed25519 -C "weronika-homelab"
Enter fullscreen mode Exit fullscreen mode

Next, I copied my public key over to the server using the static IP address I configured in the previous step:

ssh-copy-id -i ~/.ssh/id_ed25519.pub root@192.168.0.100
Enter fullscreen mode Exit fullscreen mode

I verified that the key was working by logging in. The server allowed me in without prompting for my root password:

ssh root@192.168.0.100
Enter fullscreen mode Exit fullscreen mode

With key-based access verified, I disabled password logins. On Debian 13 (the foundation of PVE 9), the cleanest way to customize SSH settings is by dropping a configuration file into the /etc/ssh/sshd_config.d/ directory, rather than editing the main config file directly.

I opened the shell console on my Proxmox host and created a new hardening configuration:

nano /etc/ssh/sshd_config.d/harden.conf
Enter fullscreen mode Exit fullscreen mode

I pasted the following directive to disable password logins:

PasswordAuthentication no
Enter fullscreen mode Exit fullscreen mode

Before restarting the SSH service, I tested the configuration syntax to ensure I wouldn't lock myself out:

sshd -t
Enter fullscreen mode Exit fullscreen mode

With no errors returned, I restarted the SSH daemon to apply the new policy:

systemctl restart ssh
Enter fullscreen mode Exit fullscreen mode

To audit and test my security configuration, I ran an SSH command on my laptop that forces the SSH client to bypass local keys and attempt a standard password login:

ssh -o PubkeyAuthentication=no root@192.168.0.100
Enter fullscreen mode Exit fullscreen mode

Because my server-side policy was active, the Proxmox host rejected the connection without prompting me to enter a password:

root@192.168.0.100: Permission denied (publickey).
Enter fullscreen mode Exit fullscreen mode

My host’s command line was now successfully locked down.

(Note: Disabling SSH password authentication only locks port 22. It does not affect the Proxmox Web GUI in your browser on port 8006, where you will still log in using your standard root username and password).

2. Tuning for Silence: Configuring the CPU Governor

My mini PC is powered by an Intel Core i5-4570T. While this dual-core Haswell chip is efficient, it resides in a tiny 1-liter chassis with a very small fan. Out of the box, the Linux kernel often favors performance-heavy settings that keep the CPU clocks high, causing the fan to spin and waste power while idling.

When I first ran diagnostics on my host, I noticed the CPU was idling at an observed 3.30 GHz under the default performance governor (close to its 3.60 GHz maximum single-core turbo limit).

Since a home server sits idle most of the time, I wanted to change the CPU scaling governor. To configure this, I installed the linux-cpupower utility:

apt install linux-cpupower -y
Enter fullscreen mode Exit fullscreen mode

Once installed, I analyzed my CPU using the following command:

cpupower frequency-info
Enter fullscreen mode Exit fullscreen mode

The terminal output confirmed that the Intel scaling driver (intel_cpufreq, the passive operation mode of intel_pstate) was active, offering several governors, including powersave, performance, and ondemand.

In my setup, powersave kept the CPU at its minimum reported frequency of 800 MHz even under sustained load, while ondemand allowed the frequency to scale dynamically based on workload.

To change the governor, I ran:

cpupower frequency-set -g ondemand
Enter fullscreen mode Exit fullscreen mode

To make this setting survive reboots, I set up a task in the system’s automated scheduler (cron). I opened the cron scheduler editor:

crontab -e
Enter fullscreen mode Exit fullscreen mode

(I selected option 1 to open the file in the nano editor). At the very bottom of the file, I added the following line to enforce the dynamic state every time the system boots up:

@reboot cpupower frequency-set -g ondemand >/dev/null 2>&1
Enter fullscreen mode Exit fullscreen mode

I saved the file and exited.

The CPU now spends idle time at a much lower frequency, and subjectively the fan became noticeably quieter on my desk.

3. Monitoring Thermals from the CLI

Because a mini PC has limited airflow, I wanted a simple way to monitor my hardware's core temperatures from the command line.

I installed lm-sensors to handle temperature readouts, and htop to monitor active CPU threads and memory load:

apt install lm-sensors htop -y
Enter fullscreen mode Exit fullscreen mode

Next, I ran the sensor detection wizard to let Linux automatically find my motherboard's thermal monitors (I followed the prompts and accepted the recommended defaults):

sensors-detect
Enter fullscreen mode Exit fullscreen mode

Once the configuration was saved, checking my CPU temperatures became as simple as typing a single command:

sensors
Enter fullscreen mode Exit fullscreen mode

5. The "Aha!" Moment: Debugging the CPU Frequency Trap

While setting up my host, I encountered a silent configuration issue that showed how easily generic system optimization advice can backfire on specific hardware.

The Problem

To lower my mini PC's idle power consumption, I read a suggestion online to set the CPU scaling governor to powersave. After installing linux-cpupower, I applied the setting:

cpupower frequency-set -g powersave
Enter fullscreen mode Exit fullscreen mode

It seemed like a sensible default, and I assumed the CPU would scale down dynamically when idle and scale back up under load.

The Investigation

To test how this change behaved under load, I decided to verify my CPU frequencies in the host console:

cpupower frequency-info
Enter fullscreen mode Exit fullscreen mode

While the server was idle, the CPU sat at its minimum hardware frequency of 800 MHz. However, when I ran a heavy processing task to see the frequency scale up, the clocks on all cores remained locked at 800 MHz. The processor refused to scale up, significantly reducing performance in my test workload.

The Root Cause

The issue lay in the active CPU scaling driver. My system automatically loaded the intel_cpufreq driver (the passive mode of intel_pstate used on older Intel architectures lacking hardware-managed P-states).

Under generic CPUFreq drivers, the powersave governor requests the lowest frequency within the hardware limits. In my setup, this meant the system remained pinned at 800 MHz rather than scaling dynamically with processing load.

The Solution

To achieve dynamic scaling without keeping the CPU at its observed 3.30 GHz idle state, I switched the governor to ondemand:

cpupower frequency-set -g ondemand
Enter fullscreen mode Exit fullscreen mode

Checking the frequency info again confirmed the fix. During my observation, the reported frequency fluctuated around 955 MHz at idle and reached up to 3.60 GHz under load. This was a good reminder to always verify system behavior directly against the active hardware driver rather than blindly trust generic optimization tips.

6. What I Learned

Setting up this initial host left me with a few grounded takeaways:

  1. Generic Linux advice rarely accounts for older hardware. The issue with the CPU governor showed me why I need to inspect the active scaling driver directly rather than blindly trust popular optimization tips.
  2. Hardware ownership does not automatically equal security. Getting rid of cloud subscriptions gives me control, but it also transfers the entire responsibility for patching, firewall rules, and hardware reliability directly onto me.
  3. Writing detailed documentation is the best way to test comprehension. It is one thing to run commands until a service boots; it is entirely different to explain why each interface, partition, and configuration exists.

7. What’s Next: Building the Secure Network Gateway

At this point, my Proxmox hypervisor is fully set up, updated, and ready to host virtual machines and containers.

However, right now, any service I build at this stage will be reachable only from my local home network. To access my files or check my server's status when I am away from home, I need a secure way in.

In Part 2 of this series, we will solve this. We are going to deploy a dedicated Tailscale VPN Gateway inside a virtual machine and write custom, device-level security policies (ACLs) to ensure that accessing our home network from the outside is both simple and secure.

Other articles in this series:

  • Part 1 — Proxmox VE: Installing and Configuring the Virtualization Host (You are here)
  • Part 2 — Tailscale: Building a Secure Private Network (Coming soon)

References

  1. Proxmox Server Solutions. Proxmox VE Administration Guide.
  2. Debian Wiki. NetworkInterfaceNames: Persistent Network Interface Naming.
  3. Intel Corporation. Intel Core i5-4570T Processor Specifications (ARK).
  4. The Linux Kernel Organization. CPU Performance Scaling (CPUFreq) Documentation and intel_pstate Driver Documentation.
  5. National Institute of Standards and Technology (NIST). Post-Quantum Cryptography Project & HNDL Guidelines.

Follow the project

This article is part of my Homelab Infrastructure series, documenting my journey of building and maintaining a self-hosted home lab.

→ Explore the project on GitHub
→ Connect with me on LinkedIn

Thanks for reading!

Top comments (0)