Evgeny Pokhilko's Weblog

Programmer's den

OpenGL hardware acceleration through remote X11 SSH connection


This article is about running an OpenGL application on a remote server and using the local graphics card for rendering. It can help you in different rare scenarios: 1. You have a server in your network and it has some software with graphical output. You want to use that software remotely on many computers in the network without installing it on each machine individually. 2. Your application needs specific hardware configuration or resources that are only available on the server. 3. You experiment with remote OpenGL rendering for some reason.

For demonstration we are going to play chromium-bsu running on a remote server using the local graphics card.


You should be aware of the security risk of opening X server for hardware rendering. The ssh server gets more control of the client with inderict rendering enabled.

My environment

I have a server with OpenSUSE Tumbleweed 13.2. It runs in headless mode. I also have a laptop with Lubuntu 15.10 wily that connects to the server through SSH. I will call these machines OpenSUSE and Lubuntu.


You need to be familiar with general X11 client / server and SSH concepts. Counter intuitively, in my environment the laptop acts as X server and OpenSUSE Tumbleweed as X client. At the same time, Lubuntu is ssh client and OpenSUSE is ssh server.

Direct rendering – the OpenGL application sends instructions directly to the local hardware bypassing the target X server. This is only possible with single machine. We cannot use it in our scenario.

Software rendering – software rendering engine is used without leveraging the graphics card. It can be slow.

Indirect rendering – The remote application sends instructions to the X server which transfers them to the graphics card. This is what we are going to demonstrate in this article.

Before we start

This article will not explain known topics. We assume that SSH is already configured and all packages and drivers are installed. You have a private key for ssh to connect to the server and the server authorized_keys contains the corresponding public key.

Configure OpenSUSE

We need to enable X11 forwarding in the sshd configuration file:

  1. Open /etc/ssh/sshd_config in your favorite text editor.
  2. Add or uncomment X11Forwarding yes
  3. Restart your sshd daemon

    service sshd restart

  4. Install the game

    zypper install chromium-bsu

Nothing else needs to be done on OpenSUSE.

Configure Lubuntu

  1. Enable trusted forwarding. Open or create ~/.ssh/config

    Host ForwardX11Trusted yes

Trusted forwarding is needed to enable 3D hardware rendering.

  1. Enable indirect redering. Open /etc/lightdm/lightdm.conf

Add or uncomment:

xserver-command=X +iglx

The command enables iglx, which I believe is indirect glx.

  1. Restart lightdm or reboot the X server

    systemctl restart lightdm.service

Run Chromium B.S.U

  1. Connect to the SSH server.
  2. Run chromium-bsu with the environment variables below:

    LIBGL_ALWAYS_INDIRECT=1 chromium-bsu

You can also enable debug output for LIBGL with LIBGL_DEBUG=verbose chromium-bsu

The game is already playable. I get 30 FPS.

Make it even faster

To improve the performance further we need to enable direct TCP connection to the X server rather than going through SSH. Please note that this represents a security vulnerability and disabled by default. You can only use in a trusted local network.

  1. Open /etc/lightdm/lightdm.conf

Add or uncomment:

xserver-command=X -listen tcp +iglx
  1. Open /etc/xinit/xserverrc

Commend out -nolisten tcp and another line as follows:

# exec /usr/bin/X -nolisten tcp "$@"
exec /usr/bin/X "$@"
  1. Enable X11 connection to all clients (very unsafe!):

    xhost +

Run Chromium B.S.U. with direct TCP connection

LIBGL_ALWAYS_INDIRECT=1 DISPLAY=<client-tcp>:0 chromium-bsu

This mode gave me the best possible performance. I could not distinguish between the game running locally and remotely from the server.

Troubleshooting and diagnostics

Use LIBGL_DEBUG=verbose environment variable to see warning messages. I get the following messages when the application falls back to the software rendering:

libGL error: failed to authenticate magic 1
libGL error: failed to load driver: r600
libGL: OpenDriver: trying /usr/lib64/dri/tls/swrast_dri.so
libGL: OpenDriver: trying /usr/lib64/dri/swrast_dri.so

You can also see the following message when X server does not allow iglx (+iglx option):

AIGLX: Screen 0 is not DRI capable

March 4, 2017 Posted by | Linux, Networking, SUSE | Leave a comment

How To Create and Seed a Torrent (Ubuntu server, Transmission)

Did you ever need to send somebody large files? This manual provides steps to create new torrents and seed files. The environment is Ubuntu server 12.04 and the torrent client is Transmission 2.51. Any compatible torrent client and OS can be used by the receiver.

There was a solution that was very helpful for me to create this manual. I made a few improvements in my opinion. You won’t need to create and configure a watch directory and copy your torrent files into it. I think I simplified that solution and made mine more inline with the Transmission default configuration.

We can begin now.

1. SSH to your server and install transmission-daemon if you don’t have it already.

The service is a headless torrent client that can be controlled through command line, web interface or possibly another GUI front end. We are going to use transmission-remote (see below).

sudo apt-get install transmission-daemon

The command will install and start the Transmission service.

2. Configure Transmission to be able to control it from the command line.

After the service is installed the security settings are too strict. It’s not possible to control it even from the command line. Issuing “transmission-remote -l” results in a permission error.

Stop the service with the following command:

sudo service transmission-daemon stop

The Transmission settings file in my environment is located under /var/lib/transmission-daemon/info/settings.json. If it’s not there, start the service and look at the parameters. “ps -Af | grep trans” outputs “/usr/bin/transmission-daemon –config-dir /var/lib/transmission-daemon/info”. info is the directory where settings.json is read from.

Open the settings file in vi or nano.

sudo vi /var/lib/transmission-daemon/info/settings.json

Find rpc-whitelist and rpc-whitelist-enabled. Modify them as follows:

"rpc-whitelist": "",
"rpc-whitelist-enabled": true,

These settings are also very strict but they are enough for our task. Now you can control Transmission from the same machine and nowhere else. You may consider changing them later if you want to use the web interface.

While your are still in the text editor, note the location of the Transmission downloads directory. You will need it later. This is what I have:

"download-dir": "/var/lib/transmission-daemon/downloads"

Start the service again:

sudo service transmission-daemon start

To verify that you have done everything correctly invoke this command:

transmission-remote -l

It will print a table listing your active torrents. You don’t have any at this stage so the table should be empty (see “transmission-remote –help” for the description of -l and other commands). You can use this command later to see what the service is transferring.

3. Create a bash script file with the output of the cat command below.
It will automate the process of seeding torrents in the future. I called the script seedfile.sh

cat ~/bin/seed_file.sh

cp -p $1 $TRANSDIR/downloads/
transmission-create $TRANSDIR/downloads/$1 -t udp://tracker.openbittorrent.com:80 -o $HOME/$1.torrent
transmission-remote --add $HOME/$1.torrent

Modify TRANSDIR variable if needed. $TRANSDIR/downloads should be the directory you noted at step 2. It’s the directory where Transmission downloads files to.

You can call this script as below:

~/bin/seed_file.sh file_I_want_to_send.zip

The script copies the file to the downloads directory (make sure that the file you are sending has enough permissions to be read by debian-trasmission user). Then the torrent file is created in $HOME. You can send the torrent to the people receiving the zip file. Finally we add the torrent to our service. When the service receives the torrent, it will know that the zip file already exists in the downloads directory (see the cp command) and it will skip to the Done state as if the file has been downloaded. The seeding will start at this point. Download the torrent file from the server and distribute it to the people on the receiving end.

A few notes on the tracker. You can see the transmission-create -t parameter in the script. The tracker is needed to coordinate peers before they are connected. Once the connection is established it’s not used. You can use any available tracker of choice.

Hope you find this manual useful.

January 11, 2015 Posted by | Linux, Torrent | , | 2 Comments

Run a bash script with sudo, nohup and in the background

This command will run script.sh under super user and you can disconnect and come back later:

sudo nohup bash script.sh &

It’s useful if you don’t have Screen or you want the process to close when it finishes without a screen session hanging around.

By default, the output will go to nohup.out. You can change it by redirecting it to a file:

sudo nohup bash script.sh > script.out &

nohup runs a command immune to hangups. It redirects input and output of the process. If you want to connect to the server again and see the output, use tail, as below:

tail -f script.out

The command will  be printing output as your command produces it as if it runs in your terminal session. Ctrl-C will terminate tail but not the nohup command.

If you need to kill the command before it finishes, find the process id first with:

sudo ps -Af | grep “bash script.sh”
sudo kill <process id>

I hope it helps.

February 20, 2012 Posted by | Linux, Networking | | 3 Comments