Skip to main content

Proxmox VE Host Name Changing On Existing Server

When setting up a Proxmox VE environment it is common to end up with a node named pve, which is the default hostname assigned during installation. This becomes a problem when managing multiple Proxmox servers since every node will show up as pve in the web UI. This post covers the complete process for renaming a Proxmox node to a meaningful name including the FQDN, and how to handle the pmxcfs filesystem quirks that make this more involved than a standard Linux hostname change.

Understanding How Proxmox Uses the Hostname

Proxmox VE derives the node name directly from the short hostname (the part before the first dot). This means a server configured with the FQDN pve-node-1.example.lan will appear in the UI as pve-node-1. It is important to plan the naming convention carefully upfront. A naming scheme like pve-node-1, pve-node-2 works well because the short hostname is already fully unique, without relying on the domain portion to differentiate nodes.

Proxmox stores its configuration in a virtual FUSE filesystem called pmxcfs, which is backed by a SQLite database at /var/lib/pve-cluster/config.db. This filesystem has restrictions that prevent renaming non-empty folders, which is why a Proxmox node rename requires more than just editing /etc/hostname.

Step 1: Update /etc/hostname

Replace the contents of /etc/hostname with the new short hostname:

echo "pve-node-1" > /etc/hostname

Step 2: Update /etc/hosts

The /etc/hosts file must map the new FQDN and short hostname to the server's static IP address. The pmxcfs service will fail to start if it cannot resolve the node name to a non-loopback IP, so this step is critical.

127.0.0.1       localhost
192.168.1.x     pve-node-1.example.lan    pve-node-1

Step 3: Update Postfix

Edit /etc/postfix/main.cf and update the myhostname value to the new FQDN:

myhostname = pve-node-1.example.lan

Step 4: Rename the Node in the pmxcfs Database

This is where Proxmox node renames differ from a standard Linux hostname change. The node name is stored in the SQLite database that backs pmxcfs. The official Proxmox documentation notes that pmxcfs cannot rename non-empty folders, so standard file copy approaches will not work reliably. The cleanest solution is to rename the node directly in the database while the pve-cluster service is stopped.

One important note: pmxcfs reads the node name from /etc/hostname at startup and requires it to be resolvable in /etc/hosts. If the hostname has already been changed but the database still references the old name, pmxcfs will fail to start with the error:

Unable to resolve node name 'pve' to a non-loopback IP address

If this situation occurs, temporarily add the old hostname as an alias in /etc/hosts to get pve-cluster running, then proceed with the database update.

Stop the pve-cluster service:

systemctl stop pve-cluster

Rename the node in the database. The nodes directory in the tree table uses inode as the primary key. First confirm the schema and identify the correct row:

sqlite3 /var/lib/pve-cluster/config.db "SELECT inode, parent, name FROM tree WHERE name IN ('pve', 'nodes');"

Then update the node name directly:

sqlite3 /var/lib/pve-cluster/config.db "UPDATE tree SET name='pve-node-1' WHERE name='pve' AND parent=(SELECT inode FROM tree WHERE name='nodes');"

Verify the change looks correct:

sqlite3 /var/lib/pve-cluster/config.db "SELECT inode, parent, name FROM tree WHERE name IN ('pve', 'pve-node-1', 'nodes');"

The output should show only the new name with no remaining pve entry under nodes. Start pve-cluster back up:

systemctl start pve-cluster

Step 5: Copy RRD Statistics Data

Proxmox stores historical performance data for nodes and storage in RRD files under /var/lib/rrdcached/db/. These are keyed by node name, so they need to be copied to match the new name. If the old directories do not exist this step can be skipped.

cp -r /var/lib/rrdcached/db/pve2-node/pve /var/lib/rrdcached/db/pve2-node/pve-node-1
cp -r /var/lib/rrdcached/db/pve2-storage/pve /var/lib/rrdcached/db/pve2-storage/pve-node-1
rm -r /var/lib/rrdcached/db/pve2-node/pve
rm -r /var/lib/rrdcached/db/pve2-storage/pve

Step 6: Reboot and Verify

reboot

After the server comes back up, confirm the rename was successful:

hostname        # should return: pve-node-1
hostname -f     # should return: pve-node-1.example.lan
ls /etc/pve/nodes/    # should show only pve-node-1

The web UI should reflect the new node name with all VMs and containers listed correctly under the renamed node.

Things to Watch Out For

1) SSL certificates — The self-signed certificate generated by Proxmox is tied to the hostname. It will regenerate automatically on reboot, so expect a new browser warning to accept. If Let's Encrypt is configured through the Proxmox UI it will need to be re-issued after the rename.

2) pmxcfs caches its state in memory — Any direct edits to the SQLite database must be made while pve-cluster is stopped. If pve-cluster is running when edits are made, it will overwrite the database with its in-memory state on the next restart, undoing the changes.

3) The node name is always the short hostname — pmxcfs derives the node name from the hostname, not the FQDN. A server configured with FQDN pve-node-1.example.lan will show as pve-node-1 in the UI. Do not rely on the domain portion to differentiate nodes — ensure the short hostname itself is unique across all servers.

4) Do not attempt this on a clustered node — Renaming a node that is a member of a Proxmox cluster requires additional steps to update the corosync configuration and is outside the scope of this post.

Comments

Popular posts from this blog

Power Pages Update Last Successful Login Using JavaScript and Power Pages API

 Recently while working on a Power Pages implementation for a client, I had the requirement to show the last time a user logged in on their profile page.  I thought this would be easy to do as there is already a field on the contact record for "Last Successful Login" (      adx_identity_lastsuccessfullogin).  This use to update when a user logged in, but it appears Microsoft has removed that automation. While searching I came across a few different ways of achieving this task.  One used application insights in Azure and another one used an HTTP endpoint setup in Power Automate.  I thought, this needs to be simpler.  What I came up with is to use Liquid with JavaScript to tell if a user is logged in or not.  Then use the new Power Pages api to update the logged in users contact record to mark the last time they logged in. Here is the approach I setup: 1) Make sure you turn on the api for contact in Site Settings. 1) Link to Microsoft Do...

Validating User Input In CRM Portals With JavaScript

When we are setting up CRM Portals to allow customers to update their information, open cases, fill out an applications, etc. We want to make sure that we are validating their input before it is committed to CRM.  This way we ensure that our data is clean and meaningful to us and the customer. CRM Portals already has a lot validation checks built into it. But, on occasion we need to add our own.  To do this we will use JavaScript to run the validation and also to output a message to the user to tell them there is an issue they need to fix. Before we can do any JavaScript, we need to check and see if we are using JavaScript on an Entity Form or Web Page.  This is because the JavaScript, while similar, will be different.  First, we will go over the JavaScript for Entity Forms.  Then, we will go over the JavaScript for Web Pages.  Finally, we will look at the notification JavaScript. Entity Form: if (window.jQuery) { (function ($) { if ...

Lookup In Select of URL For Power Pages

 While working on a Power Pages implementation I was consume the Power Pages API to get a Lookup table so I could show and hide information on the form using jQuery.  One issue I was having is I couldn't get a lookup field to return even though I had it as a field in the site setting for the table and included it in the my select statement in the URL.  I kept getting an `unexpected error occurred`. This issue is caused because lookup's are made up using 3 fields. 1) Formatted Value = The information you see in the lookup field (i.e. the record name) 2) Logical Name = The table the related record is a part of 3) Id = The id of the related record In the api there is a 4th field that is returned that is the Associated Navigation Property and it is the logical name of the lookup field. When setting up our select and even saying what columns can be returned in the API, we have to think how the OData endpoint will return the data to us.  ...