Skip to main content

NoMachine Customizations

Proxmox VM vs Linux Container

This page was written when I was using Kali Linux in a Proxmox VM. I now predominantly run Kali in an unprivileged Proxmox Linux Container (LXC). Since LXC does not have a display driver the nxdisplay driver does not have the issues described below.

 

Auto-Login

On Kali side, go to Startup & Shutdown > Login Screen (SDDM) and click Behavior . Set the Automatically log in as <username> setting.

Best User and Viewing Experience

Experimenting with different settings, I finally found a mixture of settings that yields:

  • Fluid, dynamic screen resolution change that follows the client
  • No artifacts on the client window
  • Auto-login
  • Not necessarily the best user experience
  • Ensure use of X11 display server (instead of Wayland)
    • If not using X11, the fixes below won't work. Plus X11 allows a better window resizing experience 
    • If using KDE Plasma and SDDM, the choice is in the bottom left

      image.png

Dynamic Screen Resolution w/ No Artifacts

Settings on Proxmox side:

  • Display:  VMware Compatible
    • Setting to VMware compatible seems to have a missing driver on Kali -- at least with KDE from what I can gather
    • This causes X display to fail to render, so Kali has no display device, but does create a user session
    • Connecting to kali causes a virtual desktop, nxoutput0 to be created and attach to the X server
      • Because it is a NoMachine display device, 100% dynamic resolutions are supported
      • xrandr -q shows full 60Hz support on all resolutions
    • Closing the NoMachine client window does not break the session
      • So, it behaves like a headless server only due to the fact that the display driver is broken

Settings on the NoMachine Server side:

  • Encoding: VP8
  • Use hardware encoding
  • Use acceleration

Settings on the NoMachine Enterprise Client side:

  • On higher resolutions (4K, 43" monitor), I've found that setting the display settings accordingly improved performanceimage.png


Caveats

  • If the NoMachine service is restarted, this will terminate the NX server session, effectively logging the user off
    • The only way to work around this is to use a display device other than VMware compatible
    • This will allow a proper X session as the auto-login user and share the desktop via NoMachine
      • As opposed to creating a nxoutput virtual desktop
    • The only downside to this is that I haven't found a way to allow dynamic resizing for any and all resolutions
      • xrandr -q shows that there isn't a proper refresh rate for a multitude of resolutions
  • Breaks NoVNC console on Kali VM
  • For some reason, the VMware compatible driver must not be present in Kali
    • I tried installing open-vm-tools on Kali to see if that would work
    • It's not a big enough issue to worry about, as I barely use the NoVNC console
  • Anything that I can't do in the NoMachine client, I could likely workaround in SSH



Setting Ad-Hoc Resolutions

Looking at the Caveats section above, you'll note that when using the VMware Compatible graphics driver in Proxmox, this breaks the NoVNC console in Proxmox, and also breaks the X server running on Linux. This happens not because there's anything special about that graphics driver. It happens -- rather -- because the kernel fails to load the driver and NoMachine creates a virtual desktop session.

The virtual desktop session running under nxoutput0 is not using the X server, therefore if the NoMachine service crashes and/or restarts, then anything running under the NX user session will be lost. It's essentially the same effect as rebooting the VM.

Therefore, whilst the viewing experience is optimal -- and crashes are rare -- you run the risk of data loss and corruption. Setting ad-hoc resolutions is a viable workaround, and can easily be automated once you find some resolutions you like.

Default Resolutions

Running xrandr -q will show you the default resolutions X server makes available based on the driver in-use by the VM.

image.png

NoMachine client has the ability to auto-resize the remote display when resizing the client window. However, this will only work when the client has stretched the window to a size that conforms to one of the default available resolutions. You'll see in the output above that based on the video memory made available to this VM, I can set resolutions up to 8192x8192.

image.png

Adding Custom Resolutions

The monitor I am using at the time of this writing has a native resolution of 5120x1440 and various refresh rates, but currently outputting at 60hz due to unsupported hardware.


Scenario 1: Adding Native Resolution

Let's say I want to add full 5120x1440 @ 60Hz for when I want to run this VM in full screen mode. Open a terminal window and follow along.

# Calculate a new mode configuration
# 5120x1440 @ 60Hz
mode="5120 1440 60"
modeline=$(cvt `echo $mode` | grep Mode | sed -e 's/Modeline //g' -e 's/"//g')
modename=$(echo $modeline | cut -d ' ' -f 1 | sed 's/"//g')

# Get the display device name
display_device=$(xrandr | grep -e " connected [^(]" | sed -e "s/\([A-Z0-9]\+\) connected.*/\1/")

# Take the output from the cvt and add a new mode
xrandr --newmode `echo $modeline`

# Add the newly added mode to the list of resolutions
xrandr --addmode $display_device $modename

image.png

image.png

image.png

image.png

Note the availability of the new resolution at the bottom of the list.

image.png

This resolution will also be available for selection in the graphical settings interface where you can manage your display resolution.

image.png

Once you've added the resolution to your VM, restart your NoMachine service with this command:

sudo systemctl restart nxserver.service

Once I restarted the NoMachine daemon, everything works perfectly and the client continues to dynamically resize to full screen mode when engaged or disengaged.

Persisting Reboots

These changes to the display configuration will not persist reboots, so you'll want to add the xrandr commands to your preferred Xsession script. I am using sddm as my login manager, so looking at /usr/share/sddm/scripts/Xsession, I can add the resolutions to a couple places to make it stick:

If you want your resolutions to be available to all users, put them in: /etc/X11/Xsession.d/100set-resolutions
If you want your resolutions to be user-specific, put them in: ~/.xsessionrc

sudo nano /etc/X11/Xsession.d/100set-resolutions
# Add support for 5120x1440 @ 60Hz resolution at boot
mode="5120 1440 60"
modeline=$(cvt `echo $mode` | grep Mode | sed -e 's/Modeline //g' -e 's/"//g')
modename=$(echo $modeline | cut -d ' ' -f 1 | sed 's/"//g')
display_device=$(xrandr | grep -e " connected [^(]" | sed -e "s/\([A-Z0-9]\+\) connected.*/\1/")
xrandr --newmode `echo $modeline`
xrandr --addmode $display_device $modename

Scenario 2: Adding Custom Window Sizes

So, maybe you want a window size that isn't full screen, but is bigger than the default resolutions provided by the driver. The easiest way to do this is the following steps:

  1. Figure out the dimensions of the window size
  2. Add support for the resolution following the steps covered above

Measure the Window Dimension

On your host machine (not the VM), open a PowerShell window (this guide is being written on a Windows host) and run the following command:

# 64 bit Chrome
& 'C:\Program Files\Google\Chrome\Application\chrome.exe' --app=https://whatismyviewport.com

This web app will dynamically tell you the viewport size as you resize the window. The viewport is the content of the application minus the title bar. This is important, because you don't want to include the title bar in your resolution. You only want your screen resolution to reflect the actual content viewport.

image.png

Add the Screen Resolution

If my viewport was set to 5120x1377 and running on a 60Hz output, then I'd add the resolution by running these commands:

# Add support for 5120x1377 @ 60Hz
mode="5120 1377 60"
modeline=$(cvt `echo $mode` | grep Mode | sed -e 's/Modeline //g' -e 's/"//g')
modename=$(echo $modeline | cut -d ' ' -f 1 | sed 's/"//g')
display_device=$(xrandr | grep -e " connected [^(]" | sed -e "s/\([A-Z0-9]\+\) connected.*/\1/")
xrandr --newmode `echo $modeline`
xrandr --addmode $display_device $modename

Don't forget to:

  • Restart the NoMachine daemon
  • Add the persistence to the /etc/X11/Xsession.d/100set-resolutions script (your script path may differ).

References: