A Nextcloud app that lets users open RDP (Remote Desktop Protocol) sessions directly in the browser — no VPN client, no separate remote-desktop software needed. Connections are stored securely in Nextcloud and accessible to any logged-in user.
- Create and manage multiple RDP connections from the Nextcloud sidebar
- Live RDP sessions rendered in the browser via Apache Guacamole
- Passwords stored encrypted in the Nextcloud database
- Configurable resolution per connection (720p, 1080p, 1440p, or custom)
- Fullscreen mode
- Works in any modern browser; no plugins required
| Requirement | Notes |
|---|---|
| Nextcloud ≥ 27 | Already installed and running |
| Debian / Ubuntu server | Where Nextcloud runs; apt access required |
| Node.js 18+ | For the guaclite WebSocket proxy |
| An RDP-enabled target machine | Windows Remote Desktop or any RDP server on TCP 3389 |
sudo apt update
sudo apt install guacd
sudo systemctl enable --now guacdVerify it is listening on port 4822:
sudo systemctl status guacdChoose a random 32-character string. It must be exactly 32 characters — AES-256-CBC requires a 32-byte key.
# Generate one quickly
cat /dev/urandom | tr -dc 'A-Za-z0-9' | head -c 32Create /etc/guaclite.env (readable only by root / the service user):
GUACD_HOST=127.0.0.1
GUACD_PORT=4822
GUAC_SECRET=change_me_to_exactly_32_chars!!!
sudo chmod 600 /etc/guaclite.envImportant: This value must match the
guac_secretyou set later in the Nextcloud admin panel. If they differ, guaclite silently decrypts to garbage and all RDP connections will fail.
guacamole-lite is a lightweight Node.js WebSocket proxy between the browser and guacd.
sudo mkdir /opt/guaclite
sudo npm install --prefix /opt/guaclite guacamole-lite@1
sudo cp guaclite-server.js /opt/guaclite/Create the systemd service at /etc/systemd/system/guaclite.service:
[Unit]
Description=guacamole-lite WebSocket proxy
After=network.target guacd.service
Requires=guacd.service
[Service]
Type=simple
WorkingDirectory=/opt/guaclite
EnvironmentFile=/etc/guaclite.env
ExecStart=/usr/bin/node /opt/guaclite/guaclite-server.js
Restart=on-failure
User=nobody
Group=nogroup
[Install]
WantedBy=multi-user.targetEnable and start it:
sudo systemctl daemon-reload
sudo systemctl enable --now guaclite
sudo systemctl status guaclite
# Should show: [guaclite] listening on :8080Copy the app into your Nextcloud custom_apps directory and enable it:
# Adjust the target path to match your Nextcloud installation
sudo cp -r web-rdp /var/www/nextcloud/custom_apps/
sudo chown -R www-data:www-data /var/www/nextcloud/custom_apps/web-rdp
sudo -u www-data php /var/www/nextcloud/occ app:enable web-rdpIn Nextcloud: Admin (top-right) → Administration settings → Connected Accounts → Web RDP
| Setting | Value |
|---|---|
| guaclite URL | ws://localhost:8080 |
| Secret key | The same 32-character string you put in /etc/guaclite.env as GUAC_SECRET |
Or set via command line:
sudo -u www-data php /var/www/nextcloud/occ config:app:set web-rdp guaclite_url --value="ws://localhost:8080"
sudo -u www-data php /var/www/nextcloud/occ config:app:set web-rdp guac_secret --value="your_32_char_secret_here"- Open your Nextcloud and navigate to Web RDP in the app menu
- Click + in the left sidebar
- Fill in: Name, Host (IP or hostname of the target machine), Username, Password
- Click Save, then click Connect
The RDP session opens in the main area.
| Setting | Default | Description |
|---|---|---|
guaclite_url |
ws://localhost:8080 |
WebSocket URL of the guaclite service. Change if you run guaclite on a different host or port. |
guac_secret |
(set manually) | Must match GUAC_SECRET in /etc/guaclite.env. Used to decrypt the encrypted token the browser sends to guaclite. |
The RDP session connects but shows nothing. Most likely cause: the guac_secret in the Nextcloud admin settings does not match GUAC_SECRET in /etc/guaclite.env. guaclite silently decrypts to garbage, guacd gets an invalid connection config, and sends no display data.
Fix: make sure both values are identical, then reconnect.
Shown in guaclite logs. The secret is mismatched or the token format is wrong. Verify:
GUAC_SECRETin/etc/guaclite.envequals theguac_secretin the Nextcloud admin panel- The value is exactly 32 characters
journalctl -u guaclite --since "5 minutes ago"GUAC_SECRET is not exactly 32 characters. AES-256-CBC requires a 32-byte key. Count the characters and adjust.
The Nextcloud Content Security Policy is blocking the WebSocket. Make sure the guaclite_url in the admin settings exactly matches the URL the browser is trying to connect to (including ws:// vs wss:// and the port).
- Confirm the target machine has Remote Desktop enabled
- Confirm no firewall blocks TCP 3389
- Test connectivity from the server:
nc -zv <host> 3389
# guaclite — WebSocket / token errors
journalctl -u guaclite -f
# guacd — RDP-level errors (auth failures, display issues)
journalctl -u guacd -f
# Nextcloud PHP errors
sudo tail -f /var/www/nextcloud/data/nextcloud.logThe frontend is a Vue 3 SPA built with webpack. After editing files in src/, rebuild:
cd custom_apps/web-rdp
# Install dependencies (first time only)
npm install
# Watch mode — rebuilds automatically on file save
npm run dev
# Production build
npm run buildOn Windows PowerShell (the npm scripts use NODE_ENV=x which fails in cmd/PowerShell):
$env:NODE_ENV='production'; npx webpack --config webpack.config.jsThe compiled output goes to js/web-rdp-main.js, which is served by Nextcloud automatically — no restart needed after a rebuild.
Browser (Vue 3 + guacamole-common-js)
↕ AJAX/POST (JSON)
Nextcloud PHP · ConnectionController · TunnelController
↕ AES-256-CBC encrypted token (WebSocket)
guacamole-lite (ws://localhost:8080)
↕ Guacamole protocol (TCP 4822)
guacd
↕ RDP (TCP 3389)
Target machine (Windows Remote Desktop / any RDP server)
If you encounter any issues or have questions:
- 🐛 Report bugs
- 💡 Request features
- ⭐ Star the repo if you find it useful!
If you like this project, support further development with a repost or coffee:
- 🧑💻 Markus Begerow
- 💾 GitHub