Skip to content

Commit e516446

Browse files
BenraouaneSoufianerootDevelopmentCatsCopilot
authored
Add Rustdesk module (coder#266)
Closes coder#79 ## Description This PR add new module, install minimal desktop environment (xfce), virtual display, ,rustdesk package from deb file, init new screen, export DISPLAY environment variable with last created virtual screen, start new xfce session & execute the rustdesk cli, generate new password, change the default password, then log the ID & password to be used within rustdesk client to connect to the host ## Type of Change - [x] New module - [ ] Bug fix - [ ] Feature/enhancement - [ ] Documentation - [ ] Other ## Module Information Overview/test video: live demo that launch rustdesk with GUI in a docker container https://youtu.be/_rR-l7nARN4 Screenshots: <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/ba67a864-4295-471e-8b6a-976c23cb8f55" /> <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/24686339-aba7-47fe-92b4-5700ef5b154a" /> <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/21884c31-9eed-45ef-b3de-c12c99f2aa96" /> <img width="1920" height="1080" alt="image" src="https://github.com/user-attachments/assets/ec0c65fe-61be-404c-ba36-8cc2882e85a2" /> **Path:** `registry/BenraouaneSoufiane/modules/rustdesk` **New version:** `v1.0.0` **Breaking change:** [ ] Yes [x] No ## Testing & Validation - [x] Tests pass (`bun test`) - [x] Code formatted (`bun run fmt`) - [x] Changes tested locally ## Related Issues /claim coder#79 (remain asset 150$) --------- Co-authored-by: root <root@DESKTOP-6QN3GRE.localdomain> Co-authored-by: DevCats <christofer@coder.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent f004539 commit e516446

File tree

6 files changed

+293
-0
lines changed

6 files changed

+293
-0
lines changed

.icons/rustdesk.svg

Lines changed: 5 additions & 0 deletions
Loading
28 KB
Loading
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
display_name: "Benraouane Soufiane"
3+
bio: "Full stack developer creating awesome things."
4+
avatar: "./.images/avatar.png"
5+
github: "benraouanesoufiane"
6+
linkedin: "https://www.linkedin.com/in/benraouane-soufiane" # Optional
7+
website: "https://benraouanesoufiane.com" # Optional
8+
support_email: "hello@benraouanesoufiane.com" # Optional
9+
status: "community"
10+
---
11+
12+
# Benraouane Soufiane
13+
14+
Full stack developer creating awesome things.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
display_name: RustDesk
3+
description: Run RustDesk in your workspace with virtual display
4+
icon: ../../../../.icons/rustdesk.svg
5+
verified: false
6+
tags: [rustdesk, rdp, vm]
7+
---
8+
9+
# RustDesk
10+
11+
Launches RustDesk within your workspace with a virtual display to provide remote desktop access. The module outputs the RustDesk ID and password needed to connect from external RustDesk clients.
12+
13+
```tf
14+
module "rustdesk" {
15+
count = data.coder_workspace.me.start_count
16+
source = "registry.coder.com/BenraouaneSoufiane/rustdesk/coder"
17+
version = "1.0.0"
18+
agent_id = coder_agent.example.id
19+
}
20+
```
21+
22+
## Features
23+
24+
- Automatically sets up virtual display (Xvfb)
25+
- Downloads and configures RustDesk
26+
- Outputs RustDesk ID and password for easy connection
27+
- Provides external app link to RustDesk web client for browser-based access
28+
- Starts virtual display (Xvfb) with customizable resolution
29+
- Customizable screen resolution and RustDesk version
30+
31+
## Requirements
32+
33+
- Coder v2.5 or higher
34+
- Linux workspace with `apt`, `dnf`, or `yum` package manager
35+
36+
## Examples
37+
38+
### Custom configuration with specific version
39+
40+
```tf
41+
module "rustdesk" {
42+
count = data.coder_workspace.me.start_count
43+
source = "registry.coder.com/BenraouaneSoufiane/rustdesk/coder"
44+
version = "1.0.0"
45+
agent_id = coder_agent.example.id
46+
rustdesk_password = "mycustompass"
47+
xvfb_resolution = "1920x1080x24"
48+
rustdesk_version = "1.4.1"
49+
}
50+
```
51+
52+
### Docker container configuration
53+
54+
It requires coder' server to be run as root, when using with Docker, add the following to your `docker_container` resource:
55+
56+
```tf
57+
resource "docker_container" "workspace" {
58+
59+
# ... other configuration ...
60+
61+
user = "root"
62+
privileged = true
63+
network_mode = "host"
64+
65+
ports {
66+
internal = 21115
67+
external = 21115
68+
}
69+
ports {
70+
internal = 21116
71+
external = 21116
72+
}
73+
ports {
74+
internal = 21118
75+
external = 21118
76+
}
77+
ports {
78+
internal = 21119
79+
external = 21119
80+
}
81+
}
82+
```
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
4+
required_providers {
5+
coder = {
6+
source = "coder/coder"
7+
version = ">= 2.5"
8+
}
9+
}
10+
}
11+
12+
variable "log_path" {
13+
type = string
14+
description = "The path to log rustdesk to."
15+
default = "/tmp/rustdesk.log"
16+
}
17+
18+
variable "agent_id" {
19+
description = "Attach RustDesk setup to this agent"
20+
type = string
21+
}
22+
23+
variable "order" {
24+
description = "Run order among scripts/apps"
25+
type = number
26+
default = 1
27+
}
28+
29+
# Optional knobs passed as env (you can expose these as variables too)
30+
variable "rustdesk_password" {
31+
description = "If empty, the script will generate one"
32+
type = string
33+
default = ""
34+
sensitive = true
35+
}
36+
37+
variable "xvfb_resolution" {
38+
description = "Xvfb screen size/depth"
39+
type = string
40+
default = "1024x768x16"
41+
}
42+
43+
variable "rustdesk_version" {
44+
description = "RustDesk version to install (use 'latest' for most recent release)"
45+
type = string
46+
default = "latest"
47+
}
48+
49+
resource "coder_script" "rustdesk" {
50+
agent_id = var.agent_id
51+
display_name = "RustDesk"
52+
run_on_start = true
53+
54+
# Prepend env as bash exports, then append the script file literally.
55+
script = <<-EOT
56+
# --- module-provided env knobs ---
57+
export RUSTDESK_PASSWORD="${var.rustdesk_password}"
58+
export XVFB_RESOLUTION="${var.xvfb_resolution}"
59+
export RUSTDESK_VERSION="${var.rustdesk_version}"
60+
# ---------------------------------
61+
62+
${file("${path.module}/run.sh")}
63+
EOT
64+
}
65+
66+
resource "coder_app" "rustdesk" {
67+
agent_id = var.agent_id
68+
slug = "rustdesk"
69+
display_name = "Rustdesk"
70+
url = "https://rustdesk.com/web"
71+
icon = "/icon/rustdesk.svg"
72+
order = var.order
73+
external = true
74+
}
75+
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env bash
2+
3+
BOLD='\033[0;1m'
4+
RESET='\033[0m'
5+
6+
printf "${BOLD}🖥️ Installing RustDesk Remote Desktop\n${RESET}"
7+
8+
# ---- configurable knobs (env overrides) ----
9+
RUSTDESK_VERSION="${RUSTDESK_VERSION:-latest}"
10+
LOG_PATH="${LOG_PATH:-/tmp/rustdesk.log}"
11+
12+
# ---- fetch latest version if needed ----
13+
if [ "$RUSTDESK_VERSION" = "latest" ]; then
14+
printf "🔍 Fetching latest RustDesk version...\n"
15+
RUSTDESK_VERSION=$(curl -s https://api.github.com/repos/rustdesk/rustdesk/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' || echo "1.4.1")
16+
printf "📌 Fetched RustDesk version: ${RUSTDESK_VERSION}\n"
17+
else
18+
printf "📌 Using specified RustDesk version: ${RUSTDESK_VERSION}\n"
19+
fi
20+
XVFB_RESOLUTION="${XVFB_RESOLUTION:-1024x768x16}"
21+
RUSTDESK_PASSWORD="${RUSTDESK_PASSWORD:-}"
22+
23+
# ---- detect package manager & arch ----
24+
ARCH="$(uname -m)"
25+
case "$ARCH" in
26+
x86_64 | amd64) PKG_ARCH="x86_64" ;;
27+
aarch64 | arm64) PKG_ARCH="aarch64" ;;
28+
*)
29+
echo "❌ Unsupported arch: $ARCH"
30+
exit 1
31+
;;
32+
esac
33+
34+
if command -v apt-get > /dev/null 2>&1; then
35+
PKG_SYS="deb"
36+
PKG_NAME="rustdesk-${RUSTDESK_VERSION}-${PKG_ARCH}.deb"
37+
INSTALL_DEPS='apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y wget libva2 libva-drm2 libva-x11-2 libgstreamer-plugins-base1.0-0 gstreamer1.0-pipewire xfce4 xfce4-goodies xvfb x11-xserver-utils dbus-x11 libegl1 libgl1 libglx0 libglu1-mesa mesa-utils libxrandr2 libxss1 libgtk-3-0t64 libgbm1 libdrm2 libxcomposite1 libxdamage1 libxfixes3'
38+
INSTALL_CMD="apt-get install -y ./${PKG_NAME}"
39+
CLEAN_CMD="rm -f \"${PKG_NAME}\""
40+
elif command -v dnf > /dev/null 2>&1; then
41+
PKG_SYS="rpm"
42+
PKG_NAME="rustdesk-${RUSTDESK_VERSION}-${PKG_ARCH}.rpm"
43+
INSTALL_DEPS='dnf install -y wget libva libva-intel-driver gstreamer1-plugins-base pipewire xfce4-session xfce4-panel xorg-x11-server-Xvfb xorg-x11-xauth dbus-x11 mesa-libEGL mesa-libGL mesa-libGLU mesa-dri-drivers libXrandr libXScrnSaver gtk3 mesa-libgbm libdrm libXcomposite libXdamage libXfixes'
44+
INSTALL_CMD="dnf install -y ./${PKG_NAME}"
45+
CLEAN_CMD="rm -f \"${PKG_NAME}\""
46+
elif command -v yum > /dev/null 2>&1; then
47+
PKG_SYS="rpm"
48+
PKG_NAME="rustdesk-${RUSTDESK_VERSION}-${PKG_ARCH}.rpm"
49+
INSTALL_DEPS='yum install -y wget libva libva-intel-driver gstreamer1-plugins-base pipewire xfce4-session xfce4-panel xorg-x11-server-Xvfb xorg-x11-xauth dbus-x11 mesa-libEGL mesa-libGL mesa-libGLU mesa-dri-drivers libXrandr libXScrnSaver gtk3 mesa-libgbm libdrm libXcomposite libXdamage libXfixes'
50+
INSTALL_CMD="yum install -y ./${PKG_NAME}"
51+
CLEAN_CMD="rm -f \"${PKG_NAME}\""
52+
else
53+
echo "❌ Unsupported distro: need apt, dnf, or yum."
54+
exit 1
55+
fi
56+
57+
# ---- install rustdesk if missing ----
58+
if ! command -v rustdesk > /dev/null 2>&1; then
59+
printf "📦 Installing dependencies...\n"
60+
sudo bash -c "$INSTALL_DEPS" 2>&1 | tee -a "${LOG_PATH}"
61+
62+
printf "⬇️ Downloading RustDesk ${RUSTDESK_VERSION} (${PKG_SYS}, ${PKG_ARCH})...\n"
63+
URL="https://github.com/rustdesk/rustdesk/releases/download/${RUSTDESK_VERSION}/${PKG_NAME}"
64+
wget -q "$URL" 2>&1 | tee -a "${LOG_PATH}"
65+
66+
printf "🔧 Installing RustDesk...\n"
67+
sudo bash -c "$INSTALL_CMD" 2>&1 | tee -a "${LOG_PATH}"
68+
69+
printf "🧹 Cleaning up...\n"
70+
bash -c "$CLEAN_CMD" 2>&1 | tee -a "${LOG_PATH}"
71+
else
72+
printf "✅ RustDesk already installed\n"
73+
fi
74+
75+
# ---- start virtual display ----
76+
echo "Starting Xvfb with resolution ${XVFB_RESOLUTION}"
77+
Xvfb :99 -screen 0 "${XVFB_RESOLUTION}" >> "${LOG_PATH}" 2>&1 &
78+
export DISPLAY=:99
79+
80+
# Wait for X to be ready
81+
for i in {1..10}; do
82+
if xdpyinfo -display :99 > /dev/null 2>&1; then
83+
echo "X display is ready"
84+
break
85+
fi
86+
sleep 1
87+
done
88+
89+
# ---- create (or accept) password and start rustdesk ----
90+
if [[ -z "${RUSTDESK_PASSWORD}" ]]; then
91+
RUSTDESK_PASSWORD="$(tr -dc 'a-zA-Z0-9@' < /dev/urandom | head -c 10)@97"
92+
fi
93+
94+
echo "Starting XFCE desktop environment..."
95+
xfce4-session >> "${LOG_PATH}" 2>&1 &
96+
97+
echo "Waiting for xfce4-session to initialize..."
98+
sleep 5
99+
100+
printf "🔐 Setting RustDesk password and starting service...\n"
101+
rustdesk >> "${LOG_PATH}" 2>&1 &
102+
sleep 2
103+
104+
rustdesk --password "${RUSTDESK_PASSWORD}" >> "${LOG_PATH}" 2>&1 &
105+
sleep 3
106+
107+
RID="$(rustdesk --get-id 2> /dev/null || echo 'ID_PENDING')"
108+
109+
printf "🥳 RustDesk setup complete!\n\n"
110+
printf "${BOLD}📋 Connection Details:${RESET}\n"
111+
printf " RustDesk ID: ${RID}\n"
112+
printf " RustDesk Password: ${RUSTDESK_PASSWORD}\n"
113+
printf " Display: ${DISPLAY} (${XVFB_RESOLUTION})\n"
114+
printf "\n📝 Logs available at: ${LOG_PATH}\n\n"
115+
116+
echo "Setup script completed successfully. All services running in background."
117+
exit 0

0 commit comments

Comments
 (0)