Skip to content

Instantly share code, notes, and snippets.

@jeffnash
Created April 27, 2026 18:50
Show Gist options
  • Select an option

  • Save jeffnash/a1556d9fe9bba0eb340462afb5bea49d to your computer and use it in GitHub Desktop.

Select an option

Save jeffnash/a1556d9fe9bba0eb340462afb5bea49d to your computer and use it in GitHub Desktop.
Tailscale + NoMachine + headless XFCE on :99

Francesco: how I set up Tailscale + NoMachine + headless XFCE on :99

This is the setup pattern I use on this Linux box so I can reach it remotely without a physical monitor attached.

The stack is:

  1. Tailscale for private network access.
  2. NoMachine for remote desktop.
  3. Xvfb on display :99 to provide a fake display.
  4. XFCE running inside that virtual display.

What is actually enabled on this machine

These system services are enabled at boot:

  • tailscaled.service
  • nxserver.service
  • headless-xfce.service

The important local files are:

1. Install the pieces

On a Debian/Ubuntu-style machine:

sudo apt update
sudo apt install -y xvfb xfce4 xfce4-session dbus-x11 tailscale

Then install NoMachine from their .deb package.

After that, verify the key binaries exist:

which Xvfb
which startxfce4
which tailscaled
test -x /etc/NX/nxserver && echo "NoMachine installed"

2. Make the headless XFCE launcher

Create /usr/local/bin/headless-xfce.sh with this content:

#!/bin/bash

export DISPLAY=:99
export XDG_SESSION_TYPE=x11
export XDG_CURRENT_DESKTOP=XFCE
export DESKTOP_SESSION=xfce
export XDG_RUNTIME_DIR=/run/user/1000

pkill -f "Xvfb :99" || true
rm -f /tmp/.X99-lock
rm -f /tmp/.X11-unix/X99

/usr/bin/Xvfb :99 -screen 0 1920x1080x24 -nolisten tcp -ac &
sleep 3

exec /usr/bin/dbus-run-session -- startxfce4

Make it executable:

sudo chmod +x /usr/local/bin/headless-xfce.sh

What this does:

  • forces everything onto display :99
  • starts a virtual X server at 1920x1080x24
  • clears stale X lock files first
  • launches XFCE inside that fake display

3. Make systemd keep the virtual desktop alive

Create /etc/systemd/system/headless-xfce.service:

[Unit]
Description=Headless XFCE on Xvfb :99
After=network.target

[Service]
User=clawffrey
Environment=DISPLAY=:99
ExecStart=/usr/local/bin/headless-xfce.sh
Restart=always

[Install]
WantedBy=multi-user.target

Then enable it:

sudo systemctl daemon-reload
sudo systemctl enable --now headless-xfce.service

Check it:

systemctl status headless-xfce.service

4. Configure NoMachine

NoMachine is the remote desktop layer. The service on this machine is:

sudo systemctl enable --now nxserver

Its unit file runs:

ExecStart=-/etc/NX/nxserver --daemon

The main node config on this box is /usr/NX/etc/node.cfg.

One relevant line there is:

DefaultDesktopCommand "/usr/bin/cinnamon-session --session cinnamon"

Even though that line still says Cinnamon, my actual working headless session is the systemd-managed XFCE session on :99, started by headless-xfce.service. That is the part I rely on.

To verify NoMachine itself:

/etc/NX/nxserver --status
sudo systemctl status nxserver

5. Configure Tailscale

Tailscale is just the secure path into the machine. The daemon is enabled at boot with:

sudo systemctl enable --now tailscaled

Then bring the node into your tailnet:

sudo tailscale up

Useful checks:

tailscale ip
tailscale status
sudo systemctl status tailscaled

Once the machine is on Tailscale, connect to it from NoMachine using the machine’s Tailscale IP or MagicDNS name instead of exposing NoMachine directly to the public internet.

6. How Francesco connects from his own computer

Francesco also needs Tailscale and NoMachine installed on his own laptop or desktop.

On Francesco's computer

  1. Install Tailscale.
  2. Install the NoMachine client.
  3. Sign in to Tailscale using the same tailnet you shared this machine into.
  4. Confirm his computer is online in Tailscale.

On this Linux box

Make sure this machine is also logged into Tailscale:

sudo tailscale up
tailscale ip -4
tailscale status
hostnamectl --static

The useful address choices for NoMachine are:

  • the machine's Tailscale IPv4 address from tailscale ip -4
  • the machine's Tailscale MagicDNS name, if enabled
  • the host's normal name, which on this box is clawffrey-Jasper-Lake-Client-Platform

In practice, the Tailscale IP is usually the easiest thing to hand Francesco.

Create the NoMachine connection

On Francesco's computer:

  1. Open NoMachine.
  2. Click New.
  3. Choose the NX protocol.
  4. For Host, enter this machine's Tailscale IP or MagicDNS name.
  5. Leave the default NoMachine port unless you intentionally changed it. The default NoMachine TCP port is 4000.
  6. Save the connection.
  7. Connect and log in with the Linux username and password for this machine.

Once connected, he should land in the headless XFCE desktop running on Xvfb :99.

What I would send Francesco directly

Something like this:

1. Install Tailscale and NoMachine on your computer.
2. Join my Tailscale network.
3. In NoMachine, create a new NX connection to:
   Host: <my tailscale IP or MagicDNS name>
   Port: 4000
4. Log in with my Linux machine username/password.

If you want, replace the placeholder with the actual Tailscale IP before sending him the guide.

7. Useful validation commands

These are the main commands I’d run when checking whether the stack is healthy:

systemctl status headless-xfce.service
systemctl status nxserver
systemctl status tailscaled
ps -ef | grep Xvfb
echo $DISPLAY
tailscale status
/etc/NX/nxserver --status

If you want to confirm the fake display exists:

ls -l /tmp/.X11-unix/

You should see X99.

8. Troubleshooting note from this box

On this machine, /etc/NX/nxserver --status currently reports:

'/etc/NX/server/localhost/runner.cfg' has wrong ownership

That file currently belongs to nobody:nogroup, which is unusual. However, NoMachine is still actively working on this box, so treat this as a status-path warning, not proof that the remote desktop is broken.

If Francesco hits the same warning, check:

ls -l /etc/NX/server/localhost/runner.cfg

and compare ownership with a clean NoMachine install. That is a NoMachine-specific warning, not a Tailscale or Xvfb :99 problem.

9. Short version

If Francesco only wants the gist:

  • install tailscale, xvfb, xfce4, and NoMachine
  • run Xvfb on :99
  • launch XFCE against DISPLAY=:99
  • keep that alive with systemd
  • enable nxserver and tailscaled
  • connect to NoMachine over the Tailscale network
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment