| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| computing:rustdesk [2024/11/02 17:25] – oemb1905 | computing:rustdesk [2026/01/02 04:26] (current) – oemb1905 |
|---|
| * **Jonathan Haack** | * **Jonathan Haack** |
| * **Haack's Networking** | * **Haack's Networking** |
| * **netcmnd@jonathanhaack.com** | * **webmaster@haacksnetworking.org** |
| ------------------------------------------- | ------------------------------------------- |
| |
| ------------------------------------------- | ------------------------------------------- |
| |
| This tutorial is for users of Debian GNU/Linux who want to setup a self-hosted RustDesk instance. This tutorial is designed for a public facing instance/domain which uses an apache2 reverse proxy to serve TLS requests back to the gohttp server listening on port 8000. TLS certs are handled by Let's Encrypt and cron. This tutorial also covers where and how to obtain the API key and other parameters needed for switching RustDesk clients over to the new self-hosted relay. Before proceeding any further, make sure that port 22, 80, and 443 are already open / firewalled as you see fit and that you have already exchanged ssh keys, assigned an A record to your public facing domain, and have a bare bones LAMP stack installed. Once that's done, let's begin. | This tutorial is for Debian users who want to create a self-hosted RustDesk instance manually. This covers installing the relay server (hbbr), the signaling server (hbbs), and the gohttp server (for client downloads and/or configs). After installing these services, I go through how to setup each systemd unit and, additionally, cover how to drop the gohttp server behind a reverse proxy. This tutorial assumes you have a hardened VM and/or VPS ready with a LAMP stack in place. If not, please head to [[https://wiki.haacksnetworking.org/doku.php?id=computing:apachesurvival|Apache Survival]] first. If you are ready to go, let's start by configuring the firewall: |
| |
| ufw allow 21114:21119/tcp | sudo ufw allow 22/tcp |
| ufw allow 8000/tcp | sudo ufw allow 80/tcp |
| ufw allow 21116/udp | sudo ufw allow 443/tcp |
| sudo ufw enable | sudo ufw allow 21114:21119/tcp |
| | sudo ufw allow 21116/udp |
| | sudo ufw enable |
| |
| Download the installer, make it executable, then run it: | Let's now download the latest version of rustdesk, unzip it, and then copy the binaries into the standard location inside ''/opt/rustdesk'': |
| |
| wget https://raw.githubusercontent.com/techahold/rustdeskinstall/master/install.sh | cd /tmp |
| chmod +x install.sh | wget https://github.com/rustdesk/rustdesk-server/releases/download/1.1.14/rustdesk-server-linux-amd64.zip |
| ./install.sh | unzip rustdesk-server-linux-amd64.zip |
| | sudo mkdir -p /opt/rustdesk /var/log/rustdesk |
| You can always download the package as a .deb and install it directly. The [[https://github.com/rustdesk/rustdesk-server/releases/tag/1.1.12|rustdesk repository]] has the latest amd64. I used wget to grab this, and installed it with dpkg -i. If you take this approach, you will need to set up the hbbs/hbbr environments manually. After reviewing the code and discussing the project with members of the [[https://matrix.to/#/#pubglug:gnulinux.club|pubglug community]], I decided the script was just fine. The script prompts the user with two questions. First, do you want to be IP-based or domain-based, I chose domain. It also asks if you want to set up the http server; I also chose yes. After the script was done, I went ahead and focused on setting up apache2's reverse proxy configs. | sudo cp amd64/hbbs amd64/hbbr amd64/rustdesk-utils /opt/rustdesk/ |
| | sudo chmod +x /opt/rustdesk/hbbs /opt/rustdesk/hbbr /opt/rustdesk/rustdesk-utils |
| |
| * [[https://repo.haacksnetworking.org/haacknet/haackingclub/-/blob/main/configs/webservers/apache/apache-rustdesk-domain.com.conf?ref_type=heads|HTTP Virtual Host]] | After the relay and signaling servers are installed and copied to the standard locations, we can download and install the gohttp server: |
| * [[https://repo.haacksnetworking.org/haacknet/haackingclub/-/blob/main/configs/webservers/apache/apache-rustdesk-domain.com-ssl.conf?ref_type=heads|TLS Virtual Host]] | |
| |
| Use the configs above and adapt to your needs. However, before you put them in place using ''a2ensite'', you should first setup TLS for your domain using the default virtual host. Leaving ''000-default.conf'' as the active virtual host for now, run the following commands: | sudo mkdir -p /opt/gohttp /var/log/gohttp |
| | cd /tmp |
| | wget https://github.com/codeskyblue/gohttpserver/releases/download/1.3.0/gohttpserver_1.3.0_linux_amd64.tar.gz |
| | tar -xzf gohttpserver_1.3.0_linux_amd64.tar.gz |
| | sudo cp gohttpserver /opt/gohttp/ |
| | sudo chmod +x /opt/gohttp/gohttpserver |
| | |
| | We can now navigate to our dedicated rustdesk directory and generate our keypair: |
| | |
| | cd /opt/rustdesk |
| | sudo ./rustdesk-utils genkeypair |
| | sudo chmod 600 id_ed25519 |
| | cat /opt/rustdesk/id_ed25519.pub |
| | |
| | Make a note of the public key somewhere in your secure notes. That's your API key for configuring clients to use your self-hosted relay. We now need to create our systemd units for each of the three services. Let's start with hbbs, or the signaling server. Open up ''sudo nano /etc/systemd/system/rustdesksignal.service'' and drop inside: |
| | |
| | <code bash> |
| | [Unit] |
| | Description=Rustdesk Signal Server |
| | |
| | [Service] |
| | Type=simple |
| | LimitNOFILE=1000000 |
| | ExecStart=/opt/rustdesk/hbbs -r hackingclub.org:21117 |
| | WorkingDirectory=/opt/rustdesk/ |
| | User=root |
| | Group=root |
| | Restart=always |
| | StandardOutput=append:/var/log/rustdesk/signalserver.log |
| | StandardError=append:/var/log/rustdesk/signalserver.error |
| | RestartSec=10 |
| | |
| | [Install] |
| | WantedBy=multi-user.target |
| | </code> |
| | |
| | Next, let's configure the relay server, or hbbr. To do that, open up ''sudo nano /etc/systemd/system/rustdeskrelay.service'' and drop the following inside: |
| | |
| | <code bash> |
| | [Unit] |
| | Description=Rustdesk Relay Server |
| | |
| | [Service] |
| | Type=simple |
| | LimitNOFILE=1000000 |
| | ExecStart=/opt/rustdesk/hbbr |
| | WorkingDirectory=/opt/rustdesk/ |
| | User=root |
| | Group=root |
| | Restart=always |
| | StandardOutput=append:/var/log/rustdesk/relayserver.log |
| | StandardError=append:/var/log/rustdesk/relayserver.error |
| | RestartSec=10 |
| | |
| | [Install] |
| | WantedBy=multi-user.target |
| | </code> |
| | |
| | Finally, let's create the systemd unit for the gohttp server. Please note that the unit contains a section to password protect the webroot so only authorized staff can access the client configs in the gohttp server. Adjust that to a secure value. Let's open up ''sudo nano /etc/systemd/system/gohttpserver.service'' and drop the following inside: |
| | |
| | <code bash> |
| | [Unit] |
| | Description=Go HTTP Server |
| | |
| | [Service] |
| | Type=simple |
| | LimitNOFILE=1000000 |
| | ExecStart=/opt/gohttp/gohttpserver -r ./public --port 8000 --auth-type http --auth-http admin:STRONG_PASSWORD_HERE |
| | WorkingDirectory=/opt/gohttp/ |
| | User=root |
| | Group=root |
| | Restart=always |
| | StandardOutput=append:/var/log/gohttp/gohttpserver.log |
| | StandardError=append:/var/log/gohttp/gohttpserver.error |
| | RestartSec=10 |
| | |
| | [Install] |
| | WantedBy=multi-user.target |
| | </code> |
| | |
| | We can now enable all the units and start the services: |
| | |
| | sudo systemctl daemon-reload |
| | sudo systemctl enable rustdesksignal rustdeskrelay gohttpserver |
| | sudo systemctl start rustdesksignal rustdeskrelay gohttpserver |
| | sudo systemctl status rustdesksignal rustdeskrelay gohttpserver |
| | |
| | We can now drop the gohttp server behind an apache reverse proxy. To do that, let's install certbot, cut a certificate, and enable the modules. To make things easier for yourself, open up ''/etc/apache2/sites-enabled/000-default.conf'' and uncomment and change ''ServerName'' to ''domain.com'' of your instance. Restart apache ''sudo systemctl restart apache2'' and then do the following: |
| |
| sudo apt install certbot letsencrypt python3-certbot-apache | sudo apt install certbot letsencrypt python3-certbot-apache |
| sudo certbot --authenticator standalone --installer apache -d site1.com --pre-hook "systemctl stop apache2" --post-hook "systemctl start apache2" | sudo certbot --authenticator standalone --installer apache -d domain.com --pre-hook "systemctl stop apache2" --post-hook "systemctl start apache2" |
| | sudo a2enmod proxy proxy_http proxy_wstunnel rewrite headers ssl |
| Once this completes successfully, you want to disable both the default virtual host called ''000-default.conf'' and the Let's Encrypt generated one called ''000-default-le-ssl.conf''. | |
| |
| sudo a2dissite 000-default.conf | You will now have to enabled vhosts in apache, namely, ''000-default.conf'' and something like ''000-default-le-ssl.conf'' or something similar. These are running stock configurations, not reverse proxies, however. So, now that the certificate is cut, simply swap the contents with some reverse proxy configs instead. For http, use something like: |
| sudo a2dissite 000-default-le-ssl.conf | |
| | |
| Please note that these are example virtual host names, so adjust to your OS / distro accordingly. Once all virtual hosts are disabled, you want to take the reverse proxy configs above and copy them into ''/etc/apache2/sites-available/''. Make sure to edit each and replace the example domains and ports with your FQDN and your port, presumably 8000. Additionally, make sure you have the required php modules enabled before restarting apache2's service: | |
| |
| sudo a2enmod proxy_http | <code bash> |
| sudo a2enmod proxy | <VirtualHost *:80> |
| sudo a2enmod rewrite | ServerName hackingclub.org |
| sudo a2enmod headers | ServerSignature Off |
| sudo systemctl restart apache2 | ProxyPreserveHost On |
| sudo reboot | AllowEncodedSlashes NoDecode |
| | |
| If you did everything correctly, your server will now load at ''https://fqdn.com'' without entering a port, as it will be handled by apache, which in turn passes it back to gohttp server running your RustDesk instance. This ensures that you communicate with the external instance using TLS, and that only the apache2 TLS communicates back via the proxy with RustDesk using http. Thus, only apache2 via TLS is publicly exposed, and by extension, this means when you set up your clients and the API key, you are sending/receiving all these sensitive remote desktop sessions across a TLS encrypted session. Make sure that you have Let's Encrypt cert renewal attached to an appropriate cronjob. Once this is in place, you need to setup the clients. Download RustDesk from the main website, and then adjust the following settings with the following information. | |
| |
| cat /opt/rustdesk/id_ed25519.pub | <Location /> |
| | Require all granted |
| The output above is your API key. On each client that you want to use with this server, you open the RustDesk client, unlock Network Settings, and enter this key into the parameter called "Key." In the sections above, enter you FQDN.tld without http:// or https://. Here's an example: | ProxyPassReverse http://127.0.0.1:8000 |
| \\ | ProxyPassReverse http://hackingclub.org |
| | </Location> |
| | |
| | RewriteEngine on |
| | RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR] |
| | RewriteCond %{REQUEST_URI} ^/uploads/.* |
| | RewriteRule .* http://127.0.0.1:8000%{REQUEST_URI} [P,QSA,NE] |
| | |
| | ErrorDocument 404 /404.html |
| | ErrorDocument 422 /422.html |
| | ErrorDocument 500 /500.html |
| | ErrorDocument 502 /502.html |
| | ErrorDocument 503 /503.html |
| | |
| | LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common_forwarded |
| | ErrorLog /var/log/apache2/hackingclub.org_error.log |
| | CustomLog /var/log/apache2/hackingclub.org_forwarded.log common_forwarded |
| | CustomLog /var/log/apache2/hackingclub.org_access.log combined env=!dontlog |
| | CustomLog /var/log/apache2/hackingclub.org.log combined |
| | |
| | RewriteCond %{SERVER_NAME} =hackingclub.org |
| | RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] |
| | </VirtualHost> |
| | </code> |
| | |
| | For the https virtual host, use something like: |
| | |
| | <code bash> |
| | <VirtualHost *:443> |
| | SSLEngine on |
| | SSLProtocol all -SSLv2 |
| | SSLHonorCipherOrder on |
| | SSLCipherSuite "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS" |
| | Header add Strict-Transport-Security: "max-age=15768000;includeSubdomains" |
| | SSLCompression Off |
| | |
| | ServerName hackingclub.org |
| | ServerSignature Off |
| | ProxyPreserveHost On |
| | |
| | <FilesMatch ".+\.ph(ar|p|tml)$"> |
| | SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost" |
| | </FilesMatch> |
| | |
| | AllowEncodedSlashes NoDecode |
| | |
| | <Location /> |
| | Require all granted |
| | ProxyPassReverse http://127.0.0.1:8000 |
| | ProxyPassReverse http://hackingclub.org |
| | </Location> |
| | |
| | RewriteEngine on |
| | RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR] |
| | RewriteCond %{REQUEST_URI} ^/uploads/.* |
| | RewriteRule .* http://127.0.0.1:8000%{REQUEST_URI} [P,QSA,NE] |
| | |
| | RequestHeader set X_FORWARDED_PROTO 'https' |
| | RequestHeader set X-Forwarded-Ssl on |
| | |
| | ErrorDocument 404 /404.html |
| | ErrorDocument 422 /422.html |
| | ErrorDocument 500 /500.html |
| | ErrorDocument 502 /502.html |
| | ErrorDocument 503 /503.html |
| | |
| | LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common_forwarded |
| | ErrorLog /var/log/apache2/hackingclub.org_error.log |
| | CustomLog /var/log/apache2/hackingclub.org_forwarded.log common_forwarded |
| | CustomLog /var/log/apache2/hackingclub.org_access.log combined env=!dontlog |
| | CustomLog /var/log/apache2/hackingclub.org.log combined |
| | |
| | Include /etc/letsencrypt/options-ssl-apache.conf |
| | SSLCertificateFile /etc/letsencrypt/live/hackingclub.org/fullchain.pem |
| | SSLCertificateKeyFile /etc/letsencrypt/live/hackingclub.org/privkey.pem |
| | </VirtualHost> |
| | </code> |
| | |
| | Check your configs with ''apache2ctl configtest'' and then restart the service ''sudo systemctl restart apache2''. Once everything is working properly, we can now switch to setting up clients. On each RustDesk client, you go to Settings > Network > Unlock and edit the following: |
| | |
| | * **ID Server**: hackingclub.org |
| | * **Relay Server**: hackingclub.org |
| | * **API Server**: https://hackingclub.org |
| | * **Key**: API Key from above |
| | |
| | Here's an example of what this section looks like. Note that entering a value in API Server is moot - that's only supported by the premium/paid version. It does not hurt anything to add the value there, however. |
| |
| {{ :computing:screenshot_from_2024-11-02_11-12-52.png?direct&800 |}} | {{ :computing:screenshot_from_2024-11-02_11-12-52.png?direct&800 |}} |
| |
| \\ | Enter the same values on your primary workstation. Once that's done for your workstation and at least one client, you can then specify the ID your "Control Remote Desktop" section and you are all set. Of course, there are many settings inside RustDesk, such as "Always connect via relay" and also how you choose to configure the "Password", i.e., whether it is permanent or one-time. These are decisions that will be decided by your use-case, as with others, but these are two good areas to look at post-installation. For updates, we do the following: |
| Personally, I choose to use both one-time keys and set/static passwords for the connections, but those are personal preference decisions, so I won't detail that here. From here on out, just make sure to set up all other clients equivalently and you are all set. After you confirm all is working, you can test to see if RustDesk was indeed using your new self-hosted relay by attempting to use it when your VPS is powered down. The connection will fail because neither client is using the RustDesk default server any longer and yours is down. A bit overkill, but we like to confirm things at Haack's Networking lol. Well, hope this helps other Debian users who want to use and set this up without using docker! | |
| | sudo systemctl stop rustdesksignal rustdeskrelay gohttpserver |
| | cd /tmp |
| | wget https://github.com/rustdesk/rustdesk-server/releases/download/NEW_VERSION/rustdesk-server-linux-amd64.zip |
| | unzip -o rustdesk-server-linux-amd64.zip |
| | sudo cp amd64/hbbs amd64/hbbr /opt/rustdesk/ |
| | sudo chmod +x /opt/rustdesk/hbbs /opt/rustdesk/hbbr |
| | sudo systemctl start rustdesksignal rustdeskrelay gohttpserver |
| | sudo systemctl status rustdesksignal rustdeskrelay gohttpserver |
| | |
| | That's basically it. The new binaries are executed and controlled by the pre-established systemd units, so you merely replace the binaries and make them executable and you are good to go. If the gohttp server has been updated, similarly: |
| | |
| | sudo systemctl stop gohttpserver |
| | cd /tmp |
| | wget https://github.com/codeskyblue/gohttpserver/releases/download/NEW_VERSION/gohttpserver_NEW_VERSION_linux_amd64.tar.gz |
| | tar -xzf gohttpserver_NEW_VERSION_linux_amd64.tar.gz |
| | sudo cp gohttpserver /opt/gohttp/ |
| | sudo chmod +x /opt/gohttp/gohttpserver |
| | sudo systemctl start gohttpserver |
| | sudo systemctl status gohttpserver |
| | |
| | The password is specified in the systemd unit, which remains unchanged. Just make sure to restart the service as directed above and it will invoke that same value, but on the updated go server. You should now be fully up to date. Hope this helps others wanting to avoid using the automated script / understand all the moving parts of the instance. Happy hacking! |
| |
| --- //[[webmaster@haacksnetworking.org|oemb1905]] 2024/11/02 17:23// | --- //[[alerts@haacksnetworking.org|oemb1905]] 2026/01/01 18:24// |