How to set up a multi-user VNC server on Ubuntu Desktop with GNOME & TigerVNC
A step-by-step guide to creating independent, persistent desktop sessions for multiple users.
Introduction
Setting up a remote desktop on a server is a common task, but most guides focus on a single user or simple screen sharing. This guide tackles a more advanced scenario: building a true multi-user VNC "terminal" server on Ubuntu 24.04 LTS.
The goal is to allow multiple users (like alice and bob) to connect to the same server but get their own independent, persistent GNOME desktop session. Alice's session will be on display :1, Bob's on :2, and neither will see or interfere with the other.
This is incredibly useful for small teams, developer environments, or any situation requiring a shared Linux server with a full graphical interface for each user.
We will use TigerVNC for the server, GNOME as the desktop environment, and systemd to manage the persistent sessions.
Step 1: Install VNC server and GNOME desktop
First, connect to your server via SSH. We need to install the TigerVNC server and the full GNOME desktop environment.
We'll install ubuntu-desktop to ensure all required dependencies for a full gnome-session are present.
xinit@localhost:~$ sudo apt update
xinit@localhost:~$ sudo apt install ubuntu-desktop tigervnc-standalone-server -y
This installation may take a few minutes.
Step 2: Create user accounts
For a multi-user setup, we need users. For this guide, we'll create two example users: alice and bob.
xinit@localhost:~$ sudo adduser alice
xinit@localhost:~$ sudo adduser bob
Follow the prompts to set a strong password for each user. If these users also need administrative privileges, add them to the sudo group:
xinit@localhost:~$ sudo usermod -aG sudo alice
xinit@localhost:~$ sudo usermod -aG sudo bob
Step 3: Configure VNC password (for each user)
This is a critical step that must be performed by each user. Each user must log in and set their own VNC password (which is separate from their system login password).
This initial run also creates the necessary ~/.vnc directory and default files.
For alice:
# Switch to the new user
xinit@localhost:~$ su - alice
# Run vncserver. It will prompt you to set a password.
xinit@localhost:~$ vncserver
# Enter and verify a VNC-specific password.
# (You can decline the view-only password).
# vncserver automatically starts a session on :1.
# We don't need it yet, so kill it.
xinit@localhost:~$ vncserver -kill :1
# Log out of alice's shell
xinit@localhost:~$ exit
For bob:
Repeat the exact same process for bob.
# Switch to the second user
xinit@localhost:~$ su - bob
# Run vncserver to set the password
xinit@localhost:~$ vncserver
# ... (Enter and verify a DIFFERENT password for bob) ...
# This will also likely start on :1 (since alice's is off).
xinit@localhost:~$ vncserver -kill :1
# Log out of bob's shell
xinit@localhost:~$ exit
Now, both users have a ~/.vnc/passwd file and are ready for configuration.
Step 4: Configure xstartup for GNOME
By default, VNC starts a very basic window manager. We need to tell it to launch the full GNOME session. We'll do this by editing the ~/.vnc/xstartup file for each user.
Create the xstartup file for alice:
# As your sudo user (not as alice)
xinit@localhost:~$ sudo nano /home/alice/.vnc/xstartup
Paste the following configuration into the file. This script correctly sets up the environment variables for a modern GNOME session.
#!/bin/sh
[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
export XDG_CURRENT_DESKTOP="GNOME"
export XDG_SESSION_TYPE=x11
eval $(/usr/bin/dbus-launch --sh-syntax --exit-with-session)
exec /usr/bin/gnome-session
Save and close the file. Now, make it executable and set the correct ownership:
xinit@localhost:~$ sudo chmod +x /home/alice/.vnc/xstartup
xinit@localhost:~$ sudo chown alice:alice /home/alice/.vnc/xstartup
Copy the configuration for bob:
There's no need to re-type. Simply copy the file and set the ownership for bob.
xinit@localhost:~$ sudo cp /home/alice/.vnc/xstartup /home/bob/.vnc/xstartup
xinit@localhost:~$ sudo chown bob:bob /home/bob/.vnc/xstartup
Step 5: Create systemd services (the "multi-user" part)
To make the VNC sessions persistent and start on boot, we'll create a dedicated systemd service for each user. This is the core of our multi-user setup.
We will hard-code each user to a specific display:
- alice -> :1 (Port 5901)
- bob -> :2 (Port 5902)
Create the service file for alice:
xinit@localhost:~$ sudo nano /etc/systemd/system/vncserver-alice.service
Paste in the following service definition. Note how it's configured specifically for the user alice and display :1. The -localhost no flag is essential for allowing connections from other machines.
[Unit]
Description=TigerVNC-Server for user alice on :1
After=syslog.target network.target
[Service]
Type=forking
User=alice
Group=alice
WorkingDirectory=/home/alice
ExecStartPre=-/usr/bin/vncserver -kill :1
ExecStart=/usr/bin/vncserver -localhost no -depth 24 -geometry 1920x1080 :1
ExecStop=/usr/bin/vncserver -kill :1
[Install]
WantedBy=multi-user.target
Create the service file for bob:
We can just copy Alice's file and modify it for Bob.
xinit@localhost:~$ sudo cp /etc/systemd/system/vncserver-alice.service /etc/systemd/system/vncserver-bob.service
Now, edit the new file: sudo nano /etc/systemd/system/vncserver-bob.service.
You must change the following 7 lines:
- Description=TigerVNC-Server for user bob on :2
- User=bob
- Group=bob
- WorkingDirectory=/home/bob
- ExecStartPre=... -kill :2
- ExecStart=... :2 (at the end of the line)
- ExecStop=... -kill :2
Save and close the file.
Step 6: Start and enable the services
Now we can reload the systemd daemon and launch our new services.
# Reload systemd to read the new .service files
xinit@localhost:~$ sudo systemctl daemon-reload
# Enable and start alice's service
xinit@localhost:~$ sudo systemctl enable --now vncserver-alice.service
# Enable and start bob's service
xinit@localhost:~$ sudo systemctl enable --now vncserver-bob.service
You can check their status to ensure they are running:
xinit@localhost:~$ systemctl status vncserver-alice.service
xinit@localhost:~$ systemctl status vncserver-bob.service
You should see an "active (running)" status for both.
Step 7: Disable screen lock & sleep
This is a critical final step. By default, a GNOME session on a server will lock the screen or go to sleep after a period of inactivity. This is useless for a persistent VNC session, as you'll be unable to log back in.
We must run these commands as each user to change their personal settings. The sudo -u ... dbus-run-session ... prefix is the correct way to do this from your admin account.
For alice:
xinit@localhost:~$ sudo -u alice dbus-run-session gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0
xinit@localhost:~$ sudo -u alice dbus-run-session gsettings set org.gnome.desktop.session idle-delay 0
xinit@localhost:~$ sudo -u alice dbus-run-session gsettings set org.gnome.desktop.screensaver lock-enabled false
For bob:
xinit@localhost:~$ sudo -u bob dbus-run-session gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0
xinit@localhost:~$ sudo -u bob dbus-run-session gsettings set org.gnome.desktop.session idle-delay 0
xinit@localhost:~$ sudo -u bob dbus-run-session gsettings set org.gnome.desktop.screensaver lock-enabled false
These commands disable sleep, the idle timer, and the lock screen.
Step 8: Configure firewall (UFW)
Finally, we need to open the VNC ports in the firewall.
- Display :1 uses port 5901.
- Display :2 uses port 5902.
xinit@localhost:~$ sudo ufw allow 5901/tcp comment "VNC for alice"
xinit@localhost:~$ sudo ufw allow 5902/tcp comment "VNC for bob"
xinit@localhost:~$ sudo ufw enable
xinit@localhost:~$ sudo ufw status
Step 9: Connect!
You are all set. Grab your favorite VNC client (e.g., TigerVNC Viewer, RealVNC, Remmina).
- To connect to alice:
- Server: your_server_ip:1 (or your_server_ip:5901)
- Password: The VNC password alice set in Step 3.
- To connect to bob:
- Server: your_server_ip:2 (or your_server_ip:5902)
- Password: The VNC password bob set in Step 3.
Each user will be greeted with their own, independent GNOME desktop.
Conclusion & how to add more users
You now have a robust, multi-user VNC server. The process for adding a third user, charlie, is a simple checklist of the steps we just followed:
- sudo adduser charlie
- su - charlie -> vncserver (set password) -> vncserver -kill :1 -> exit
- sudo cp /home/alice/.vnc/xstartup /home/charlie/.vnc/xstartup
- sudo chown charlie:charlie /home/charlie/.vnc/xstartup
- Create vncserver-charlie.service (copy vncserver-bob.service), using :3 for the display and updating all user/path names to charlie.
- sudo systemctl enable --now vncserver-charlie.service
- Run the three gsettings commands for charlie (e.g., sudo -u charlie ...).
- sudo ufw allow 5903/tcp
This setup provides a scalable and isolated remote desktop environment for your entire team.