{"id":30752522,"url":"https://github.com/tommyvange/rustdeskpro-wss","last_synced_at":"2025-10-19T08:37:11.817Z","repository":{"id":311823219,"uuid":"1045134115","full_name":"tommyvange/RustDeskPro-WSS","owner":"tommyvange","description":"Production-ready Docker Compose setup for RustDesk Server Pro with Caddy reverse proxy. Features automatic HTTPS, WebSocket support, secure file permissions, and automated installation. Includes hardened configuration with CORS controls and proper user isolation for enterprise deployments.","archived":false,"fork":false,"pushed_at":"2025-09-03T16:01:17.000Z","size":55,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-03T18:05:06.197Z","etag":null,"topics":["caddyserver","http3","install-script","installer","installer-automation","remote-control","remote-desktop","reverse-proxy-server","rustdesk","rustdesk-server","websocket","websockets"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tommyvange.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-26T17:48:47.000Z","updated_at":"2025-09-03T16:01:17.000Z","dependencies_parsed_at":"2025-08-27T04:49:51.067Z","dependency_job_id":"99502074-bcf8-4b21-9a61-2444f0fd4097","html_url":"https://github.com/tommyvange/RustDeskPro-WSS","commit_stats":null,"previous_names":["tommyvange/rustdeskpro-wss"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tommyvange/RustDeskPro-WSS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyvange%2FRustDeskPro-WSS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyvange%2FRustDeskPro-WSS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyvange%2FRustDeskPro-WSS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyvange%2FRustDeskPro-WSS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tommyvange","download_url":"https://codeload.github.com/tommyvange/RustDeskPro-WSS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tommyvange%2FRustDeskPro-WSS/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273574155,"owners_count":25129883,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-04T02:00:08.968Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["caddyserver","http3","install-script","installer","installer-automation","remote-control","remote-desktop","reverse-proxy-server","rustdesk","rustdesk-server","websocket","websockets"],"created_at":"2025-09-04T08:09:36.257Z","updated_at":"2025-10-19T08:37:11.728Z","avatar_url":"https://github.com/tommyvange.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RustDeskPro-WSS\n\nA production-ready websocket-enabled wrapper to run RustDesk Server Pro (hbbr/hbbs) behind Caddy with automatic HTTPS, Docker Compose, and a hardened firewall posture.\n\n**This setup completely replaces the normal RustDesk direct connection model with websocket-based connections**, providing enhanced security and easier firewall management by routing all traffic through standard HTTPS/websocket protocols.\n\nThis repo gives you two paths:\n- Automated install with `install.sh` (recommended)\n- Manual step-by-step setup (do it yourself, explained in detail)\n\nWorks on Linux servers with Docker. Caddy terminates TLS for your domain and safely proxies websocket endpoints and console access to hbbr/hbbs running on the host network.\n\nTake a look at my scripts for automating Windows client deployment, its called [RustDeskPro-Deployment-Scripts](https://github.com/tommyvange/RustDeskPro-Deployment-Scripts).\n\n---\n\n## Server Requirements and Recommendation\n\nEven though this should be fine to run on an existing server as it is just a Docker stack, we strongly recommend renting a cheap cloud server from a provider like Hetzner or Azure and only running this setup there. Especially if using the install.sh script, as there will be edge cases where the script could break something on existing servers.\n\n**Server requirements (based on RustDesk documentation):**\n- Lowest level VPS is sufficient for most use cases\n- RustDesk Server Pro is not CPU and memory intensive\n- According to RustDesk, their public ID server hosted on a 2 CPU/4 GB Vultr server serves 1.0+ million endpoints\n- Each websocket relay connection consumes avg 180kb per second\n- 1 CPU core and 1GB RAM is enough to support 1000 websocket relay concurrent connections\n\nFor more detailed hardware requirements, see: https://rustdesk.com/docs/en/self-host/rustdesk-server-pro/#hardware-requirement\n\n---\n\n## Quick start (automated install)\n\nPrereqs\n- A Linux server with root/sudo\n- Docker Engine and Docker Compose Plugin installed\n- A DNS A/AAAA record pointing your domain to this server’s public IP\n- UFW or another firewall configured to match the [firewall section](#firewall-ufw-guide).\n\nSteps\n1) Clone the repository\n```bash\ngit clone https://github.com/tommyvange/RustDeskPro-WSS.git\ncd RustDeskPro-WSS\n```\n\n2) Copy the sample environment file and edit values\n```bash\ncp .env.example .env\n${EDITOR:-nano} .env\n```\nRequired:\n- DOMAINS: Comma-separated list (e.g., rd.example.com,servername.westeurope.cloudapp.azure.com). The installer converts this to a space-separated list for Caddy.\n- FILE_LOCATION_CADDY: Where Caddy keeps config/state (default in example: /srv/caddy).\n- FILE_LOCATION_RUSTDESK: Where RustDesk Pro stores data (default in example: /srv/rustdesk).\nOptional:\n- RUSTDESK_CORS: true to keep the strict rustdesk.com-only CORS block; false to remove it.\n- RUSTDESK_NOINDEX: true to add X-Robots-Tag noindex header (blocks search engine indexing); false to allow indexing.\n- HIDE_SERVER_DETAILS: true to remove server identification headers (via, server); false to keep default headers.\n\nNote: Leave UID/GID fields empty; the installer fills them in.\n\n3) Make the installer executable\n```bash\nchmod +x install.sh\n```\n\n4) Run the installer as root (uses Docker, creates system users, writes files)\n```bash\nsudo ./install.sh\n```\n\nVerification\n- Check containers: `docker compose ps`\n- Visit: `https://your-domain` (Caddy auto‑obtains certificates; ensure ports 80/443 are reachable)\n\n---\n\n## Default login\n\nOn first build, RustDesk creates a default user called admin:\n\n- **Username:** `admin`\n- **Password:** `test1234`\n\n**Important:** I recommend completely deleting this account after you have created a new administrator account. \n\nFor more information about logging in and console management, see: https://rustdesk.com/docs/en/self-host/rustdesk-server-pro/console/#log-in\n\n---\n\n## What the installer does\n\nThe `install.sh` script performs these steps safely and idempotently:\n- Validates it runs as root and that Docker/Compose are present\n- Loads variables from `.env` (created from `.env.example`); requires: `DOMAINS`, `FILE_LOCATION_CADDY`, `FILE_LOCATION_RUSTDESK`\n- Creates system users: `rustdesk` and `caddy` (no shell, no home)\n- Writes their UID/GID back into `.env` so `compose.yml` runs containers as those users\n- Creates and permissions data directories\n  - RustDesk: `$FILE_LOCATION_RUSTDESK/data` owned by `rustdesk:rustdesk` (750)\n  - Caddy: `$FILE_LOCATION_CADDY/{data,config}` owned by `caddy:caddy` (750)\n- Processes `Caddyfile`\n  - Replaces `EXAMPLE.COM` with your `DOMAINS` (comma → space list)\n  - Removes the CORS block if `RUSTDESK_CORS=false`; otherwise keeps it\n  - Removes the ROBOTS block if `RUSTDESK_NOINDEX=false`; otherwise keeps it\n  - Removes the SERVER_DETAILS block if `HIDE_SERVER_DETAILS=false`; otherwise keeps it\n  - Copies the processed file to `$FILE_LOCATION_CADDY/Caddyfile` (640, owner `caddy`)\n- Orchestrates containers\n  - `docker compose down` (if any), `pull`, then `up -d --force-recreate`\n  - Prints a final status summary\n\nIf any required bits are missing (Docker not installed, `.env` absent, etc.), the script exits with a clear error and what to fix.\n\n---\n\n## Manual setup (do it yourself)\n\nThis is a simple, copy‑paste friendly guide that avoids the `.env` file. We’ll hardcode clear paths so you see exactly what’s happening.\n\nBefore you start: make sure your domain (for example, example.com) points to your server’s public IP, and Docker is installed.\n\n1) Pick where files will live (you can change these)\n- Caddy files: /srv/caddy\n- RustDesk data: /srv/rustdesk\n\n2) Create the folders\n```bash\nsudo mkdir -p /srv/caddy/data /srv/caddy/config\nsudo mkdir -p /srv/rustdesk/data\n```\n\n3) (Optional but recommended) Create service users for better security\n```bash\nsudo useradd --system --no-create-home --shell /bin/false rustdesk || true\nsudo useradd --system --no-create-home --shell /bin/false caddy || true\n\nid -u rustdesk; id -g rustdesk   # note these numbers, e.g. 998 998\nid -u caddy;    id -g caddy      # note these numbers, e.g. 997 997\n```\nIf you skip this, containers will run as their default users. That’s simpler but less locked‑down.\n\n4) Tell Docker where to store things (edit compose.yml)\n- Open the file `compose.yml` in an editor.\n- Find and replace the paths so they point to your folders:\n  - Change `${FILE_LOCATION_RUSTDESK}/data` to `/srv/rustdesk/data`\n  - Change `${FILE_LOCATION_CADDY}/Caddyfile` to `/srv/caddy/Caddyfile`\n  - Change `${FILE_LOCATION_CADDY}/data` to `/srv/caddy/data`\n  - Change `${FILE_LOCATION_CADDY}/config` to `/srv/caddy/config`\n- About the `user: \"${...}:${...}\"` lines:\n  - If you created users above, replace with the numbers you noted. Example: `user: \"998:998\"`\n  - If you didn’t create users, you can remove or comment out those `user:` lines.\n\n5) Prepare and place the Caddyfile\n- Open the file `Caddyfile` (in this repo) and edit three things:\n  1) Replace `EXAMPLE.COM` with your real domain. If you have www too, write both separated by a space, like:\n     `example.com www.example.com {`\n  2) Decide the CORS block:\n     - Keep it if you want to only allow requests from rustdesk.com\n     - Remove the whole block between `### CORS - START ###` and `### CORS - END ###` if you don’t need that restriction\n  3) Decide the ROBOTS block:\n     - Keep it if you want to prevent search engines from indexing your server (recommended)\n     - Remove the whole block between `### ROBOTS - START ###` and `### ROBOTS - END ###` if you want to allow indexing\n  4) Decide the SERVER_DETAILS block:\n     - Keep it if you want to hide server identification headers like `via` and `server` (recommended)\n     - Remove the whole block between `### SERVER_DETAILS - START ###` and `### SERVER_DETAILS - END ###` if you want to keep default headers\n- Set folder ownership, lock down the folder and copy the Caddyfile.\n```bash\nsudo chown -R caddy:caddy /srv/caddy || true\nsudo chmod -R 750 /srv/caddy\nsudo cp Caddyfile /srv/caddy/Caddyfile\nsudo chmod 640 /srv/caddy/Caddyfile\n```\n\n6) Set ownership on the RustDesk data folder (if you created the user)\n```bash\nsudo chown -R rustdesk:rustdesk /srv/rustdesk || true\nsudo chmod -R 750 /srv/rustdesk\n```\n\n7) Start the containers\n```bash\ndocker compose pull                       # download images (safe to ignore failures)\ndocker compose up -d --force-recreate     # start in the background\ndocker compose ps                         # show status\n```\n\n8) Configure UDP buffers (recommended for optimal performance)\n- For optimal HTTP/3 (QUIC) performance and to avoid UDP buffer warnings in logs, configure system UDP buffer sizes\n- See the [UDP Buffer Configuration](#udp-buffer-configuration) section in Troubleshooting for detailed steps\n- This step is optional but recommended for production deployments\n\n9) Visit your site and test\n- Go to https://your-domain in a browser. Caddy will get a certificate automatically (leave it a minute the first time).\n- If it doesn’t work, check:\n  - DNS is pointing to this server (run `dig +short your-domain` and verify the IP)\n  - Ports 80 and 443 are allowed in your firewall\n  - Logs for the caddy container for any certificate messages\n\nTip: See the Firewall section below for the exact allow/deny rules to use with UFW.\n\n---\n\n## How the stack is wired\n\n- hbbr (RustDesk relay) and hbbs (RustDesk broker) run with `network_mode: host` by design (required by licensing and to expose the expected ports locally)\n- Data volume: `${FILE_LOCATION_RUSTDESK}/data` → container `/root` for both hbbr and hbbs (where RustDesk stores config/state)\n- Caddy also runs on the host network so it can proxy websocket connections to `127.0.0.1:21114/18/19`\n- Caddy mounts:\n  - `${FILE_LOCATION_CADDY}/Caddyfile:/etc/caddy/Caddyfile:ro`\n  - `${FILE_LOCATION_CADDY}/data` (ACME certs/state)\n  - `${FILE_LOCATION_CADDY}/config`\n\n### Architecture map: traffic flow and firewall\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                           INTERNET                                  │\n│                         Users/Clients                               │\n└─────────────────┬───────────────────────────────────────────────────┘\n                  │\n            ┌─────▼─────┐\n            │  Firewall │ \n            │  (UFW)    │ ALLOW: 80/tcp, 443/tcp, 443/udp\n            │           │ DENY:  21114-21119/tcp, 21116/udp\n            └─────┬─────┘\n                  │\n         ┌────────▼─────────┐\n         │  Your Server     │\n         │  Public IP       │\n         └────────┬─────────┘\n                  │\n    ┌─────────────▼──────────────┐\n    │        Caddy Container     │ (network_mode: host)\n    │   - Automatic HTTPS/TLS    │\n    │   - Reverse Proxy          │ Binds to: 80, 443\n    │   - CORS \u0026 Robots handling │\n    │   - Server details hiding │\n    └─────────────┬──────────────┘\n                  │\n         ┌────────▼────────┐\n         │ Request Routing │\n         └─────┬───────────┘\n               │\n      ┌────────▼────────┐\n      │ Path-based      │\n      │ Distribution    │\n      └─┬─────────────┬─┘\n        │             │\n   ┌────▼──────┐ ┌───▼────────────────────┐\n   │/ws/id*    │ │/ws/relay*         /*   │\n   │WebSocket  │ │WebSocket       Console │\n   └────┬──────┘ └───┬──────────┬─────────┘\n        │            │          │\n        │    ┌───────▼──────┐   │\n        │    │              │   │\n        ▼    ▼              ▼   ▼\n┌──────────────┐    ┌──────────────┐\n│ hbbs         │    │ hbbr         │ (network_mode: host)\n│ (RustDesk    │    │ (RustDesk    │\n│  Broker)     │    │  Relay)      │\n│              │    │              │\n│ :21114 (API) │    │ :21119 (WS)  │ Bound to 127.0.0.1\n│ :21118 (WS)  │    │ :21116 (UDP) │ (not Internet-facing)\n└──────────────┘    └──────────────┘\n\nLegend:\n┌─────┐ Container/Service   ▼ Network flow   ─ Firewall rule\n```\n\n**Traffic Flow Examples:**\n- User visits `https://example.com` → Caddy :443 → hbbs :21114 (web console)\n- WebSocket ID request → Caddy `/ws/id*` → hbbs :21118 (websocket connection)\n- WebSocket relay → Caddy `/ws/relay*` → hbbr :21119 (websocket connection)\n- NAT traversal (UDP) → hbbr :21116 (direct, not through Caddy websockets)\n\nTLS: Caddy obtains and renews certificates automatically via HTTPS-01/HTTP-01. Ensure:\n- `DOMAINS` point to this server (A/AAAA records)\n- Ports 80/tcp and 443/tcp+udp reachable from the Internet\n\nCORS: When enabled (default), the Caddyfile allows cross-origin requests from `https://rustdesk.com` only. If you self-host a console on another origin, disable via `RUSTDESK_CORS=false` and tailor the CORS section.\n\nRobots: When enabled (default), the Caddyfile adds the `X-Robots-Tag: noindex` header to all responses, preventing search engines from indexing your RustDesk server. Disable via `RUSTDESK_NOINDEX=false` if you want to allow search engine indexing.\n\nServer Details: When enabled (default), the Caddyfile removes server identification headers (`via`, `server`) to hide that the service is proxied through Caddy. Disable via `HIDE_SERVER_DETAILS=false` if you want to keep the default server headers.\n\n---\n\n## Firewall (UFW) guide\n\nImportant: Before enabling UFW, make sure you allow SSH or you may lock yourself out.\n\nBaseline rules\n```bash\n# Keep your SSH open (adjust if not 22)\nsudo ufw allow 22/tcp\n\n# Public web: HTTPS and HTTP (for ACME http-01 and redirect)\nsudo ufw allow 443/tcp   # HTTPS and websockets via Caddy\nsudo ufw allow 443/udp   # HTTP/3 (QUIC) via Caddy (optional but recommended)\nsudo ufw allow 80/tcp    # ACME challenge + HTTP→HTTPS redirect\n\n# Allow loopback explicitly (good hygiene)\nsudo ufw allow in on lo\n\n# Hide RustDesk backend ports from the Internet (Caddy will proxy)\nsudo ufw deny 21114:21119/tcp  # hbbs console (21114), WS (21118/21119), etc.\nsudo ufw deny 21116/udp        # NAT test\n\n# Enable UFW if not already on\nsudo ufw enable\n\n# Review\nsudo ufw status numbered\n```\n\nWhy these ports?\n- 80/tcp: Caddy uses this for ACME HTTP-01 and to redirect to HTTPS\n- 443/tcp: TLS/HTTPS and websockets for RustDesk endpoints\n- 443/udp: HTTP/3 (QUIC) for faster TLS on supporting clients\n- 21114/21118/21119 (tcp) and 21116 (udp): RustDesk services bound locally; should not be Internet-exposed when proxied by Caddy websockets\n\nIf you run a different firewall (nftables/iptables/cloud), translate the same intent: expose 80/443, keep RustDesk backend ports closed to the outside.\n\n---\n\n## Operations\n\n- Status: `docker compose ps`\n- Logs: `docker compose logs -f --tail=200`\n- Restart: `docker compose restart`\n- Stop: `docker compose down`\n\n### Keeping the Stack Updated\n\nRegular updates ensure you have the latest security patches and features. Follow these steps to update your RustDeskPro-WSS stack:\n\n**1. Check for Updates**\n```bash\n# Check current image versions\ndocker compose images\n\n# Check for newer versions available\ndocker compose pull --dry-run\n```\n\n**2. Create a Backup (Recommended)**\n```bash\n# Stop the stack\ndocker compose down\n\n# Backup data directories\nsudo tar -czf \"rustdesk-backup-$(date +%Y%m%d-%H%M%S).tar.gz\" \\\n  \"${FILE_LOCATION_RUSTDESK}\" \"${FILE_LOCATION_CADDY}\"\n```\n\n**3. Update Images and Restart**\n```bash\n# Pull latest images\ndocker compose pull\n\n# Recreate containers with new images\ndocker compose up -d --force-recreate\n\n# Verify everything is running\ndocker compose ps\ndocker compose logs --tail=50\n```\n\n**4. Monitor After Update**\n- Check logs for any error messages: `docker compose logs -f`\n- Test access to your RustDesk web console\n- Verify WebSocket connections are working properly\n\n**Alternative: Automated Update Script**\nFor regular maintenance, you can create a simple update script:\n```bash\n#!/bin/bash\n# update-rustdesk.sh\ncd /path/to/RustDeskPro-WSS\ndocker compose down\ndocker compose pull\ndocker compose up -d --force-recreate\ndocker compose ps\n```\n\nMake it executable: `chmod +x update-rustdesk.sh`\n\n**Note:** Always test updates in a staging environment first if you're running a production service.\n\nBackups\n- Back up `${FILE_LOCATION_RUSTDESK}` and `${FILE_LOCATION_CADDY}` regularly. They hold RustDesk state and Caddy’s ACME material.\n\nUninstall (manual)\n```bash\ndocker compose down\nsudo rm -rf \"$FILE_LOCATION_RUSTDESK\" \"$FILE_LOCATION_CADDY\"\n# Optionally remove users (only if dedicated to this stack)\nsudo userdel rustdesk || true\nsudo userdel caddy || true\n```\n\n---\n\n## Troubleshooting\n\n- Script says \".env file not found\"\n  - Create `.env` from the template and set at least `DOMAINS`, `FILE_LOCATION_CADDY`, `FILE_LOCATION_RUSTDESK`\n- Caddy can’t obtain a certificate\n  - Check DNS records, make sure ports 80 and 443 are open and not used by another service\n  - Inspect: `docker compose logs caddy`\n- Ports already in use (bind errors)\n  - Another web server (nginx/apache/caddy host install) may be running; stop it or change ports\n- Can’t reach backend ports from the Internet\n  - That’s intentional; access via your domain through Caddy only\n- Docker/Compose not found\n  - Install Docker Engine + Compose Plugin from the official docs\n- UDP buffer size warning in Caddy logs\n  - Message: \"failed to sufficiently increase receive buffer size\"\n  - This affects HTTP/3 (QUIC) performance but doesn't break functionality\n  - The install script automatically configures optimal UDP buffer sizes\n  - For manual setup, see the \"UDP Buffer Configuration\" section below\n\n### UDP Buffer Configuration\n\nThe install script automatically configures system UDP buffer sizes to eliminate QUIC performance warnings. For manual configuration or troubleshooting:\n\n```bash\n# Check current settings\nsysctl net.core.rmem_max net.core.wmem_max\n\n# Apply optimal settings for QUIC\nsudo sysctl -w net.core.rmem_max=8388608\nsudo sysctl -w net.core.rmem_default=1048576\nsudo sysctl -w net.core.wmem_max=8388608\nsudo sysctl -w net.core.wmem_default=1048576\n\n# Make persistent (survives reboots)\nsudo tee /etc/sysctl.d/99-rustdesk-quic.conf \u003c\u003c EOF\nnet.core.rmem_max = 8388608\nnet.core.rmem_default = 1048576\nnet.core.wmem_max = 8388608\nnet.core.wmem_default = 1048576\nEOF\n```\n\nThese settings provide 8 MB buffers, which exceeds the 7 MB that QUIC requests and eliminates the buffer size warnings.\n\n---\n\n## Notes and recommendations\n\n- Images are `:latest` for convenience. For production stability, consider pinning versions in `compose.yml`.\n- This setup assumes Linux; macOS/Windows won’t support `network_mode: host` the same way.\n- Keep your domain list in `.env` up to date. You can rerun the installer any time; it’s safe.\n- Use the included `.env.example` as a starting point and keep it around to document your defaults.\n\n---\n\n## Affiliation\n\nThis repository is not affiliated with either RustDesk or Caddy in any way.\n\n---\n\n## License\n\n[GNU General Public License v3.0 (GPLv3)](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftommyvange%2Frustdeskpro-wss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftommyvange%2Frustdeskpro-wss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftommyvange%2Frustdeskpro-wss/lists"}