← Back to posts
comparison guide self-hosted · · 13 min read

Self-Hosted Remote Desktop: Apache Guacamole vs RustDesk vs MeshCentral 2026

Complete guide to self-hosted remote desktop solutions in 2026. Compare Apache Guacamole, RustDesk, and MeshCentral with Docker setup, feature comparison, and deployment instructions.

OS
Editorial Team

Why Self-Host Your Remote Desktop Infrastructure

Remote desktop access is a foundational requirement for any homelab, small business, or distributed team. Commercial solutions like TeamViewer, AnyDesk, and Splashtop offer convenience at a cost — both financial and privacy-related. Subscription pricing for these services has climbed steadily, with enterprise plans regularly exceeding $50 per user per month. More critically, every connection routed through a third-party relay server means your session metadata — connection times, endpoint IPs, and session durations — is visible to the provider.

Self-hosting your remote desktop infrastructure eliminates these trade-offs entirely:

  • Full session privacy — no third party logs which machines you connect to, when, or for how long
  • No per-seat licensing — support unlimited endpoints on your own hardware regardless of user count
  • Customizable access control — integrate with your existing authentication system (LDAP, OAuth, SAML)
  • On-premises data processing — screen recordings, file transfers, and clipboard data never leave your network
  • Resilient connectivity — operate through your own relay infrastructure, unaffected by commercial service outages
  • Audit trail ownership — maintain complete session logs for compliance and incident review

Whether you’re managing a fleet of workstations, providing IT support across a distributed organization, or accessing your homelab from anywhere, a self-hosted remote desktop solution gives you control without the recurring costs or surveillance dependencies.

Quick Comparison

FeatureApache GuacamoleRustDeskMeshCentral
TypeWeb gatewayP2P + relayFull IT management
ProtocolsRDP, VNC, SSH, Telnet, kubernetesProprietary (encrypted)RDP, VNC, SSH, Terminal
ClientBrowser-based (HTML5)Desktop + web + mobileWeb-based
Self-Host RelayN/A (direct)✅ Built-in✅ Built-in
File Transfer✅ Via RDP/VNC✅ Native✅ Native
Clipboard Sync
Multi-Monitor✅ (RDP)
Audio Redirection✅ (RDP)
Recording✅ Session recording✅ Optional✅ Screen + terminal
2FA / MFA✅ (TOTP, LDAP, SAML)✅ (OAuth, LDAP)✅ (SAML, LDAP, 2FA)
Agent Required❌ (server-side)✅ (both ends)✅ (target only)
NAT Traversal❌ Manual port forward✅ STUN/TURN✅ Built-in
Group/Org Mgmt✅ Connection groups✅ Address book✅ Full device groups
Resource UsageMedium (Java)Low (Rust)Medium (Node.js)
Best ForBrowser access, mixed protocolsFast P2P, simplicityFull IT fleet management

1. Apache Guacamole (The Protocol-Agnostic Gateway)

Best for: Browser-based access to heterogeneous endpoints (RDP, VNC, SSH)

Key Features

Apache Guacamole is a clientless remote desktop gateway. It supports standard protocols — RDP, VNC, SSH, telnet, and Kubernetes exec — and renders sessions as HTML5 in any modern browser. No client software installation is required on the user side. The architecture consists of two components:

  • guacd: The proxy daemon that speaks native protocols and translates to Guacamole’s internal protocol
  • guacamole: The web application (WAR file) running on a servlet container (Tomcat)

Guacamole excels in environments where users need to access a mix of Windows (RDP), Linux (VNC/SSH), and network equipment (SSH/telnet) from a single browser interface. It integrates with Active Directory, LDAP, SAML, CAS, and OpenID Connect for authentication, and supports two-factor authentication via TOTP.

docker Deployment

The official Docker deployment requires three services: Guacamole, guacd, and a database (PostgreSQL or MySQL) for connection configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# docker-compose.yml
version: '3'
services:
  guacd:
    image: guacamole/guacd:latest
    container_name: guacd
    restart: unless-stopped
    volumes:
      - ./drive:/drive:rw
      - ./record:/record:rw

  postgres:
    image: postgres:16-alpine
    container_name: guac-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: guacamole_db
      POSTGRES_USER: guacamole_user
      POSTGRES_PASSWORD: changeme_secure_password_2026
    volumes:
      - ./pgdata:/var/lib/postgresql/data

  guacamole:
    image: guacamole/guacamole:latest
    container_name: guacamole
    restart: unless-stopped
    depends_on:
      - guacd
      - postgres
    ports:
      - "8080:8080"
    environment:
      GUACD_HOSTNAME: guacd
      POSTGRES_HOSTNAME: postgres
      POSTGRES_DATABASE: guacamole_db
      POSTGRES_USER: guacamole_user
      POSTGRES_PASSWORD: changeme_secure_password_2026
      # Enable TOTP for two-factor auth
      TOTP_ENABLED: "true"
      # Session recording
      RECORDING_PATH: /record

Before starting the stack, initialize the PostgreSQL database with Guacamole’s schema:

1
2
3
4
5
6
# Generate the initialization SQL
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgres > initdb.sql

# Run it against the database
docker cp initdb.sql guac-postgres:/initdb.sql
docker exec -u postgres guac-postgres psql -d guacamole_db -f /initdb.sql

Start the stack:

1
docker compose up -d

Access the web interface at http://your-server:8080/guacamole. Default credentials: guacadmin / guacadmin. Change this immediately after first login.

Configuring a Windows RDP Connection

After logging in, navigate to Settings → Connections → New Connection:

  • Name: Workstation-01
  • Protocol: RDP
  • Parameters:
    • Hostname: 192.168.1.50 (or DNS name)
    • Port: 3389
    • Username: your Windows username
    • Password: your Windows password
    • Security mode: NLA (Network Level Authentication)
    • Color depth: 32-bit
    • Enable clipboard: checked
    • Enable audio: checked

For Linux endpoints, use VNC protocol with the hostname of your VNC server (e.g., TigerVNC or x11vnc).

Advanced: LDAP Integration

For organizations with existing directory infrastructure, Guacamole supports LDAP authentication. Place the extension JAR in the extensions directory and configure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# guacamole.properties
auth-provider: net.sourceforge.guacamole.net.auth.ldap.LdapAuthenticationProvider
ldap-hostname: ldap.yourdomain.com
ldap-port: 636
ldap-encryption-method: ssl
ldap-search-bind-dn: cn=guacamole,ou=services,dc=yourdomain,dc=com
ldap-search-bind-password: service_account_password
ldap-user-base-dn: ou=users,dc=yourdomain,dc=com
ldap-user-search-filter: (uid={0})
ldap-config-base-dn: dc=yourdomain,dc=com
ldap-group-base-dn: ou=groups,dc=yourdomain,dc=com
ldap-group-search-filter: (member={0})

Pros and Cons

Pros: Protocol-agnostic (RDP + VNC + SSH + more), browser-based access, mature project with strong security audit history, excellent LDAP/SAML integration, session recording

Cons: Requires manual connection setup per endpoint, no automatic NAT traversal (firewall rules needed), Java dependency increases resource usage, no native file transfer without RDP drive redirection


2. RustDesk (The Modern P2P Alternative)

Best for: Fast peer-to-peer remote access with automatic NAT traversal

Key Features

RustDesk is an open-source remote desktop application written in Rust. It was designed as a TeamViewer alternative from the ground up, with a focus on performance, privacy, and self-hosting. The key differentiator is its peer-to-peer architecture with automatic relay fallback — when a direct connection can be established between two machines, data flows directly without touching any server.

RustDesk includes:

  • End-to-end encryption using ChaCha20-Poly1305
  • Built-in file transfer and TCP tunneling
  • Multi-platform clients (Windows, macOS, Linux, iOS, Android, Web)
  • Unattended access with permanent password
  • Address book with tags and groups
  • Session recording (optional)
  • Custom branding for self-hosted deployments

Self-Hosting the Relay Server

For optimal performance and full data control, deploy your own RustDesk ID and relay server. This eliminates the public relay servers and keeps all metadata within your infrastructure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# docker-compose.yml
version: '3'
services:
  hbbs:
    image: rustdesk/rustdesk-server:latest
    container_name: rustdesk-hbbs
    restart: unless-stopped
    command: hbbs -r relay.yourdomain.com:21117
    ports:
      - "21115:21115"    # TCP NAT test
      - "21116:21116"    # TCP ID server
      - "21116:21116/udp" # UDP ID server
      - "21118:21118"    # TCP WebSocket
    volumes:
      - ./hbbs-data:/root

  hbbr:
    image: rustdesk/rustdesk-server:latest
    container_name: rustdesk-hbbr
    restart: unless-stopped
    command: hbbr
    ports:
      - "21117:21117"    # TCP relay
      - "21119:21119"    # TCP WebSocket relay
    volumes:
      - ./hbbr-data:/root
    depends_on:
      - hbbs

The two components serve different purposes:

  • hbbs (ID server): Handles peer discovery and connection brokering
  • hbbr (Relay server): Acts as a data relay when P2P connection fails

Start the servers:

1
2
3
4
docker compose up -d

# Get the public key for client configuration
cat ./hbbs-data/id_ed25519.pub

Client Configuration

On each RustDesk client, configure the custom server settings:

Via GUI: Open RustDesk → Settings → Network → ID/Relay Server:

  • ID Server: relay.yourdomain.com (port 21116)
  • Relay Server: relay.yourdomain.com (port 21117)
  • Key: Content of id_ed25519.pub
  • API Server: Leave empty (unless using RustDesk’s web console)

Via CLI/registry (for mass deployment):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Linux
rustdesk --config "id_server=relay.yourdomain.com"
rustdesk --config "relay_server=relay.yourdomain.com:21117"
rustdesk --config "key=<contents of id_ed25519.pub>"

# Windows (registry)
reg add "HKCU\Software\RustDesk" /v "id_server" /t REG_SZ /d "relay.yourdomain.com" /f
reg add "HKCU\Software\RustDesk" /v "relay_server" /t REG_SZ /d "relay.yourdomain.com:21117" /f

# macOS
defaults write com.carller.rustdesk "id_server" -string "relay.yourdomain.com"
defaults write com.carller.rustdesk "relay_server" -string "relay.yourdomain.com:21117"

Unattended Access Setup

For headless servers and workstations that need permanent remote access:

  1. Open RustDesk on the target machine
  2. Set a permanent password: Settings → Security → Permanent Password
  3. Enable Start on Boot and Enable Service (runs with system privileges before login)
  4. Note the RustDesk ID — this is your permanent identifier

The client can now be accessed at any time using the ID and permanent password, even when no user is logged in.

Reverse Proxy with TLS

For the web client and API, put the relay behind a reverse proxy:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server {
    listen 443 ssl http2;
    server_name relay.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/relay.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/relay.yourdomain.com/privkey.pem;

    # WebSocket support for hbbs
    location / {
        proxy_pass http://127.0.0.1:21118;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # WebSocket relay for hbbr
    location /relay {
        proxy_pass http://127.0.0.1:21119;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

Pros and Cons

Pros: True P2P connectivity, minimal latency on direct connections, excellent NAT traversal, native clients for all platforms, easy to deploy, Rust-based performance, built-in file transfer and TCP tunneling

Cons: Requires agent installation on both ends, proprietary protocol (though open-source), no built-in web management console in the free version, limited protocol support (RustDesk only — no RDP/VNC bridging)


3. MeshCentral (The Full IT Management Platform)

Best for: Comprehensive device fleet management with remote desktop as one feature

Key Features

MeshCentral (by Ylian Saint-Hill, creator of Intel AMT) is a full-featured remote management platform that goes well beyond simple remote desktop. It provides device management, remote terminal access, file management, power control (via Intel AMT), Wake-on-LAN, event logging, user permissions, and alerting — all from a single web interface.

MeshCentral’s architecture is designed for scale:

  • MeshAgent: Lightweight agent installed on managed devices (Windows, Linux, macOS)
  • MeshCentral Server: Node.js-based server with web interface
  • Relay support: Built-in relay for cross-network connectivity
  • Intel AMT support: Out-of-band management for compatible hardware

Docker Deployment

MeshCentral requires a MongoDB (or NeDB for small deployments) backend:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# docker-compose.yml
version: '3'
services:
  mongodb:
    image: mongo:7
    container_name: mesh-mongo
    restart: unless-stopped
    volumes:
      - ./mongodb:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: meshadmin
      MONGO_INITDB_ROOT_PASSWORD: mesh_secure_password_2026

  meshcentral:
    image: typex51/meshcentral:latest
    container_name: meshcentral
    restart: unless-stopped
    depends_on:
      - mongodb
    ports:
      - "4430:443"      # Web interface
      - "4433:4433"      # Mesh agent relay
      - "10001:10001/udp" # Intel AMT
    volumes:
      - ./meshcentral-data:/opt/meshcentral/meshcentral-data
      - ./meshcentral-files:/opt/meshcentral/meshcentral-files
      - ./meshcentral-logs:/opt/meshcentral/meshcentral-logs
    environment:
      - HOSTNAME=mesh.yourdomain.com
      - MONGODB=mongodb://meshadmin:mesh_secure_password_2026@mongodb:27017/meshcentral
      - USE_MONGODB=true

Create the initial configuration file at ./meshcentral-data/config.json:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "settings": {
    "cert": "mesh.yourdomain.com",
    "WANonly": true,
    "_agentHeartbeat": 300
  },
  "domains": {
    "": {
      "title": "IT Operations",
      "title2": "MeshCentral",
      "newAccounts": false,
      "auth": "ldapauth"
    }
  },
  "ldap": {
    "url": "ldap://ldap.yourdomain.com:389",
    "base": "dc=yourdomain,dc=com",
    "bindDN": "cn=mesh,ou=services,dc=yourdomain,dc=com",
    "bindPassword": "ldap_service_password",
    "searchFilter": "(&(objectClass=user)(sAMAccountName={{username}}))",
    "ca": "/opt/meshcentral/meshcentral-data/ca.pem"
  }
}

Start the stack:

1
docker compose up -d

Access the web interface at https://mesh.yourdomain.com:4430. Create the first admin account (disabled newAccounts after setup for security).

Agent Deployment

Deploy the MeshAgent to managed devices. Download the agent installer from the MeshCentral web interface, or deploy via script:

1
2
3
4
5
6
7
8
# Linux agent installation
curl -sSL https://mesh.yourdomain.com:4430/meshagents?id=1&installflags=1 -o meshagent
chmod +x meshagent
sudo ./meshagent -install

# Windows (via PowerShell)
Invoke-WebRequest -Uri "https://mesh.yourdomain.com:4430/meshagents?id=1&installflags=1" -OutFile "$env:TEMP\meshagent.exe"
Start-Process -FilePath "$env:TEMP\meshagent.exe" -ArgumentList "-install" -Wait

Managing Devices

Once agents are installed, devices appear in the MeshCentral web interface organized by groups. For each device, you can:

  • Remote Desktop: Full screen remote control with quality adjustment
  • Terminal: Remote command-line access (Linux shell, Windows CMD/PowerShell)
  • Files: Browse, upload, and download files
  • Wake-on-LAN: Power on devices (requires network configuration)
  • Power Control: Reboot, shutdown, or send Intel AMT commands
  • Event Log: View agent events, connection history, and system changes

Advanced: User Groups and Permissions

MeshCentral supports fine-grained access control. Create user groups with different permission levels:

  • Full Access: Remote desktop, terminal, file transfer, power control
  • View Only: Remote desktop without input (screen sharing)
  • Terminal Only: Command-line access without desktop
  • Custom: Selective permission combination

Permissions can be set per-device or per-group, allowing contractors temporary access to specific machines while restricting others.

Pros and Cons

Pros: Comprehensive IT management beyond just remote desktop, Intel AMT out-of-band management, excellent user permission system, built-in file manager, event logging, group/device organization, active development

Cons: More complex setup than Guacamole or RustDesk, Node.js resource footprint, MongoDB dependency, web-only interface (no native desktop client), steeper learning curve


Network and Firewall Configuration

Each solution has different networking requirements. Here’s what you need to open in your firewall:

PortProtocolGuacamoleRustDeskMeshCentral
80/443TCP✅ Web UI✅ Web UI
3389TCP✅ RDP target
5900TCP✅ VNC target
22TCP✅ SSH target
21115TCP✅ ID server
21116TCP/UDP✅ ID server
21117TCP✅ Relay
21118TCP✅ WebSocket
21119TCP✅ WebSocket
4433TCP✅ Agent relay
10001UDP✅ Intel AMT

For Guacamole, only port 8080 (or 443 behind a reverse proxy) needs to be exposed — all target machine connections originate from the server side. For RustDesk, the relay ports must be reachable from all client machines. For MeshCentral, ports 443 and 4433 must be accessible from managed devices.

Security Best Practices

Regardless of which solution you choose, follow these security fundamentals:

Authentication:

  • Always enable two-factor authentication (TOTP or hardware tokens)
  • Integrate with your LDAP/Active Directory for centralized user management
  • Disable default accounts immediately after setup
  • Implement IP-based access restrictions where possible

Network:

  • Place the remote desktop server behind a reverse proxy with TLS termination
  • Use fail2ban or equivalent to block brute-force attempts
  • Implement rate limiting on the authentication endpoint
  • Consider a bastion host architecture for internet-facing deployments

Session Security:

  • Enable session recording for audit purposes
  • Set idle timeout policies (15-30 minutes recommended)
  • Restrict clipboard sharing and file transfer to trusted users
  • Regularly rotate permanent access passwords

Infrastructure:

  • Keep the server software updated — check for security advisories monthly
  • Run each component in isolated containers with minimal privileges
  • Back up configuration databases (PostgreSQL, MongoDB) daily
  • Monitor connection logs for anomalous access patterns

Choosing the Right Solution

Your choice depends on your primary use case:

  • Choose Apache Guacamole if you need browser-based access to a mixed environment of Windows (RDP), Linux (VNC), and network devices (SSH) without installing agents on endpoints. Ideal for IT teams managing diverse infrastructure.

  • Choose RustDesk if you want the fastest possible connection speeds with minimal latency, need automatic NAT traversal, and are comfortable deploying a lightweight client on both the controller and target machines. Ideal for individual users and small teams.

  • Choose MeshCentral if you need comprehensive device management including power control, file management, terminal access, and user permissions alongside remote desktop. Ideal for IT departments managing fleets of workstations and servers.

All three solutions are fully open-source, actively maintained, and can be deployed on commodity hardware. Start with the Docker compositions provided above, and scale from there based on your requirements.

Frequently Asked Questions (FAQ)

Which one should I choose in 2026?

The best choice depends on your specific requirements:

  • For beginners: Start with the simplest option that covers your core use case
  • For production: Choose the solution with the most active community and documentation
  • For teams: Look for collaboration features and user management
  • For privacy: Prefer fully open-source, self-hosted options with no telemetry

Refer to the comparison table above for detailed feature breakdowns.

Can I migrate between these tools?

Most tools support data import/export. Always:

  1. Backup your current data
  2. Test the migration on a staging environment
  3. Check official migration guides in the documentation

Are there free versions available?

All tools in this guide offer free, open-source editions. Some also provide paid plans with additional features, priority support, or managed hosting.

How do I get started?

  1. Review the comparison table to identify your requirements
  2. Visit the official documentation (links provided above)
  3. Start with a Docker Compose setup for easy testing
  4. Join the community forums for troubleshooting
Advertise here