Post

RustDesk

Another experiment with self-hosted remote desktop control. This one is promising.

About a week ago I experimented with selfhosting MeshCentral and while the experiment itself was a success, being restricted to remotely controlling other computers from a web browser prevented certain controls I regularly use from being passed through to the clients, which would ultimately slow me down. After taking to the Internetz I came across another free open source remote desktop client: RustDesk. Selfhosting the relay server is optional however you can also use direct IP connection to improve responsiveness. Naturally I wanted to selfhost the relay server so I did.

RustDesk has a UI very similar to TeamViewer and AnyDesk and near identical functions. An ID number and one-time password are generated for your computer (you have the option of creating permanent passwords in the Security options) and you can input the ID of the computer you wish to control. You can also add previous connections to a favorites list, give computers nicknames, and it has an address book and groups can be created like in MeshCentral. Just like with TeamViewer and AnyDesk though, the address book and group management are paid features. This doesn’t bother me though, the Favorites tab is sufficient for my needs. As long as RustDesk doesn’t incorrectly suspect me of commercial use, I’m fine with what we get in the free tier.

RustDesk

Installation took me a minute because the official documentation isn’t very well laid out. Specifically the section labeled Ubuntu Server, which is the only Linux distro referenced, only has a link pointing to installing in Docker. The general install section had what I needed, which I actually found on Github before I discovered it in the official docs. I created an LXC container with a single CPU core, 512MB of RAM, 2GB of drive space, and the Debian 12 CT template. I also gave the network adapter a static IP.

The documentation first requires SSH access be enabled, so once the container was created I enabled root SSH access because I don’t create additional accounts in my containers unless necessary (e.g. selfhosted cloud storage). To do this I added PermitRootLogin yes to the end of the SSH daemon config file.

1
root@RustDesk:~# nano /etc/ssh/sshd_config
1
2
3
4
5
6
7
8
# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server

PermitRootLogin yes

Next was installing and configuring the Uncomplicated Firewall (UFW). Port 8000 is for the auto-generated install files and the RustDesk HTTP server, according to the documentation, and the other ports are for the RustDesk relay server connections.

1
root@RustDesk:~# apt install -y ufw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@RustDesk:~# ufw allow proto tcp from [IP of LXC container] to any port 22
Rules updated

root@RustDesk:~# ufw allow 21114:21119/tcp
ufw allow 8000/tcp
ufw allow 21116/udp
ufw enable
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Firewall is active and enabled on system startup

Note above that the ufw enable command does not have sudo in front of it. This is because everything is being run as the root user. If I were running this in a virtual machine or bare metal installation where a non-root user account was created, I would include the sudo.

Time to download techahold’s script.

1
root@RustDesk:~# wget https://raw.githubusercontent.com/techahold/rustdeskinstall/master/install.sh

Ordinarily I would do a chmod +x and run the script, but since the script includes numerous instances of sudo these needed to be removed, as I found out after failing to run it the first time.

1
root@RustDesk:~# nano install.sh

Using Ctrl+W to search for all instances of sudo I could then delete them all and save the script with Ctrl+O and then exiting with Ctrl+X. Now I could run chmod +x and run the script.

1
2
root@RustDesk:~# chmod +x install.sh
./install.sh

After running apt update the script first asks you your preferred connection method:

1
2
3
1) IP
2) DNS/Domain
Choose your preferred connection method: auto-resolve current WAN IP or enter your DNS/Domain:

I chose IP since I’m selfhosting everything and nothing will be exposed publicly. After the relay server is installed it then asks you if you want to install the HTTP server.

1
2
3
1) Yes
2) No
Please choose if you want to download configs and install HTTP server:

I opted to install it. Once complete the following information is printed:

1
2
3
4
5
6
Your IP/DNS Address is [IP address]
Your public key is [public key]
Install Rustdesk on your machines and change your public key and IP/DNS name to the above
You can access your install scripts for clients by going to http://[public IP]:8000
Username is admin and password is [autogenerated password]
Press any key to finish install

The next part I take a bit of issue with because it involves a password being stored as plain text, however it’s just for the HTTP server and since I’m not exposing anything, for my purposes I deem this an acceptable risk. If you access the HTTP server using the IP address of the container with port 8000 you’re presented with a login which takes the user name and generated password shown at the end of the install script. However there is no way in the HTTP server interface to change it.

HTTP Server

The only way to change the password (that I’ve seen) is to edit the /etc/systemd/system/gohttpserver.service file, which stores the aforementioned autogenerated password as plain text.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@RustDesk:~# nano /etc/systemd/system/gohttpserver.service

[Unit]
Description=Go HTTP Server
[Service]
Type=simple
LimitNOFILE=1000000
ExecStart=/opt/gohttp/gohttpserver -r ./public --port 8000 --auth-type http --auth-http admin:[password]
WorkingDirectory=/opt/gohttp/
User=root
Group=root
Restart=always
StandardOutput=append:/var/log/gohttp/gohttpserver.log
StandardError=append:/var/log/gohttp/gohttpserver.error
# Restart service after 10 seconds if node service crashes
RestartSec=10
[Install]
WantedBy=multi-user.target

After saving restart the signal and relay services.

1
2
root@RustDesk:~# systemctl restart rustdesksignal
root@RustDesk:~# systemctl restart rustdeskrelay

Note again the lack of sudo because these commands are being run as root in my container setup.

With installation now complete I could then install RuskDesk on the client machines I wanted to control. For me these are all Windows virtual machines in Proxmox plus a phsyical machine that I use as a backup for work if needed. In my post about MeshCentral I mentioned how I had to use invites as a workaround to the client downloads not working from the relay server, however RustDesk uses that method as the primary means of installing it on a client machine (assuming you install the HTTP server), so it works much more smoothly than MeshCentral. When accessing the HTTP server, as shown in the screenshot above, there are two script files that are autocreated specifically for installing RustDesk on client machines. Since my clients are all Windows machines, I downloaded and ran the PowerShell script.

Once the script was finished I loaded RustDesk and was presented with the same panel as my main machine, however it was getting an error while trying to connect to the relay network. When I went into the network settings I discovered that it was pre-configured with my external IP instead of internal.

Server config

Changing the external IP to the LAN IP of the container for the server entries resolved this.

Up and running

After setting up a permanent password I then installed RustDesk using the same process on my main desktop. Alternatively I could have downloaded the MSI installer from RustDesk’s website and then configured the relay server manually. With that done, RustDesk was ready for use. Connection was near instant and I was very pleased that the key combos and mouse buttons that I couldn’t use in MeshCentral worked just fine in RuskDesk. Something else that worked even better than before with any software I’ve used is that my custom global hotkeys were also passed through to the client. While this doesn’t do anything on the client end, this resolved another issue I haven’t mentioned that would occur with AnyDesk: the Ctrl, Alt, or Shift keys would often get stuck when using a custom hotkey (my combos are usually a combination of Ctrl+Shift or Ctrl+Alt, remants from my LiteStep days of very old) and I’d have to mash all of those modifier keys to try and bring the client back to normal which only worked about half of the time. Very annoying. But because the hotkey combos are also passed through it doesn’t bring RustDesk out of focus and then doing whatever action assigned to the hotkey, leaving the modifiers stuck on the client end. Very happy to see this issue resolved.

Another highlight I’ve enjoyed so far are the tabbed UI for multiple connections. AnyDesk has the appearance of using tabs but it doesn’t actually support them, it just opens a new window when you click the “+” for a new connection. This is nice and clean and makes it easier to go back and forth between Windows testing environments as I almost always have to test something on two or more versions of Windows. Being able to run things in a streamlined parallel setup gets my work done more efficiently and fewer things slip throught the proverbial cracks.

The icing on the cake for me is Dark Mode. The mere presence of it is an upgrade from AnyDesk because while the newer versions have it, the tradeoff is a few features that were previously available for free were now paywalled. I don’t know if TeamViewer has a dark theme and quite frankly I don’t care because the shear headache that was dealing with them isn’t even worth the Google search to find out. #FirstWorldProblems? Absolutely, but I legitimately do have a mild light sensitivity so I need Dark Mode as much as possible.

As of writing this I’ve been using RustDesk for a considerable amount over the last four days for my day job and the only issue I’ve encountered is the odd hiccup when trying to connect, which I’ve always managed to resolve thus far by canceling the automatic connection re-attempt and then trying again manually. I haven’t experienced any lost connections, lagging, problems with key mapping or clipboard transfer from host to client and vice versa, and best of all no reminders about not using a free product for commercial use! I sincerely hope that this software doesn’t go the way of its ancestors because this really is well built and I love being able to selfhost services whenever possible. But unless/until this happens RustDesk is a keeper.

This post is licensed under CC BY 4.0 by the author.