Jailed Desktop Environment (TrueNAS CORE)

It is not easy to find guides for FreeBSD. In this guide, I explain with a near step by step how to:

  • install a KDE5 or GNOME 3 GUI in a jail
  • remote control the jail using either VNC or the X11 forwarding
  • install VNC as a service started on jail boot
  • properly setup a secure SSH connection, SSH tunnel and X11 forwarding through SSH
  • install a few graphical applications like mkvtoolnix-gui, qbittorrent, sakura, dolphin

My fist need was to remux a few videos directly on TrueNAS instead of doing it from a Windows machine through SMB, loosing both bandwidth and ZFS/ECC checksum during file operations.

There is no images, feel free to ask questions
I also did not go in the basics like adding users or explaining vncserver command options. There are a lot of guides for that.

Setup a jail with VNC and GUI

I assume a working jail with network access is setup, we name it “xgui”
Create a user to which we will login using teh remote session
I assume in this guide the user “admin”
Ensure you create a password for your user, because KDE and GNOME won’t accept an empty password at the login prompt !
For security reasons, set also a password for user root
Only add the mountpoints you need in ro, and some temp smb directories in rw, again for security reasons

Login to the jail

root@truenas:~ #
iocage start xgui
iocage console xgui

First update packages

root@xgui:~ #
pkg update

Install X Window: xorg

This is the X Window System used to provide a graphical environment in BSD
It is needed for all BSD desktops which are based on Xorg (KDE, XFCE, Gnome)
pkg install xorg

Install TigerVNC

This is by far the most maintained VNC client
pkg install tigervnc-server

Run VNC for the first time to setup config files

First login as the user under which we will start VNC sessions so that the config files are created under the user home directory, and not root home directory
I will assume a user called admin was created
su - admin

admin@xgui:~ $

enter the password, skip a view only password unless needed to change password:

rm ~/.vnc/passwd

Exit vncserver

vncserver -kill :1

Check the xstartup file vnc created:

by default, TigerVNC will start twm GUI and will start a small graphical terminal, xterm, no edits should be needed to test an xterm session with twm
cat ~/.vnc/xstartup

[xstartup][default] {

OS=`uname -s`
if [ $OS = 'Linux' ]; then
  case "$WINDOWMANAGER" in
      if [ -e /etc/SuSE-release ]; then
        export PATH
if [ -x /etc/X11/xinit/xinitrc ]; then
  exec /etc/X11/xinit/xinitrc
if [ -f /etc/X11/xinit/xinitrc ]; then
  exec sh /etc/X11/xinit/xinitrc
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
twm &

} [xstartup][default]

Test an xterm VNC remote session

vncserver :1 -localhost no

Connect to the VNC server from Windows RealVNC VNC Viewer

We should see the xterm console

Edit xstartup file to support kde, xfce and gnome

admin@xgui:~ $
nano ~/.vnc/xstartup
[xstartup][Final] {

# Options: gnome, xfce, kde

# xsetroot: is a program that allows you to tailor the appearance of the background ("root")
# window on a workstation display running X (xorg). Any X dialog will have that look
OS=$(uname -s)
if [ "$OS" = 'Linux' ]; then
  case "$WINDOWMANAGER" in
      if [ -e /etc/SuSE-release ]; then
        export PATH
if [ -x /etc/X11/xinit/xinitrc ]; then
  exec /etc/X11/xinit/xinitrc
if [ -f /etc/X11/xinit/xinitrc ]; then
  exec sh /etc/X11/xinit/xinitrc

# Start and bind to desktop
if [ "$desktop" = "gnome3" ]; then
    # Start Gnome 3 Desktop
    [ -r "$HOME/.Xresources" ] && xrdb "$HOME/.Xresources"
    vncconfig -iconic &
        dbus-launch --exit-with-session gnome-session &
elif [ "$desktop" = "xfce" ]; then
    # Start xfce GUI
    [ -r "$HOME/.Xresources" ] && xrdb "$HOME/.Xresources"
    xsetroot -solid grey
    startxfce4 &
elif [ "$desktop" = "kde" ]; then
    # Start KDE Plasama
    [ -r "$HOME/.Xresources" ] && xrdb "$HOME/.Xresources"
    xsetroot -solid grey
    startplasma-x11 &
    # Start default xterm with twm
    [ -r "$HOME/.Xresources" ] && xrdb "$HOME/.Xresources"
    xsetroot -solid grey
    xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
        twm &

} [xstartup][Final]

Install KDE:

KDE is probably the most supported desktop environment for FreeBSD
First, install SDDM display manager, needed for KDE (equivalent of GDM for gnome)
The display manager offers a graphical login page and sessions manager
pkg install sddm

Install kde desktop:

Full package
pkg install kde5

Minimal package (our choice)
pkg install plasma5-plasma

Base apps only
pkg install kde-baseapps

Set KDE and needed services to launch on start by adding these lines at end of /etc/rc.conf
Note: We can safely disable the line kde5_enable because our system is headless
The KDE desktop will be started by vncserver when launched

  • moused_enable: [NO MORE NEEDED] mouse support in xorg
  • hald_enable: [NO MORE NEEDED] HAL kernel layer for graphics support in xorg
  • dbus_enable: kernel messaging system, needed for proper working of KDE
  • sddm_enable: the SDDM display manager to display a login session
  • kde5_enable: we start the desktop manually with VNC
    nano /etc/rc.conf
    Enable KDE services on start

Or enable the services just by running

sysrc dbus_enable="YES" && service dbus start
sysrc sddm_enable="YES" && service sddm start

Mount /proc because it is needed by kde (even if it seems to work without it !)

Note: the above /etc/rc.conf services must be enabled before adding /proc to fstab

iocage stop xgui
iocage set mount_procfs=1 xgui

Fix file name support in UTF-8
KDE by default, doesn’t display UTF-8 file names
It doesn’t read the config in /etc/login.conf or ~/.login_conf
French chars in file names “é, à…” will not be properly handled in apps
To Fix this:
iocage console xgui

Login as the user running VNC and thus starting KDE
su - admin

Create this startup file for KDE
nano .config/plasma-workspace/env/locale.sh

[locale.sh] {
export LANG=en_US.UTF-8

} [locale.sh]

restart the jail or the VNC session
file names with special characters should be properly handled now

Add double click support to select items
KDE GUI / System settings / Workspace / Workspace Behavior / General Behavior
Clicking files and folders: Selects them

[OPTIONAL] Install gnome3

Also needs xorg we previously installed
This is probably the least supported desktop environment for FreeBSD
There are two flavours, gnome3 and gnome3-lite
The Lite edition only includes the minimal components to get a working GNOME 3 Desktop.
The user then has to install preferred applications like editor, web browser or e-mail client.
If you wish to install the full desktop after having installed gnome3-lite, look below
Note: Both flavours will automatically install gnome-desktop and gdm dependencies
- gdm: the display manager for the login page and session manager
- gnome-desktop: the graphical desktop

BUG: currently, there is an old bug still present. The login graphical page does not accept
password through a VNC connection. It is reported to be a refresh issue

We install the lite version (gdm, gnome-desktop and xorg are automatically installed as gnome3-lite dependencies)
pkg install gnome3-lite

Alternatively, install full gnome3 with all apps (gdm, gnome-desktop and xorg are automatically installed as gnome3 dependencies)
pkg install gnome3

To migrate from the lite to the full version:

pkg delete gnome3-lite
pkg install gnome3

Set gnome3 and needed services to launch on start by adding these lines at end of /etc/rc.conf
Note: We can safely disable the line gnome_enable because our system is headless
The gnome3 desktop will be started by vncserver when launched
nano /etc/rc.conf
Enable Gnome services on start

Mount /proc because it is needed by gnome3 (even if it seems to work without it !)
Note: the above /etc/rc.conf services must be enabled before adding /proc to fstab
root@truenas:~ #
iocage stop xgui
iocage set mount_procfs=1 xgui

Reboot the jail from main TrueNAS host

iocage restart xgui

VNC Server setup: Manual or using SSH Tunnel

Manually start vncserver for the user admin using our installed desktop

-localhost no: allow connecting remotely, we will disable it later

su - admin
vncserver :5 -depth 24 -geometry 1920x1080 -localhost no

Test we can properly connect using VNC Viewer


If ok, stop the VNC server

vncserver -kill :5

Enable SSH tunnel to secure VNC connection

- First we setup the SSH service on the jail

root@xgui:~ #
sudo nano /etc/ssh/sshd_config
Port 15850
PermitRootLogin no
AuthenticationMethods “publickey,password”
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM no
# Enable this for the SSH tunnel
AllowTcpForwarding yes

- Enable sshd daemon on boot, and start it

sysrc sshd_enable=“YES”
service sshd start

- Create the private/public key pair for user admin

When prompted, you must set a passphrase for openssl to generate the private key

openssl genrsa -aes256 -out privatekey.pem 4096

- Extract public key from the private key and put it in /admin/.ssh directory

+ We first create and properly set permissions on the directory and public key file

su - admin

admin@xgui:~ $
mkdir .ssh
chmod 700 .ssh
#chown admin:smb_admin .ssh
touch .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
#chown admin:smb_admin .ssh/authorized_keys

+ Extract the public key at the location set in sshd_config (authorized_keys)

root@xgui:~ #
ssh-keygen -y -f privatekey.pem >/home/admin/.ssh/authorized_keys

Restart sshd service

service sshd restart

Setup Bitvise Client for SSH access to xgui server

- in bitvise, create a new profile

- Host: IP of xgui server: JAIL_IP

- Port: 15850

- Client key manager / Import

- Select the privatekey.pem file previously created by openssl

- Passphrase: enter the passphrase we set for the private during creation

- add a comment to easily identify the key: “PC for admin@xgui Jail”

- Client key manager / Select the imported key / Change passphrase

- Remove the passphrase by entering old one, and leaving New fields empty

Bitvise cannot save the passphrase and we must remove it to avoid having a prompt for the passphrase each time

- For security, export a backup of the private key, with a passphrase

- Username: admin

- Initial method: publickey+password

- Client key: Profile (select key profile we setup in “Client key manager”)

- Passphrase: greyed if we did not set one or we removed the passphrase

+ it is the certificate passphrase we decided to remove once the key is imported in Bitvise

- Store encrypted password in profile: checked

+ User password will be saved, in an encrypted format, in Bitvise profile

- Password: enter the password for user “admin”

- Enable password over kbdi fallback: unchecked

+ Else, we will get the prompt for user password even if we saved it

- Elevation: default

- Options tab: select which programs to open on start: none since we will be using it for the VNC tunnel

Test the SSH access and manually open terminal

Setup SSH tunnel for VNC access to xgui server using Bitvise Client

VNC is an unencrypted protocol and the server as we previously setup with “-localhost no”

will listen on all interfaces. Any remote client can connect to the server.

The password, being non-encrypted, can be easily sniffed on the local network

The workaround is:

- Setup an SSH tunnel on the client that will listen to local client interface

- Set VNC Server to only accept connections and listen on the interface (localhost of the server)

- In VNC Client: we set destination IP to the client localhost interface rather than to the IP of the remote VNC Server

- The SSH client running the tunnel will forward the connection on the local client port to the remote server

The connection will use SSH and be forwarded to localhost:remote_port of the server

Steps for Bitvise: we setup C2S (Client to Server) SSH port forwarding

- Bitvise GUI / xgui Jail SSH profile / C2S Tab

+ Add

+ Enabled: check

+ Listen Interface: (or localhost)

+ List. Port: 5905

+ Destination Host: localhost

It is important that Destination Host is set to localhost

It is the target VNC Server listening interface that we will set to localhost

+ Dest. Port: 5905

+ Comment: TigerVNC #5

+ SSH Login to the server in Bitvise

- VNC Viewer / Edit VNC Connection

+ VNC Server: localhost:5905

instead of the JAIL_IP:5905

- Test the VNC connection and if it is ok, we can proceed to next step

- Restrict VNC Server to listen only on localhost, that is, it will accept only connections from a local user

and not from any other interface

admin@xgui:~ $
vncserver :5 -depth 24 -geometry 1920x1080 -localhost yes


Start VNC server as a service, on jail boot


We will use display #5 (port 5905) and user admin

First, create the service daemon file

root@xgui:~ #
nano /usr/local/etc/rc.d/vncserver

[vncserver] {

Download this file

cd /usr/local/etc/rc.d && fetch --no-verify-peer https://gist.githubusercontent.com/PhilZ-cwm6/bdc85494725bd1c1443b4db0f7f306e4/raw/64f22491e41b04398c69a80773aaa042f5ed0d64/vncserver

Make the file executable with:

/usr/local/etc/rc.d/vncserver (chmod +x)

add to /etc/rc.conf


Edit below variables for the VNC server options

PROVIDE: vncserver


. /etc/rc.subr



load_rc_config $name


: ${vncserver_user=“admin”}
: ${vncserver_enable=“NO”}
: ${vncserver_display=“5”}
: ${vncserver_depth=“24”}
: ${vncserver_geometry=“1920x1080”}
#: ${vncserver_localhost=“no”}
: ${vncserver_localhost=“yes”}

CMD=“$VNCSERVER :${vncserver_display} -depth ${vncserver_depth} -geometry ${vncserver_geometry} -localhost ${vncserver_localhost}”
su -l ${vncserver_user} -c “${CMD}”

CMD=“$VNCSERVER -kill :${vncserver_display}”
su -l ${vncserver_user} -c “${CMD}”

host=$(hostname -s)
[ -f “/home/${vncserver_user}/.vnc/${host}:${vncserver_display}.pid” ] && run_rc_command stop
run_rc_command start

run_rc_command “$1”

} [vncserver]

Set the service script as executable

chmod +x /usr/local/etc/rc.d/vncserver

Test the service

This should start the service on display :5 and under user admin

root@xgui:~ #
service vncserver onestart
service vncserver onestop
service vncserver onerestart

Enable the vncserver servcie on boot

sysrc vncserver_enable=“YES”

- Alternatively, add this line to /etc/rc.conf


Restart the jail, we should be able to connect using VNC Viewer and Bitvise SSH tunnel


Take a snapshot of our configured jail


Commands to take, restore and delete a jail snapshot:

iocage snapshot xgui -n “manual-2022-01-27_17-38-vnc-tunnel-service”
Snapshot: dataset/iocage/jails/xgui@manual-2022-01-27_17-38-vnc-tunnel-service created.
iocage rollback -n “manual-2022-01-27_17-38-vnc-tunnel-service” xgui
iocage snapremove -n “manual-2022-01-27_17-38-vnc-tunnel-service” xgui


Install Sakura terminal


pkg install sakura
New packages to be INSTALLED:
sakura: 3.8.4
vte3: 0.64.2_1

Configure Sakura useful hot keys

Sakura uses hotkeys with Accelerator+Key

Accelerator is a combination of keys defined as:

- Shift key: 1
- Scroll lock key: 2
- Ctrl key: 4
- Alt key: 8
- Windows key: 64

Below config changes will do:

- Increase font size to 14 pt

- Ctrl+T: new TAB

- Ctrl+W: delete current TAB

- Ctrl+Right/Left: change TAB

- Ctrl+Minus/Plus: font size

su - admin
nano ~/.config/sakura/sakura.conf
font=Ubuntu Mono,monospace 14


Install mkvtoolnix / dolphin file manager…


These are all X Window apps, so they need either xorg or the X11 forwarding to run

In X Org mode, we can start them directly from KDE Desktop in VNC

MKVToolnix (X Win)

pkg install mkvtoolnix

File manager (X Win)

pkg install dolphin

qBittorrent (X Win)

- Note: There is a package flavour “qBittorrent-nox” for No X11 that can run as a service without X11 needed

The “qBittorrent-nox” version can be accessed by enabling its web UI in conf files

- The quarterly repo contains an outdated version 4.3.9

pkg install qbittorrent
Updating FreeBSD repository catalogue…
FreeBSD repository is up to date.
All repositories are up to date.
The following 2 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        libtorrent-rasterbar: 1.2.14,1
        qbittorrent: 4.3.9

Proceed with this action? [y/N]: n

- We switch to latest repo, but better in a clone and different jail

cp /etc/pkg/FreeBSD.conf /usr/local/etc/pkg/repos/FreeBSD.conf
nano /usr/local/etc/pkg/repos/FreeBSD.conf
FreeBSD: {
url: “pkg+http://pkg.FreeBSD.org/${ABI}/latest”,
mirror_type: “srv”,
signature_type: “fingerprints”,
fingerprints: “/usr/share/keys/pkg”,
enabled: yes

- If pkg install gives unrecoverable errors, run

#pkg update -f

- Get the latest qbittorrent and its missing library for offline install

pkg fetch -o ./ qbittorrent libtorrent-rasterbar

- In xgui, jail, install the downloaded packages

pkg add qbittorrent-4.4.0.pkg libtorrent-rasterbar-1.2.14,1.pkg


Run remote graphical apps using Remote X11 Access


Another way to run graphical apps in a FreeBSD jail remotely controlled from Window is using

remote X11 access with X11Forwarding in SSH.

Unlike VNC, the X Server rendering the graphics is not run locally (xorg) but on the remote machine

That’s why, the remote machine is often called the server, because it runs the X Window Server

In Windows, the X Window servers are “Xming” and the most updated opensource “VcXsrv”

Other Linux X Window servers can be used with Windows for Linux Subsystem, or Cygwin

However, many X apps are designed on the assumption that the X Window server is running locally (xorg in FreeBSD)

They can have a heavy anti-aliasing and other effects not properly suitable on a slow LAN

A few important differences and limitations in X11:

- VNC exports a whole session, desktop and all,

while “ssh -X” will run a single program and show its windows on your workstation.

- VNC server exports a session that survives even when you disconnect your screen,

and you can reconnect to it later with all the windows open etc.

This is not possible with an ssh X tunnel, since when your X server dies, the windows go away.

- With ssh X, the remote machine must stay awake to proceed the remote app tasks.

VNC will keep the remote Server independent while running the app, just like Windows RDP

First, we install xauth and a sample X terminal to test:

pkg install xauth xterm

And setting SSH server like above + add below entries to allow X11 Forwarding

sudo nano /etc/ssh/sshd_config
#AllowAgentForwarding yes
AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
X11DisplayOffset 10
# Only listen on localhost address:
X11UseLocalhost yes
#PermitTTY yes

If you get the error: X11 forwarding request failed on channel 0

Or have connection issues, try “X11UseLocalhost no” to allow listening on ALL interfaces (less secure)

X11UseLocalhost no
# Disable listening on IPv6 interface:
AddressFamily inet

In jail, edit the hosts file [OPTIONAL]

Use the IP and hostname of the jail. When you ssh in with X11 forwarding,

it will try to resolve the machine’s hostname. This tells it to use the IP address of the jail.

nano /etc/hosts
JAIL_IP xgui

Install “VcXsrv X Window Server” on the Windows machine that will control the GUI apps remotely

It will be the X Window Server

The Client running the app, will send the GUI coordinates to the X Window Remote server

The X Server is responsible of rendering the graphics on the remote machine where the user is sitting

- Start XLauncher (VcXsrv X Window Server)

- Select display settings: Multiple windows

- Display number: 10

This is the display selected by default in sshd_config “X11DisplayOffset”

- Click Next

- Select how to start clients: Start no client

- Click Next

- Extra settings: Disable access control

Enable X11 forwarding on the SSH client (Bitvise, puTTy) on the Windows Machine

- In Bitvise: after setting a proper SSH connection like above

+ Terminal tab

+ X11 Forwarding: checked

+ Display:

- In Linux/Unix:

+ edit the client ~/.ssh/config file with these lines:

    ForwardAgent yes
    ForwardX11 yes

+ start ssh session with

ssh -v -X user@host

Test an xterm graphical terminal by running from SSH client:

You should get a new X11 terminal window in your Window machine


1 Like

Posting over from old forum, as I found this guide extremely useful. I will edit it as I can to keep it clean.