Page: 0 1
VNC + Ubuntu 22.04
Date: 3/5/2024
Tags: linux remote-desktop
My local Linux server is Intel Nuc running Ubuntu. A few months ago I upgraded from 18.04 to 22.04, seemed like a reasonable thing to do. In the process I lost the ability to vnc into the server and use the desktop graphically. Originally I was using this command to run the vnc server:

tigervncserver -geometry 2400x1350 -depth 24 -localhost no :1

Worked wonderfully on 18.04. Not so much on 22.04, something to do with the gnome session not starting up after the VNC connection was established. I spent hours and hours over the course of the last few months trying to debug that. But got nowhere. The logs didn't give me anything useful, and my google searches for various errors were all dead ends. Then I had some success with using the built in gnome-remote-desktop features (accessed from the main settings app's sharing -> remote desktop -> ...) on my 22.04 machine at work. So I thought today... "I'll try that!".

It did not go well.

Firstly after enabling it and attempting to connect all I got was a hung connection. No window appeared on the client end (Windows 10). I knew it was running because I checked it was listening on the right port:

matthew@nuc:~$ sudo lsof -i -P -n | grep 5900
gnome-rem 22207         matthew   10u  IPv6 249744      0t0  TCP *:5900 (LISTEN)

Nice, good to know. But what is 'gnome-rem'?

matthew@nuc:~$ ps -A | grep gnome-rem
  22207 ?        00:01:11 gnome-remote-de

Ha, slightly more info.

matthew@nuc:~$ ps -fp 22207
UID          PID    PPID  C STIME TTY          TIME CMD
matthew    22207    1075  6 11:11 ?        00:01:11 /usr/libexec/gnome-remote-desktop-daemon

Ah, so what is 'gnome-remote-desktop-daemon' anyway?

matthew@nuc:~$ dpkg -S /usr/libexec/gnome-remote-desktop-daemon
gnome-remote-desktop: /usr/libexec/gnome-remote-desktop-daemon

Ok so the 'gnome-remote-desktop' package is what's providing the actual functionality. So what else is in that package?

matthew@nuc:~$ dpkg -L gnome-remote-desktop

Alright... hmmm, grdctl? What is that?

matthew@nuc:~$ grdctl --help
Usage: grdctl [OPTIONS...] COMMAND [SUBCOMMAND]...
  rdp                                        - RDP subcommands:
    enable                                   - Enable the RDP backend
    disable                                  - Disable the RDP backend
    set-tls-cert               - Set path to TLS certificate
    set-tls-key                 - Set path to TLS key
    set-credentials      - Set username and password
    clear-credentials                        - Clear username and password
    enable-view-only                         - Disable remote control of input
    disable-view-only                        - Enable remote control of input

  vnc                                        - VNC subcommands:
    enable                                   - Enable the VNC backend
    disable                                  - Disable the VNC backend
    set-password                   - Set the VNC password
    clear-password                           - Clear the VNC password
    set-auth-method password|prompt          - Set the authorization method
    enable-view-only                         - Disable remote control of input
    disable-view-only                        - Enable remote control of input

  status [--show-credentials]                - Show current status

  --help                                     - Print this help text

At this point I played around with the vnc settings, setting a password... trying the set-auth-method options etc. Not much changed. So I thought well... it's "Open Source" right? I could like... GET the source and have a look right?

matthew@nuc:~$ /usr/libexec/gnome-remote-desktop-daemon --version
GNOME Remote Desktop 42.9

Ok, googled the source archive for that and got this. Download and unpacked that onto the nuc server and had a look. Fairly standard meson package... nice.

So I mkdir'd a build folder and installed meson. It complained there were many missing libraries. So I worked my way through them all, using apt-cache to find the -dev lib and apt install'ed each of them. Finally I could build gnome-remote-desktop locally.

From the build folder I found an x64 binary: ./src/gnome-remote-desktop-daemon

Perfect. Ok, lets stop the system one:

systemctl --user stop gnome-remote-desktop

And to make seeing the logging easy I decided to co-opt the logging to just printf to the screen. So in src/grd-daemon.c, the main function, I added:

g_log_set_default_handler(printf_log, NULL);

Where 'printf_log' is defined as:

void printf_log(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
  printf("%s:%i:%s\n", log_domain?log_domain:"-none-", log_level, message);

Super simple, but makes all the logging way easier to see. Now that that works. I ran ./src/gnome-remote-desktop-daemon and tried to connect.

Still no joy. But I was getting a 'New VNC client' in the logging. So kinda hopeful right? Well I greped the code and found the 'handle_new_client' function. Nice, it seems to get the auth method and handle it. First things first, lets log the auth method so I know what we're dealing with. It was GRD_VNC_AUTH_METHOD_PROMPT. Ok. Well what if we tried GRD_VNC_AUTH_METHOD_PASSWORD? How do I change that? Well... remember that grdctl tool?

grdctl vnc set-auth-method password

Run it again... and this time the client asks for a password! Hurrah... seems like I'm making progress. However once the password is entered the client says "unexpected error". So where are the credentials checked? check_rfb_password seems like it does that. And reading through that found:

memcmp (challenge_encrypted, response_encrypted, len)

I added some logging and checked the result... and? It's ok! The password checks out as correct. But yet... the client complains. Interesting. Something in the logging caught my attention:

-none-:16:Failed to record monitor: GDBus.Error:org.freedesktop.DBus.Error.Failed: Unknown monitor

A little googling of that error resulted in finding some forum posts about how the backend doesn't want to function on a headless machine. Which is not great, but at least I could try plugging a monitor in. So I grabbed a long HDMI cable and plugged it into my PC monitor's second port... just so it's attached to _something_ rather than nothing.

Tried to reconnect and .... SUCCESS! A remote desktop!

I have bought a little HDMI display emulator to trick it into thinking there is a monitor. And maybe someday it'll run headless properly... but I think for the moment I'm just happy it works at all. Open source is great... and a pain all at the same time. I doubt I'd even have this trouble with Windows or Mac. It does just seem to work out of the box a little better.
(0) Comments | Add Comment

Gtk3 bugs on Debian (Gnome WM)
Date: 26/6/2021
Tags: linux gtk3 debian
So over the last month I've been poking at Lgi (the framework Scribe uses) on Debian trying to fix the numerous graphical glitches in the GTK3 port. And I've come to the realization that it's just horribly broken. Unlike the Ubuntu 16/18/20 installs I have that "just work". Debian seems to include the window shadow in all the coordinates. WTF? So mouse cursor x/y values are +24 compared to the window. (Ie if you move the mouse to the top left corner it's still 26,28 or something) Setting the size of the window results in a GTK_CONFIGURE message with a wildly different rectangle (out by something like 24 x 2?). Leaving all the controls in the window scaled off the right and bottom edges. None of the invalidation of dirty client content work correctly. And on top of that they use a different glib version.

They cookin up a mess over there in Debian land. So in the short to medium term I'm just going to not support Debian. Unless someone wants to chime in with some good ideas.
(0) Comments | Add Comment

Setting a DNS domain search in Ubuntu 20
Date: 10/3/2021
Tags: linux
There doesn't seem to be many good results for that search in Google so I'm documenting it. If you want to have an automatic domain suffix set for DNS in Ubuntu 20 you need to edit:

sudo nano /etc/systemd/resolved.conf

And uncomment the Domains field like this:


Then restart the service:

sudo service systemd-resolved restart

or reboot.
(0) Comments | Add Comment

Vnc startup on recent Ubuntu for Gnome
Date: 4/12/2020
Tags: linux
It's been bugging me for ages that there doesn't seem to be a valid recipe to use the Gnome desktop on Ubuntu under VNC. There are lots of "recipes" out there, mostly for older version of Ubuntu, but often they force a change of window manager or just plain don't work.

Anyway, after some time of hobbling along with a half working VNC server, I stumbled upon a working setup and though it was high time I documented it.

My .vnc/xstartup for Gnome:
[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
vncconfig -iconic &

dbus-update-activation-environment --all
dbus-launch --exit-with-session gnome-session --session=ubuntu &
gnome-shell &
(0) Comments | Add Comment

UDP and Ubuntu 14/Windows incompatibility
Date: 14/9/2017
Tags: linux ubuntu networking
For the last few weeks I've been mucking around in the background with an application I've called "ClipShare" that basically sits on the network and allows you to copy and paste between different machines. It supports text, images and files at the moment. I'm sure such a thing already exists but I like how it auto-detects all the machines running it on the network via UDP broadcast and supports Windows, Mac and Linux. It's far from production ready, it still crashes a bit and hangs up during file transfers sometimes. But over time I'm sure I'll iron that out.

Things like Samba, VNC and VM's (Vmware/Virtualbox) tend to have support for things like clipboard and file sharing. But in my experience they break very easily and it's 50/50 if they'll work or not. Hence having an alternative for getting the data across.

In testing I had a Ubuntu 14 VM running on a Windows host and for the life of me couldn't get the UDP packets to go from Ubuntu to Windows. I could see the packets arriving in Windows land via Wireshark but the recvfrom wouldn't get the packet. The packet wasn't large, just 40 bytes or so. In researching the issue I found that IP packets have a checksum, so I figured out how to get Wireshark to test the checksum. It confirmed the checksum was good. I could see using 'netstat -s' that there was an increasing count of 'Received Packets Discarded'. So Windows for reasons unknown was discarding the UDP traffic from Ubuntu. I tried turning off the Windows Firewall. No difference.

So then I decided to spin up my Ubuntu 16 VM and test the exact same code there. And sure enough it's working fine. So in conclusion I believe that at the OS level, Ubuntu 14 has some busted networking code. I can't tell what's wrong. Maybe it's a Windows thing. But it's basically meant I'm moving to Ubuntu 16 for all my Linux dev stuff. The main reason I had a Ubuntu 14 environment was that I had a working Raspberry Pi cross compiler install and I hate messing with a working env just for the sake of upgrading. However that broke recently anyway so it seems that the last reason for keeping 14 just disappeared.

Fun times.
(1) Comment | Add Comment

sem_post funkiness on Linux
Date: 9/8/2017
Tags: linux
I moved the Linux implementation of the GThreadEvent class (.h, .cpp) over to the sem_open, sem_post, sem_wait calls a little while back.

Initially I used named semaphores and that seemed to work ok. But after a few weeks I noticed that sometimes the call to sem_post would just quietly NOT increment the semaphore count, while still returning 0 (Success). Which causes the listening thread blocking in sem_wait to never wake up. Crucially this would break the destructor / exit loop of GEventTargetThread.

Googling this didn't turn up anything useful. I believe I was using the API correctly and the documentation is very sparse. Anyway I implemented the semaphores using the sem_init/sem_destroy (anonymous) and it seems to be robust. Still, I'd like to know what the deal is with the named ones. The general pattern of behaviour I would see is:
  • Thread 1: Create using sem_open
  • Thread 2: Block on sem_wait
  • Thread 1: Start shutdown - calls sem_post (returns 0, but no increment) to tell thread 2 that it needs to exit.
  • Thread 2: Still stuck blocking on sem_wait...
Fun times. I checked it under valgrind and no weird memory accesses. Sometimes it would work ok and exit gracefully. But most of the time it would hang.
(0) Comments | Add Comment

Merry Christmas
Date: 24/12/2015
Tags: scribe linux
I think for the first time ever? There is a simultaneous release of Scribe on 3 different platforms: Windows, Mac AND Linux. The new v2.1.3 build is tri-platform. The Linux (x64) build is a GTK2 app and runs ok on Ubuntu and Arch. Well that's all I've tested at this point.

It also runs on a Raspberry Pi 2 although it's a little slow. I know because I got bored and tried building it while working on some MC2 stuff.

Links to the i.Scribe builds:
(0) Comments | Add Comment

Portable OpenSSL for Linux
Date: 21/12/2015
Tags: shared-object linux openssl scribe
A year ago I worked out how to make a portable build of OpenSSL for Mac. And now with the imminent release of the Linux build of Scribe I need to do the same with the Linux build of OpenSSL.

After downloading and unpacking OpenSSL I configured it with:
./config shared -DPURIFY
The reason for adding the -DPURIFY #define is to suppress valgrind errors related to uninitialized memory usage.

Once that is built I had a look at the shared object paths with ldd:
matthew@ubuntu:~/Downloads/openssl$ ldd ./ =>  (0x00007ffc0e197000) => /lib/x86_64-linux-gnu/ (0x00007f5c5ab6c000) => /lib/x86_64-linux-gnu/ (0x00007f5c5a7a7000) => /lib/x86_64-linux-gnu/ (0x00007f5c5a5a3000)
	/lib64/ (0x00007f5c5b1c1000)
So it's not portable yet. I initially tried using the chrpath command but it can only modify existing RPATH records. My binary doesn't have any RPATH yet. So that didn't work. The next thing I tried was the patchelf command from here:
After building and installing I issued this command in the OpenSSL folder:
patchelf --set-rpath '$ORIGIN' ./
Now to check if libssl pulls in the local libcrypto:
matthew@ubuntu:~/Downloads/openssl$ ldd ./ =>  (0x00007ffcdce86000) => /home/matthew/Code/Scribe/trunk/./ (0x00007f39b99d8000) => /lib/x86_64-linux-gnu/ (0x00007f39b9613000) => /lib/x86_64-linux-gnu/ (0x00007f39b940f000)
	/lib64/ (0x00007f39ba0a5000)
Yes! Now this build can be installed in the same folder as the Scribe binary and Scribe will use it without interfering with the system OpenSSL which is often out of date, or not built with -DPURIFY or missing.
(0) Comments | Add Comment