Open source Remote Desktop software, hosted on Oracle, for free

Written by

in

Objective: Move from Anydesk (or other remote desktop software) and self host an Open Source Rustdesk server instance in Oracle Cloud Free Tier. More info about RustDesk can be found here:

https://github.com/rustdesk/rustdesk

** EDIT – I am adding parts about increasing the security of this cloud VPS. Adding in having a firewall (UFW), Fail2Ban, and auto updating with security patches. Putting the relevant parts within the correct order. This was originally published on 12/28/2024. Updating to newer date for visibility on the blog.

General overview of the steps I have taken to achieve this:
  •  Create an VM instance in Oracle Free Tier, running Ubuntu
  •  Run Rustdesk Server as a Docker container
  •  Allow ports that Rustdesk uses to be routed to server container by adding ingress rules
  •  Using a dynamic DNS host to get a stable, accessible address
  •  Setting up target remote clients

 

Go to Oracle Cloud Free Tier at this website:

https://www.oracle.com/cloud/free/

Most of the inspiration to do this was from this youtube video, in which I made a few changes.

 

– Go through setup, adding in credit card info (which they will not charge as long as you do not go past the free tier limits, which you will not with this instance running)
– Please note your cloud account name, and your username, which is your email address that you have setup.
– Create a VM instance, I recommend Ubuntu linux version 22.02 or higher.
– When you create this instance, MAKE SURE TO DOWNLOAD the private and public key for the instance. You will use this to SSH into Ubuntu. There is no password. IF YOU FORGET THIS, you will have to delete the instance and make another one since there is no way to get the private key after the VM is spun up.
– give a name to your VNIC, change your internal IP address to the VM, and a name for your subnet.
– Now it is time to SSH into the VM Ubuntu instance
– For my own sake, I am on MacOS and I used the app Shellfish, and I was able to attach the private key to the login.
– user name would be “ubuntu”, and no password. The public IP address would be listed in the instance information from Oracle Cloud. That is what you would SSH into.
– In Windows, you can use PuTTY and attach the private key
– In Terminal on MacOS (and Linux) you can attach the key within the login info in as “ssh <SSH-key> ubuntu@<oracle-cloud-ip-address>”
– Once remote into the terminal session, first thing is to run “sudo apt update && sudo apt upgrade”
– This is to run updates to the Ubuntu image before doing anything else.
– Now it is time to install Docker, Docker Compose, DuckDNS (your choice) and RustDesk.
– With DuckDNS and Rustdesk, we will use a compose.yaml file (which interacts with Docker Compose). This file will pull down the containers and start them automatically.

 

Docker is installed using the Docker documentation and pasting it in the terminal window. (documentation here: https://docs.docker.com/engine/install/ubuntu/)
– Using apt, copy paste these commands in the SSH terminal and wait for them to complete:
# Add Docker’s official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
  “deb [arch=$(dpkg –print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo “$VERSION_CODENAME”) stable” | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

 

Install the lastest Docker package:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

 

Verify installation is succesful by running this command:
sudo docker run hello-world

 

– Now this is the part where we create a docker-compose file
– type in this command “sudo touch compose.yaml”
– then type “sudo nano compose.yaml”
The following is what I have pasted in my YAML file. Edit as you see fit. 
– An explanation of what is going on in my YAML file
– duckdns to point a DNS to an IP address of your choice (more info here: https://www.duckdns.org/about.jsp)
– Make sure to create a free DuckDNS account, create a subdomain, and take note of the token. You would need to add the value on the compose YAML file.
– hbbs and hbbr are the Rustdesk servers that need to be run to allow self-hosting. hbbs is the service that gets the client’s IP address to know where to make the direct connection. hbbr is the service that allows relaying if direct connection cannot be established.
– hbbs would need the -r switch to point to the IP address of the instance, in this one I used the DuckDNAS subdomain which points straight back to where hbbs resides
– Watchtower is used to auto-update containers daily at 3am.
– the YAML file will pull down all the containers, install them, and run.
services:
  duckdns:
    image: lscr.io/linuxserver/duckdns:latest
    container_name: duckdns
    network_mode: host #optional
    environment:
      – PUID=1000 #optional
      – PGID=1000 #optional
      – TZ=America/Los_Angeles #optional
      – SUBDOMAINS=example #enter your subdomain here
      – TOKEN=12345 #enter your token here
      – UPDATE_IP=ipv4 #optional
      – LOG_FILE=false #optional
    restart: unless-stopped
  hbbs:
    container_name: hbbs
    ports:
      – 21115:21115
      – 21116:21116
      – 21116:21116/udp
    image: rustdesk/rustdesk-server:latest
    command: hbbs -r #enter your full domain name here that points to your server, or the public IP of the instance -k #put your private key here. 
    volumes:
      – ./docker/rustdesk:/root
    restart: unless-stopped
  hbbr:
    container_name: hbbr
    ports:
      – 21117:21117
      – 21119:21119
    image: rustdesk/rustdesk-server:latest
    command: hbbr
    volumes:
      – ./docker/rustdesk:/root
    restart: unless-stopped
  watchtower:
    image: containrrr/watchtower:latest
    container_name: watchtower
    network_mode: bridge
    volumes:
      – /var/run/docker.sock:/var/run/docker.sock
    environment:
      TZ: Americas/Los_Angeles
    command: –cleanup –schedule “0 0 3 * * *” hbbr hbbs duckdns
    restart: always
– Make sure to save the compose.yaml file when you exit.

 

– Now it is time to run the containers in Docker
– Start running them by typing in “sudo docker-compose up -d”
– the -d switch will allow you to run the containers in detached mode, allowing you to close your SSH session without shutting off the containers.
– You can verify at any time that the containers are running by using the command “sudo docker ps”

 

– Once everything is running, double check the key files that gets generated at “./docker/rustdesk”. The files should be named id_ed25519 and id_ed25519.pub
– Use the cat command “cat id_ed25519.pub” and note the output
– The output is the public key for the asymmetric encryption for Rustdesk connections.
– This key would be inputted in the “Settings-Network” section of RustDesk client, in the same area where the server ID info would be put in.
– Use the cat command “cat id_ed25519” and note the output. This is your private key. I recommend re-editing your compose YAML file with the -k switch to enforce private connections. No one else can connect to your server relay via Rustdesk without the public key.
Build up your host firewall:
– within the SSH session, do the following commands:
sudo apt install ufw

sudo ufw default deny incoming
sudo ufw default allow outgoing

sudo ufw allow 21115/tcp
sudo ufw allow 21116/tcp
sudo ufw allow 21116/udp
sudo ufw allow 21117/tcp

sudo ufw allow 22/tcp

sudo ufw enable

Enable Fail2Ban. This bans IP addresses if they keep hammering your server:
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client status 

 

Enable automatic security upgrades on the server. It will save your sanity.
sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades
Poke holes in your VPS firewall!

 

– Fastest way is to go to your Oracle Cloud console instance page and look at the details of your instance. Click the name of your subnet (under the section “Primary VNIC”).
– Click Default Security List
– Add ingress rules, with source 0.0.0.0/0, TCP protocol and destination port range of 21115-21117
– second rule would be the same, but with UDP protocol and destination port 21116
 
– Double check DuckDNS is pointing to correct public IP of the instance.
– Using ping will resolve an IP address, but only once! The second ping will show unreachable. This is okay.

 

Install client on your own computer, and configure it.

 

Below would be the instructions if I was walking a client on how to set it up so I can start remote desktop services without me being physically there.
If you wanted just temporary, attended access (like a one time look), you can adapt these instructions by just downloading the Rustdesk client, and then just putting in the ServerID in settings, network. From there you would just need the computer ID and the one time password to remote in.

 

Minimum to get client to install on their system to enable permanent remote unattended desktop access
– Open web browser, go to rustdesk.com/download
– Have them download the client that matches their computer
– Have them open the file
– If on Mac, drag Rustdesk to Application folder and open it
– Enable all permissions before continuing
– If on Windows, run the RustDesk exe file
– Install it as a service to prevent UAC from interfering with it.
– If on Linux, they can figure it out themselves
– Go to settings by clicking the 3 dots next to ID number
– Go to Network and have them type in the ID Server address
– This will require elevated permissions to do this
– The ID server in my case is something.something.com, but please input what you have setup
– Everything can be blank for now
– Go to security settings and make sure to ENABLE remote configuration modification.
– This is important so you can change settings on the application itself.
– Have the client tell you what their ID number is, and the one time password to remote into the system.
– Once that is achieved, go ahead ahead and use a permanent password, set up 2FA (optional) and enter the server public key for encryption

 

With RustDesk client installed, you can verify that it is connecting to your relay server if the bottom of the window says “ready”
Use the above install info to install on another computer you want to remote to.

 

Once that is all done and it works…you are good!

 

Here is a few other things I have done. Totally optional, but this is just my preferences.

 

– I have my own FQDN. I use that instead of the duckDNS.org one since it doesn’t look pretty. This is easily achievable by creating a CNAME that points to the subdomain of duckDNS.org.
– I use Cloudflare as my DNS record holder, but make sure to TURN OFF proxy for the DNS subdomain. For some reason, the proxied data does not carry over to the hbbs container in the VPS. But an unproxied connection works fine.
– In my linux instance I did an APT INSTALL MC since I wanted to use Midnight Commander to look through the server in a semi GUI fashion. Totally not necessary (especially if you like to use the ls command), but I was thinking why not?
– Another thing to keep in mind is that Oracle can reclaim idle resources back when you are on the always free tier. This does not apply if you have a card on file and do the “Pay As You Go” model. The PAYG allows you to avoid this issue, and if you don’t go past your free limits (you probably won’t), you won’t get charged.

– However if you do not want to give out your card, you can follow this link to generate load on your VM instance so it won’t show idle.

https://medium.com/@poornamith/a-guide-to-stress-testing-your-virtual-machine-overcoming-oracle-cloud-reclaiming-idle-computer-7094de32dd9b