Repository files navigation

GoodComms v0.9.99

A self-hosted communication platform for communities that value privacy and control. Chat, voice, and screen sharing using native Rust clients, a lightweight server, and your data on hardware you own.


Why GoodComms?

Most communication platforms, even those that offer "self-hosting," still tie you to a centralized account system, ship as Electron web apps, or collect data somewhere in the pipeline. GoodComms does not.

  • No cloud accounts. You register on the server you connect to. That is the only place your account exists. No global GoodComms account, no OAuth, and no third-party identity provider.
  • No telemetry. No analytics, no tracking, and no external calls. The only optional network dependency is GIF search, which is controlled entirely by the server owner.
  • Pure native clients. Windows and Linux binaries compiled from Rust. No browser engine, no Electron, and no runtime. Download and run. This is the same model as old-school TeamSpeak, before everything moved to the cloud.
  • No surveillance logging. Server logs contain no IP addresses or account identifiers. Privacy by design.
  • Lightweight server. The server authenticates sessions, stores messages in SQLite, and routes media packets without ever processing or decoding them. CPU and RAM requirements are minimal; bandwidth and storage are the real scaling factors.

If you have a friend or community member willing to run a server, all your communication stays between you and them, not a corporation in the middle.


Key Features

  • Native Performance: Chat UI renders on the CPU (tiny-skia). Video pipeline runs on the GPU. Neither interferes with the other.
  • GPU-Accelerated Screen Sharing (Windows): Windows Graphics Capture + D3D11 + MFT H.264. Auto-detects NVIDIA, Intel, or AMD hardware. Software fallback on Linux via PipeWire.
  • Crystal Clear Voice: Opus audio with noise suppression, AGC, push-to-talk, per-user volume, and deafen support.
  • Role-Based Access Control: Hierarchical role system with channel-level and server-wide permissions. Private channels with explicit access control.
  • Server Drive: Built-in private file storage running on your own hardware with no third-party cloud.
  • Webhooks & Slash Commands: Push messages from external services into channels, or trigger external endpoints from chat commands.

For Users — Get Connected

Step 1: Download and Install

  • Windows (Recommended): Run gc-client_0.9.99_x64-setup.exe. Installs with a desktop shortcut. To update, run the new installer.
  • Windows (Portable): Run gc-client.exe directly. Create a data/ folder next to the .exe to enable Portable Mode. All settings, logs, and cache stay in that folder.
  • Linux: Portable binary. Requires PipeWire and xdg-desktop-portal for screen sharing.

Step 2: Add a Server and Log In

  1. Launch the app and click the + icon in the sidebar. Enter the address your admin gave you (e.g. chat.example.com or an IP address) and click Connect.
  2. Create a new account or log in with existing credentials. Accounts are local to each server as there is no global GoodComms account.
  3. Enable Save Password to get a one-click quick-join button on your next launch.

Step 3: Voice Channels

Voice-enabled channels show a Join Voice button. Once in voice, right-click any user for per-user volume controls. Your own mic mute and deafen are at the top of the app.

Step 4: Screen Sharing

Click Go Live in the bottom left and choose a window or display. Your stream attaches to the channel you had open. To watch someone else's stream, open their channel and click Watch next to their name.

Chat Formatting

FormatSyntax
Bold**text**
Italic*text*
Strikethrough~~text~~
Inline code`code`
Code block```code```
Slash commands/me, /shrug, /tableflip, /unflip

For Server Owners

Quick Start — Recommended Setup (Reverse Proxy)

The recommended production setup uses a reverse proxy to handle TLS. GoodComms listens on port 4076; your proxy (Caddy, Nginx, Traefik) forwards HTTPS traffic to it.

How your proxy reaches GoodComms depends on where your proxy runs:

Option A — Proxy on the host (Caddy installed directly on the server)

Expose port 4076 to the host's loopback interface. No shared Docker network needed. GoodComms is self-contained and your proxy hits it via localhost.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppedports:
- "127.0.0.1:4076:4076"# TCP — host-only, your proxy connects here
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logs
# Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:4076
}

Proxy on a different LAN machine? Replace 127.0.0.1:4076:4076 with 4076:4076 to bind to all interfaces, then point your proxy at this server's LAN IP (e.g. reverse_proxy 192.168.1.50:4076). Ensure your firewall blocks port 4076 from the internet as it is plain HTTP.

Option B — Proxy in Docker (Caddy running as a container)

Add both containers to the same Docker network. Caddy reaches GoodComms by container name. No port needs to be exposed to the host at all.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppednetworks:
- proxy-network # Must match the network your Caddy container is onports:
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logsnetworks:
proxy-network:
external: true # Your existing Caddy network
# Caddyfile
chat.yourdomain.com {
reverse_proxy gc-server:4076 # Container name resolves on the shared network
}

For standalone (no domain / LAN) and manual TLS setups, see Deployment Scenarios.

First-Time Setup (Owner Bootstrap)

  1. Uncomment ADMIN_USER and ADMIN_PASS in your compose file and set your credentials before first launch.
  2. Start the server: docker compose up -d
  3. Connect with the client and log in to claim Owner status.
  4. Security: Stop the server (docker compose down), remove the ADMIN_USER and ADMIN_PASS lines, then restart (docker compose up -d). Your account is now in the database. Credentials in a config file are a security risk.

Firewall: UDP ports 4077 and 4078 must be open. TCP is handled by your proxy. Without the UDP ports, voice and video will not work.

Configuration Reference

All options can be set via CLI flag or environment variable. Environment variables take precedence.

FeatureCLI FlagEnv VariableDefault
Bind IP-i, --ipIP_ADDR127.0.0.1
Main Port (TCP)-p, --portPORT443
HTTP Port--http-portHTTP_PORT80
Admin User-a, --adminADMIN_USER(first run only)
Admin Password-w, --passwordADMIN_PASS(first run only)
Voice Port (UDP)-v, --voice-portVOICE_PORT4077
Video Port (UDP)--video-portVIDEO_PORT4078
Database Path--db-pathDATABASE_PATHgoodcomms.db
File Upload DirSTORAGE_DIRuploads
Server Drive DirDRIVE_DIRdrive
Message RetentionRETENTION_DAYS0(disabled)
TLS CertificateTLS_CERT_PATH(auto self-signed)
TLS Private KeyTLS_KEY_PATH(auto self-signed)
Disable TLS--no-tlsNO_TLSfalse
Log Directory--log-dirLOG_DIRlogs

All ports are fully configurable. When using Docker Compose, changing a port requires updating both the environment variable and the ports: mapping. They must match. For example, to run the voice relay on port 5000:

environment:
- VOICE_PORT=5000ports:
- "5000:5000/udp"# was 4077:4077/udp

This applies to PORT, VOICE_PORT, and VIDEO_PORT. The internal PORT value is particularly useful if another service already occupies 4076. Note that for reverse proxy setups, the internal PORT is invisible to clients. Only the proxy's public-facing port matters to them.

CLI example:

./gc-server --port 8443 --admin myname --password mysecret --no-tls

Administration

Roles and Permissions

GoodComms uses a hierarchical role system. Roles with a higher Hierarchy number have authority over lower ones.

Default roles:

  • Owner (Hierarchy 101): Bypasses all permission checks.
  • Administrator (Hierarchy 100): Broad administrative access.
  • Default (Hierarchy 10): Base role for all new members.

Permissions span channel-level controls (view, send, voice, manage messages, manage users, webhooks) and server-wide controls (manage channels, manage roles, drive read/write/manage). See GETTING_STARTED.md for a moderator role walkthrough.

Security Hardening

  • Bootstrapping: No default passwords. Owner credentials must be set explicitly and removed after first login.
  • Revocation: JWT sessions are invalidated immediately on logout or credential change.
  • Privacy: All media, avatars, and drive files require a valid authentication token. No public routes.
  • Hardening: Rate limiting, SSRF protection for link previews, and parameterized queries throughout.

Known Limitations

All Platforms

  • Screen sharing: Starting a second stream in the same app session may not be visible to viewers. Restart the client before streaming again if this occurs.
  • Privacy Settings: A channel cannot be switched between Public and Private after it is created. If you need to change a channel's privacy, please delete it and create a new one.

Linux

  • Screen sharing: System audio loopback is not supported.
  • Audio: Per-user volume sliders can only lower volume, not boost.

Technical Specifications

  • Clients: Native Windows and Linux binaries (Rust). Chat UI: tiny-skia (CPU). Video pipeline: Direct3D 11 + Windows Graphics Capture + MFT H.264 (GPU, Windows); PipeWire + OpenH264 (software, Linux).
  • Server: Single Rust binary. Axum HTTP/WebSocket + UDP relay. SQLite via sqlx. Pure packet relay with zero media processing server-side.
  • Video: Simulcast SFU with FEC parity recovery for single-fragment packet loss. Quality tiers: Source / 1080p / 720p.
  • Audio: Opus codec. Jitter buffer, noise suppression (nnnoiseless), AGC, and push-to-talk.
  • Protocol: V5 binary header (20 bytes) for low-latency media relay.

Further Reading


Getting Help

Found a bug or have a question? Open an issue: github.com/GoodComms/goodcomms/issues


GoodComms v0.9.99 — Engineered for Privacy. Built with Rust.

About

A high-performance, self-hosted communication suite built in Rust. Features a native native media pipeline, zero-Electron architecture, and sovereign data control for chat, voice, and screen sharing.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

GoodComms v0.9.99

A self-hosted communication platform for communities that value privacy and control. Chat, voice, and screen sharing using native Rust clients, a lightweight server, and your data on hardware you own.


Why GoodComms?

Most communication platforms, even those that offer "self-hosting," still tie you to a centralized account system, ship as Electron web apps, or collect data somewhere in the pipeline. GoodComms does not.

  • No cloud accounts. You register on the server you connect to. That is the only place your account exists. No global GoodComms account, no OAuth, and no third-party identity provider.
  • No telemetry. No analytics, no tracking, and no external calls. The only optional network dependency is GIF search, which is controlled entirely by the server owner.
  • Pure native clients. Windows and Linux binaries compiled from Rust. No browser engine, no Electron, and no runtime. Download and run. This is the same model as old-school TeamSpeak, before everything moved to the cloud.
  • No surveillance logging. Server logs contain no IP addresses or account identifiers. Privacy by design.
  • Lightweight server. The server authenticates sessions, stores messages in SQLite, and routes media packets without ever processing or decoding them. CPU and RAM requirements are minimal; bandwidth and storage are the real scaling factors.

If you have a friend or community member willing to run a server, all your communication stays between you and them, not a corporation in the middle.


Key Features

  • Native Performance: Chat UI renders on the CPU (tiny-skia). Video pipeline runs on the GPU. Neither interferes with the other.
  • GPU-Accelerated Screen Sharing (Windows): Windows Graphics Capture + D3D11 + MFT H.264. Auto-detects NVIDIA, Intel, or AMD hardware. Software fallback on Linux via PipeWire.
  • Crystal Clear Voice: Opus audio with noise suppression, AGC, push-to-talk, per-user volume, and deafen support.
  • Role-Based Access Control: Hierarchical role system with channel-level and server-wide permissions. Private channels with explicit access control.
  • Server Drive: Built-in private file storage running on your own hardware with no third-party cloud.
  • Webhooks & Slash Commands: Push messages from external services into channels, or trigger external endpoints from chat commands.

For Users — Get Connected

Step 1: Download and Install

  • Windows (Recommended): Run gc-client_0.9.99_x64-setup.exe. Installs with a desktop shortcut. To update, run the new installer.
  • Windows (Portable): Run gc-client.exe directly. Create a data/ folder next to the .exe to enable Portable Mode. All settings, logs, and cache stay in that folder.
  • Linux: Portable binary. Requires PipeWire and xdg-desktop-portal for screen sharing.

Step 2: Add a Server and Log In

  1. Launch the app and click the + icon in the sidebar. Enter the address your admin gave you (e.g. chat.example.com or an IP address) and click Connect.
  2. Create a new account or log in with existing credentials. Accounts are local to each server as there is no global GoodComms account.
  3. Enable Save Password to get a one-click quick-join button on your next launch.

Step 3: Voice Channels

Voice-enabled channels show a Join Voice button. Once in voice, right-click any user for per-user volume controls. Your own mic mute and deafen are at the top of the app.

Step 4: Screen Sharing

Click Go Live in the bottom left and choose a window or display. Your stream attaches to the channel you had open. To watch someone else's stream, open their channel and click Watch next to their name.

Chat Formatting

FormatSyntax
Bold**text**
Italic*text*
Strikethrough~~text~~
Inline code`code`
Code block```code```
Slash commands/me, /shrug, /tableflip, /unflip

For Server Owners

Quick Start — Recommended Setup (Reverse Proxy)

The recommended production setup uses a reverse proxy to handle TLS. GoodComms listens on port 4076; your proxy (Caddy, Nginx, Traefik) forwards HTTPS traffic to it.

How your proxy reaches GoodComms depends on where your proxy runs:

Option A — Proxy on the host (Caddy installed directly on the server)

Expose port 4076 to the host's loopback interface. No shared Docker network needed. GoodComms is self-contained and your proxy hits it via localhost.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppedports:
- "127.0.0.1:4076:4076"# TCP — host-only, your proxy connects here
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logs
# Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:4076
}

Proxy on a different LAN machine? Replace 127.0.0.1:4076:4076 with 4076:4076 to bind to all interfaces, then point your proxy at this server's LAN IP (e.g. reverse_proxy 192.168.1.50:4076). Ensure your firewall blocks port 4076 from the internet as it is plain HTTP.

Option B — Proxy in Docker (Caddy running as a container)

Add both containers to the same Docker network. Caddy reaches GoodComms by container name. No port needs to be exposed to the host at all.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppednetworks:
- proxy-network # Must match the network your Caddy container is onports:
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logsnetworks:
proxy-network:
external: true # Your existing Caddy network
# Caddyfile
chat.yourdomain.com {
reverse_proxy gc-server:4076 # Container name resolves on the shared network
}

For standalone (no domain / LAN) and manual TLS setups, see Deployment Scenarios.

First-Time Setup (Owner Bootstrap)

  1. Uncomment ADMIN_USER and ADMIN_PASS in your compose file and set your credentials before first launch.
  2. Start the server: docker compose up -d
  3. Connect with the client and log in to claim Owner status.
  4. Security: Stop the server (docker compose down), remove the ADMIN_USER and ADMIN_PASS lines, then restart (docker compose up -d). Your account is now in the database. Credentials in a config file are a security risk.

Firewall: UDP ports 4077 and 4078 must be open. TCP is handled by your proxy. Without the UDP ports, voice and video will not work.

Configuration Reference

All options can be set via CLI flag or environment variable. Environment variables take precedence.

FeatureCLI FlagEnv VariableDefault
Bind IP-i, --ipIP_ADDR127.0.0.1
Main Port (TCP)-p, --portPORT443
HTTP Port--http-portHTTP_PORT80
Admin User-a, --adminADMIN_USER(first run only)
Admin Password-w, --passwordADMIN_PASS(first run only)
Voice Port (UDP)-v, --voice-portVOICE_PORT4077
Video Port (UDP)--video-portVIDEO_PORT4078
Database Path--db-pathDATABASE_PATHgoodcomms.db
File Upload DirSTORAGE_DIRuploads
Server Drive DirDRIVE_DIRdrive
Message RetentionRETENTION_DAYS0(disabled)
TLS CertificateTLS_CERT_PATH(auto self-signed)
TLS Private KeyTLS_KEY_PATH(auto self-signed)
Disable TLS--no-tlsNO_TLSfalse
Log Directory--log-dirLOG_DIRlogs

All ports are fully configurable. When using Docker Compose, changing a port requires updating both the environment variable and the ports: mapping. They must match. For example, to run the voice relay on port 5000:

environment:
- VOICE_PORT=5000ports:
- "5000:5000/udp"# was 4077:4077/udp

This applies to PORT, VOICE_PORT, and VIDEO_PORT. The internal PORT value is particularly useful if another service already occupies 4076. Note that for reverse proxy setups, the internal PORT is invisible to clients. Only the proxy's public-facing port matters to them.

CLI example:

./gc-server --port 8443 --admin myname --password mysecret --no-tls

Administration

Roles and Permissions

GoodComms uses a hierarchical role system. Roles with a higher Hierarchy number have authority over lower ones.

Default roles:

  • Owner (Hierarchy 101): Bypasses all permission checks.
  • Administrator (Hierarchy 100): Broad administrative access.
  • Default (Hierarchy 10): Base role for all new members.

Permissions span channel-level controls (view, send, voice, manage messages, manage users, webhooks) and server-wide controls (manage channels, manage roles, drive read/write/manage). See GETTING_STARTED.md for a moderator role walkthrough.

Security Hardening

  • Bootstrapping: No default passwords. Owner credentials must be set explicitly and removed after first login.
  • Revocation: JWT sessions are invalidated immediately on logout or credential change.
  • Privacy: All media, avatars, and drive files require a valid authentication token. No public routes.
  • Hardening: Rate limiting, SSRF protection for link previews, and parameterized queries throughout.

Known Limitations

All Platforms

  • Screen sharing: Starting a second stream in the same app session may not be visible to viewers. Restart the client before streaming again if this occurs.
  • Privacy Settings: A channel cannot be switched between Public and Private after it is created. If you need to change a channel's privacy, please delete it and create a new one.

Linux

  • Screen sharing: System audio loopback is not supported.
  • Audio: Per-user volume sliders can only lower volume, not boost.

Technical Specifications

  • Clients: Native Windows and Linux binaries (Rust). Chat UI: tiny-skia (CPU). Video pipeline: Direct3D 11 + Windows Graphics Capture + MFT H.264 (GPU, Windows); PipeWire + OpenH264 (software, Linux).
  • Server: Single Rust binary. Axum HTTP/WebSocket + UDP relay. SQLite via sqlx. Pure packet relay with zero media processing server-side.
  • Video: Simulcast SFU with FEC parity recovery for single-fragment packet loss. Quality tiers: Source / 1080p / 720p.
  • Audio: Opus codec. Jitter buffer, noise suppression (nnnoiseless), AGC, and push-to-talk.
  • Protocol: V5 binary header (20 bytes) for low-latency media relay.

Further Reading


Getting Help

Found a bug or have a question? Open an issue: github.com/GoodComms/goodcomms/issues


GoodComms v0.9.99 — Engineered for Privacy. Built with Rust.

About

A high-performance, self-hosted communication suite built in Rust. Features a native native media pipeline, zero-Electron architecture, and sovereign data control for chat, voice, and screen sharing.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

GoodComms v0.9.99

A self-hosted communication platform for communities that value privacy and control. Chat, voice, and screen sharing using native Rust clients, a lightweight server, and your data on hardware you own.


Why GoodComms?

Most communication platforms, even those that offer "self-hosting," still tie you to a centralized account system, ship as Electron web apps, or collect data somewhere in the pipeline. GoodComms does not.

  • No cloud accounts. You register on the server you connect to. That is the only place your account exists. No global GoodComms account, no OAuth, and no third-party identity provider.
  • No telemetry. No analytics, no tracking, and no external calls. The only optional network dependency is GIF search, which is controlled entirely by the server owner.
  • Pure native clients. Windows and Linux binaries compiled from Rust. No browser engine, no Electron, and no runtime. Download and run. This is the same model as old-school TeamSpeak, before everything moved to the cloud.
  • No surveillance logging. Server logs contain no IP addresses or account identifiers. Privacy by design.
  • Lightweight server. The server authenticates sessions, stores messages in SQLite, and routes media packets without ever processing or decoding them. CPU and RAM requirements are minimal; bandwidth and storage are the real scaling factors.

If you have a friend or community member willing to run a server, all your communication stays between you and them, not a corporation in the middle.


Key Features

  • Native Performance: Chat UI renders on the CPU (tiny-skia). Video pipeline runs on the GPU. Neither interferes with the other.
  • GPU-Accelerated Screen Sharing (Windows): Windows Graphics Capture + D3D11 + MFT H.264. Auto-detects NVIDIA, Intel, or AMD hardware. Software fallback on Linux via PipeWire.
  • Crystal Clear Voice: Opus audio with noise suppression, AGC, push-to-talk, per-user volume, and deafen support.
  • Role-Based Access Control: Hierarchical role system with channel-level and server-wide permissions. Private channels with explicit access control.
  • Server Drive: Built-in private file storage running on your own hardware with no third-party cloud.
  • Webhooks & Slash Commands: Push messages from external services into channels, or trigger external endpoints from chat commands.

For Users — Get Connected

Step 1: Download and Install

  • Windows (Recommended): Run gc-client_0.9.99_x64-setup.exe. Installs with a desktop shortcut. To update, run the new installer.
  • Windows (Portable): Run gc-client.exe directly. Create a data/ folder next to the .exe to enable Portable Mode. All settings, logs, and cache stay in that folder.
  • Linux: Portable binary. Requires PipeWire and xdg-desktop-portal for screen sharing.

Step 2: Add a Server and Log In

  1. Launch the app and click the + icon in the sidebar. Enter the address your admin gave you (e.g. chat.example.com or an IP address) and click Connect.
  2. Create a new account or log in with existing credentials. Accounts are local to each server as there is no global GoodComms account.
  3. Enable Save Password to get a one-click quick-join button on your next launch.

Step 3: Voice Channels

Voice-enabled channels show a Join Voice button. Once in voice, right-click any user for per-user volume controls. Your own mic mute and deafen are at the top of the app.

Step 4: Screen Sharing

Click Go Live in the bottom left and choose a window or display. Your stream attaches to the channel you had open. To watch someone else's stream, open their channel and click Watch next to their name.

Chat Formatting

FormatSyntax
Bold**text**
Italic*text*
Strikethrough~~text~~
Inline code`code`
Code block```code```
Slash commands/me, /shrug, /tableflip, /unflip

For Server Owners

Quick Start — Recommended Setup (Reverse Proxy)

The recommended production setup uses a reverse proxy to handle TLS. GoodComms listens on port 4076; your proxy (Caddy, Nginx, Traefik) forwards HTTPS traffic to it.

How your proxy reaches GoodComms depends on where your proxy runs:

Option A — Proxy on the host (Caddy installed directly on the server)

Expose port 4076 to the host's loopback interface. No shared Docker network needed. GoodComms is self-contained and your proxy hits it via localhost.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppedports:
- "127.0.0.1:4076:4076"# TCP — host-only, your proxy connects here
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logs
# Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:4076
}

Proxy on a different LAN machine? Replace 127.0.0.1:4076:4076 with 4076:4076 to bind to all interfaces, then point your proxy at this server's LAN IP (e.g. reverse_proxy 192.168.1.50:4076). Ensure your firewall blocks port 4076 from the internet as it is plain HTTP.

Option B — Proxy in Docker (Caddy running as a container)

Add both containers to the same Docker network. Caddy reaches GoodComms by container name. No port needs to be exposed to the host at all.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppednetworks:
- proxy-network # Must match the network your Caddy container is onports:
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logsnetworks:
proxy-network:
external: true # Your existing Caddy network
# Caddyfile
chat.yourdomain.com {
reverse_proxy gc-server:4076 # Container name resolves on the shared network
}

For standalone (no domain / LAN) and manual TLS setups, see Deployment Scenarios.

First-Time Setup (Owner Bootstrap)

  1. Uncomment ADMIN_USER and ADMIN_PASS in your compose file and set your credentials before first launch.
  2. Start the server: docker compose up -d
  3. Connect with the client and log in to claim Owner status.
  4. Security: Stop the server (docker compose down), remove the ADMIN_USER and ADMIN_PASS lines, then restart (docker compose up -d). Your account is now in the database. Credentials in a config file are a security risk.

Firewall: UDP ports 4077 and 4078 must be open. TCP is handled by your proxy. Without the UDP ports, voice and video will not work.

Configuration Reference

All options can be set via CLI flag or environment variable. Environment variables take precedence.

FeatureCLI FlagEnv VariableDefault
Bind IP-i, --ipIP_ADDR127.0.0.1
Main Port (TCP)-p, --portPORT443
HTTP Port--http-portHTTP_PORT80
Admin User-a, --adminADMIN_USER(first run only)
Admin Password-w, --passwordADMIN_PASS(first run only)
Voice Port (UDP)-v, --voice-portVOICE_PORT4077
Video Port (UDP)--video-portVIDEO_PORT4078
Database Path--db-pathDATABASE_PATHgoodcomms.db
File Upload DirSTORAGE_DIRuploads
Server Drive DirDRIVE_DIRdrive
Message RetentionRETENTION_DAYS0(disabled)
TLS CertificateTLS_CERT_PATH(auto self-signed)
TLS Private KeyTLS_KEY_PATH(auto self-signed)
Disable TLS--no-tlsNO_TLSfalse
Log Directory--log-dirLOG_DIRlogs

All ports are fully configurable. When using Docker Compose, changing a port requires updating both the environment variable and the ports: mapping. They must match. For example, to run the voice relay on port 5000:

environment:
- VOICE_PORT=5000ports:
- "5000:5000/udp"# was 4077:4077/udp

This applies to PORT, VOICE_PORT, and VIDEO_PORT. The internal PORT value is particularly useful if another service already occupies 4076. Note that for reverse proxy setups, the internal PORT is invisible to clients. Only the proxy's public-facing port matters to them.

CLI example:

./gc-server --port 8443 --admin myname --password mysecret --no-tls

Administration

Roles and Permissions

GoodComms uses a hierarchical role system. Roles with a higher Hierarchy number have authority over lower ones.

Default roles:

  • Owner (Hierarchy 101): Bypasses all permission checks.
  • Administrator (Hierarchy 100): Broad administrative access.
  • Default (Hierarchy 10): Base role for all new members.

Permissions span channel-level controls (view, send, voice, manage messages, manage users, webhooks) and server-wide controls (manage channels, manage roles, drive read/write/manage). See GETTING_STARTED.md for a moderator role walkthrough.

Security Hardening

  • Bootstrapping: No default passwords. Owner credentials must be set explicitly and removed after first login.
  • Revocation: JWT sessions are invalidated immediately on logout or credential change.
  • Privacy: All media, avatars, and drive files require a valid authentication token. No public routes.
  • Hardening: Rate limiting, SSRF protection for link previews, and parameterized queries throughout.

Known Limitations

All Platforms

  • Screen sharing: Starting a second stream in the same app session may not be visible to viewers. Restart the client before streaming again if this occurs.
  • Privacy Settings: A channel cannot be switched between Public and Private after it is created. If you need to change a channel's privacy, please delete it and create a new one.

Linux

  • Screen sharing: System audio loopback is not supported.
  • Audio: Per-user volume sliders can only lower volume, not boost.

Technical Specifications

  • Clients: Native Windows and Linux binaries (Rust). Chat UI: tiny-skia (CPU). Video pipeline: Direct3D 11 + Windows Graphics Capture + MFT H.264 (GPU, Windows); PipeWire + OpenH264 (software, Linux).
  • Server: Single Rust binary. Axum HTTP/WebSocket + UDP relay. SQLite via sqlx. Pure packet relay with zero media processing server-side.
  • Video: Simulcast SFU with FEC parity recovery for single-fragment packet loss. Quality tiers: Source / 1080p / 720p.
  • Audio: Opus codec. Jitter buffer, noise suppression (nnnoiseless), AGC, and push-to-talk.
  • Protocol: V5 binary header (20 bytes) for low-latency media relay.

Further Reading


Getting Help

Found a bug or have a question? Open an issue: github.com/GoodComms/goodcomms/issues


GoodComms v0.9.99 — Engineered for Privacy. Built with Rust.

About

A high-performance, self-hosted communication suite built in Rust. Features a native native media pipeline, zero-Electron architecture, and sovereign data control for chat, voice, and screen sharing.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

GoodComms v0.9.99

A self-hosted communication platform for communities that value privacy and control. Chat, voice, and screen sharing using native Rust clients, a lightweight server, and your data on hardware you own.


Why GoodComms?

Most communication platforms, even those that offer "self-hosting," still tie you to a centralized account system, ship as Electron web apps, or collect data somewhere in the pipeline. GoodComms does not.

  • No cloud accounts. You register on the server you connect to. That is the only place your account exists. No global GoodComms account, no OAuth, and no third-party identity provider.
  • No telemetry. No analytics, no tracking, and no external calls. The only optional network dependency is GIF search, which is controlled entirely by the server owner.
  • Pure native clients. Windows and Linux binaries compiled from Rust. No browser engine, no Electron, and no runtime. Download and run. This is the same model as old-school TeamSpeak, before everything moved to the cloud.
  • No surveillance logging. Server logs contain no IP addresses or account identifiers. Privacy by design.
  • Lightweight server. The server authenticates sessions, stores messages in SQLite, and routes media packets without ever processing or decoding them. CPU and RAM requirements are minimal; bandwidth and storage are the real scaling factors.

If you have a friend or community member willing to run a server, all your communication stays between you and them, not a corporation in the middle.


Key Features

  • Native Performance: Chat UI renders on the CPU (tiny-skia). Video pipeline runs on the GPU. Neither interferes with the other.
  • GPU-Accelerated Screen Sharing (Windows): Windows Graphics Capture + D3D11 + MFT H.264. Auto-detects NVIDIA, Intel, or AMD hardware. Software fallback on Linux via PipeWire.
  • Crystal Clear Voice: Opus audio with noise suppression, AGC, push-to-talk, per-user volume, and deafen support.
  • Role-Based Access Control: Hierarchical role system with channel-level and server-wide permissions. Private channels with explicit access control.
  • Server Drive: Built-in private file storage running on your own hardware with no third-party cloud.
  • Webhooks & Slash Commands: Push messages from external services into channels, or trigger external endpoints from chat commands.

For Users — Get Connected

Step 1: Download and Install

  • Windows (Recommended): Run gc-client_0.9.99_x64-setup.exe. Installs with a desktop shortcut. To update, run the new installer.
  • Windows (Portable): Run gc-client.exe directly. Create a data/ folder next to the .exe to enable Portable Mode. All settings, logs, and cache stay in that folder.
  • Linux: Portable binary. Requires PipeWire and xdg-desktop-portal for screen sharing.

Step 2: Add a Server and Log In

  1. Launch the app and click the + icon in the sidebar. Enter the address your admin gave you (e.g. chat.example.com or an IP address) and click Connect.
  2. Create a new account or log in with existing credentials. Accounts are local to each server as there is no global GoodComms account.
  3. Enable Save Password to get a one-click quick-join button on your next launch.

Step 3: Voice Channels

Voice-enabled channels show a Join Voice button. Once in voice, right-click any user for per-user volume controls. Your own mic mute and deafen are at the top of the app.

Step 4: Screen Sharing

Click Go Live in the bottom left and choose a window or display. Your stream attaches to the channel you had open. To watch someone else's stream, open their channel and click Watch next to their name.

Chat Formatting

FormatSyntax
Bold**text**
Italic*text*
Strikethrough~~text~~
Inline code`code`
Code block```code```
Slash commands/me, /shrug, /tableflip, /unflip

For Server Owners

Quick Start — Recommended Setup (Reverse Proxy)

The recommended production setup uses a reverse proxy to handle TLS. GoodComms listens on port 4076; your proxy (Caddy, Nginx, Traefik) forwards HTTPS traffic to it.

How your proxy reaches GoodComms depends on where your proxy runs:

Option A — Proxy on the host (Caddy installed directly on the server)

Expose port 4076 to the host's loopback interface. No shared Docker network needed. GoodComms is self-contained and your proxy hits it via localhost.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppedports:
- "127.0.0.1:4076:4076"# TCP — host-only, your proxy connects here
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logs
# Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:4076
}

Proxy on a different LAN machine? Replace 127.0.0.1:4076:4076 with 4076:4076 to bind to all interfaces, then point your proxy at this server's LAN IP (e.g. reverse_proxy 192.168.1.50:4076). Ensure your firewall blocks port 4076 from the internet as it is plain HTTP.

Option B — Proxy in Docker (Caddy running as a container)

Add both containers to the same Docker network. Caddy reaches GoodComms by container name. No port needs to be exposed to the host at all.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppednetworks:
- proxy-network # Must match the network your Caddy container is onports:
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logsnetworks:
proxy-network:
external: true # Your existing Caddy network
# Caddyfile
chat.yourdomain.com {
reverse_proxy gc-server:4076 # Container name resolves on the shared network
}

For standalone (no domain / LAN) and manual TLS setups, see Deployment Scenarios.

First-Time Setup (Owner Bootstrap)

  1. Uncomment ADMIN_USER and ADMIN_PASS in your compose file and set your credentials before first launch.
  2. Start the server: docker compose up -d
  3. Connect with the client and log in to claim Owner status.
  4. Security: Stop the server (docker compose down), remove the ADMIN_USER and ADMIN_PASS lines, then restart (docker compose up -d). Your account is now in the database. Credentials in a config file are a security risk.

Firewall: UDP ports 4077 and 4078 must be open. TCP is handled by your proxy. Without the UDP ports, voice and video will not work.

Configuration Reference

All options can be set via CLI flag or environment variable. Environment variables take precedence.

FeatureCLI FlagEnv VariableDefault
Bind IP-i, --ipIP_ADDR127.0.0.1
Main Port (TCP)-p, --portPORT443
HTTP Port--http-portHTTP_PORT80
Admin User-a, --adminADMIN_USER(first run only)
Admin Password-w, --passwordADMIN_PASS(first run only)
Voice Port (UDP)-v, --voice-portVOICE_PORT4077
Video Port (UDP)--video-portVIDEO_PORT4078
Database Path--db-pathDATABASE_PATHgoodcomms.db
File Upload DirSTORAGE_DIRuploads
Server Drive DirDRIVE_DIRdrive
Message RetentionRETENTION_DAYS0(disabled)
TLS CertificateTLS_CERT_PATH(auto self-signed)
TLS Private KeyTLS_KEY_PATH(auto self-signed)
Disable TLS--no-tlsNO_TLSfalse
Log Directory--log-dirLOG_DIRlogs

All ports are fully configurable. When using Docker Compose, changing a port requires updating both the environment variable and the ports: mapping. They must match. For example, to run the voice relay on port 5000:

environment:
- VOICE_PORT=5000ports:
- "5000:5000/udp"# was 4077:4077/udp

This applies to PORT, VOICE_PORT, and VIDEO_PORT. The internal PORT value is particularly useful if another service already occupies 4076. Note that for reverse proxy setups, the internal PORT is invisible to clients. Only the proxy's public-facing port matters to them.

CLI example:

./gc-server --port 8443 --admin myname --password mysecret --no-tls

Administration

Roles and Permissions

GoodComms uses a hierarchical role system. Roles with a higher Hierarchy number have authority over lower ones.

Default roles:

  • Owner (Hierarchy 101): Bypasses all permission checks.
  • Administrator (Hierarchy 100): Broad administrative access.
  • Default (Hierarchy 10): Base role for all new members.

Permissions span channel-level controls (view, send, voice, manage messages, manage users, webhooks) and server-wide controls (manage channels, manage roles, drive read/write/manage). See GETTING_STARTED.md for a moderator role walkthrough.

Security Hardening

  • Bootstrapping: No default passwords. Owner credentials must be set explicitly and removed after first login.
  • Revocation: JWT sessions are invalidated immediately on logout or credential change.
  • Privacy: All media, avatars, and drive files require a valid authentication token. No public routes.
  • Hardening: Rate limiting, SSRF protection for link previews, and parameterized queries throughout.

Known Limitations

All Platforms

  • Screen sharing: Starting a second stream in the same app session may not be visible to viewers. Restart the client before streaming again if this occurs.
  • Privacy Settings: A channel cannot be switched between Public and Private after it is created. If you need to change a channel's privacy, please delete it and create a new one.

Linux

  • Screen sharing: System audio loopback is not supported.
  • Audio: Per-user volume sliders can only lower volume, not boost.

Technical Specifications

  • Clients: Native Windows and Linux binaries (Rust). Chat UI: tiny-skia (CPU). Video pipeline: Direct3D 11 + Windows Graphics Capture + MFT H.264 (GPU, Windows); PipeWire + OpenH264 (software, Linux).
  • Server: Single Rust binary. Axum HTTP/WebSocket + UDP relay. SQLite via sqlx. Pure packet relay with zero media processing server-side.
  • Video: Simulcast SFU with FEC parity recovery for single-fragment packet loss. Quality tiers: Source / 1080p / 720p.
  • Audio: Opus codec. Jitter buffer, noise suppression (nnnoiseless), AGC, and push-to-talk.
  • Protocol: V5 binary header (20 bytes) for low-latency media relay.

Further Reading


Getting Help

Found a bug or have a question? Open an issue: github.com/GoodComms/goodcomms/issues


GoodComms v0.9.99 — Engineered for Privacy. Built with Rust.

About

A high-performance, self-hosted communication suite built in Rust. Features a native native media pipeline, zero-Electron architecture, and sovereign data control for chat, voice, and screen sharing.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

GoodComms v0.9.99

A self-hosted communication platform for communities that value privacy and control. Chat, voice, and screen sharing using native Rust clients, a lightweight server, and your data on hardware you own.


Why GoodComms?

Most communication platforms, even those that offer "self-hosting," still tie you to a centralized account system, ship as Electron web apps, or collect data somewhere in the pipeline. GoodComms does not.

  • No cloud accounts. You register on the server you connect to. That is the only place your account exists. No global GoodComms account, no OAuth, and no third-party identity provider.
  • No telemetry. No analytics, no tracking, and no external calls. The only optional network dependency is GIF search, which is controlled entirely by the server owner.
  • Pure native clients. Windows and Linux binaries compiled from Rust. No browser engine, no Electron, and no runtime. Download and run. This is the same model as old-school TeamSpeak, before everything moved to the cloud.
  • No surveillance logging. Server logs contain no IP addresses or account identifiers. Privacy by design.
  • Lightweight server. The server authenticates sessions, stores messages in SQLite, and routes media packets without ever processing or decoding them. CPU and RAM requirements are minimal; bandwidth and storage are the real scaling factors.

If you have a friend or community member willing to run a server, all your communication stays between you and them, not a corporation in the middle.


Key Features

  • Native Performance: Chat UI renders on the CPU (tiny-skia). Video pipeline runs on the GPU. Neither interferes with the other.
  • GPU-Accelerated Screen Sharing (Windows): Windows Graphics Capture + D3D11 + MFT H.264. Auto-detects NVIDIA, Intel, or AMD hardware. Software fallback on Linux via PipeWire.
  • Crystal Clear Voice: Opus audio with noise suppression, AGC, push-to-talk, per-user volume, and deafen support.
  • Role-Based Access Control: Hierarchical role system with channel-level and server-wide permissions. Private channels with explicit access control.
  • Server Drive: Built-in private file storage running on your own hardware with no third-party cloud.
  • Webhooks & Slash Commands: Push messages from external services into channels, or trigger external endpoints from chat commands.

For Users — Get Connected

Step 1: Download and Install

  • Windows (Recommended): Run gc-client_0.9.99_x64-setup.exe. Installs with a desktop shortcut. To update, run the new installer.
  • Windows (Portable): Run gc-client.exe directly. Create a data/ folder next to the .exe to enable Portable Mode. All settings, logs, and cache stay in that folder.
  • Linux: Portable binary. Requires PipeWire and xdg-desktop-portal for screen sharing.

Step 2: Add a Server and Log In

  1. Launch the app and click the + icon in the sidebar. Enter the address your admin gave you (e.g. chat.example.com or an IP address) and click Connect.
  2. Create a new account or log in with existing credentials. Accounts are local to each server as there is no global GoodComms account.
  3. Enable Save Password to get a one-click quick-join button on your next launch.

Step 3: Voice Channels

Voice-enabled channels show a Join Voice button. Once in voice, right-click any user for per-user volume controls. Your own mic mute and deafen are at the top of the app.

Step 4: Screen Sharing

Click Go Live in the bottom left and choose a window or display. Your stream attaches to the channel you had open. To watch someone else's stream, open their channel and click Watch next to their name.

Chat Formatting

FormatSyntax
Bold**text**
Italic*text*
Strikethrough~~text~~
Inline code`code`
Code block```code```
Slash commands/me, /shrug, /tableflip, /unflip

For Server Owners

Quick Start — Recommended Setup (Reverse Proxy)

The recommended production setup uses a reverse proxy to handle TLS. GoodComms listens on port 4076; your proxy (Caddy, Nginx, Traefik) forwards HTTPS traffic to it.

How your proxy reaches GoodComms depends on where your proxy runs:

Option A — Proxy on the host (Caddy installed directly on the server)

Expose port 4076 to the host's loopback interface. No shared Docker network needed. GoodComms is self-contained and your proxy hits it via localhost.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppedports:
- "127.0.0.1:4076:4076"# TCP — host-only, your proxy connects here
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logs
# Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:4076
}

Proxy on a different LAN machine? Replace 127.0.0.1:4076:4076 with 4076:4076 to bind to all interfaces, then point your proxy at this server's LAN IP (e.g. reverse_proxy 192.168.1.50:4076). Ensure your firewall blocks port 4076 from the internet as it is plain HTTP.

Option B — Proxy in Docker (Caddy running as a container)

Add both containers to the same Docker network. Caddy reaches GoodComms by container name. No port needs to be exposed to the host at all.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppednetworks:
- proxy-network # Must match the network your Caddy container is onports:
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logsnetworks:
proxy-network:
external: true # Your existing Caddy network
# Caddyfile
chat.yourdomain.com {
reverse_proxy gc-server:4076 # Container name resolves on the shared network
}

For standalone (no domain / LAN) and manual TLS setups, see Deployment Scenarios.

First-Time Setup (Owner Bootstrap)

  1. Uncomment ADMIN_USER and ADMIN_PASS in your compose file and set your credentials before first launch.
  2. Start the server: docker compose up -d
  3. Connect with the client and log in to claim Owner status.
  4. Security: Stop the server (docker compose down), remove the ADMIN_USER and ADMIN_PASS lines, then restart (docker compose up -d). Your account is now in the database. Credentials in a config file are a security risk.

Firewall: UDP ports 4077 and 4078 must be open. TCP is handled by your proxy. Without the UDP ports, voice and video will not work.

Configuration Reference

All options can be set via CLI flag or environment variable. Environment variables take precedence.

FeatureCLI FlagEnv VariableDefault
Bind IP-i, --ipIP_ADDR127.0.0.1
Main Port (TCP)-p, --portPORT443
HTTP Port--http-portHTTP_PORT80
Admin User-a, --adminADMIN_USER(first run only)
Admin Password-w, --passwordADMIN_PASS(first run only)
Voice Port (UDP)-v, --voice-portVOICE_PORT4077
Video Port (UDP)--video-portVIDEO_PORT4078
Database Path--db-pathDATABASE_PATHgoodcomms.db
File Upload DirSTORAGE_DIRuploads
Server Drive DirDRIVE_DIRdrive
Message RetentionRETENTION_DAYS0(disabled)
TLS CertificateTLS_CERT_PATH(auto self-signed)
TLS Private KeyTLS_KEY_PATH(auto self-signed)
Disable TLS--no-tlsNO_TLSfalse
Log Directory--log-dirLOG_DIRlogs

All ports are fully configurable. When using Docker Compose, changing a port requires updating both the environment variable and the ports: mapping. They must match. For example, to run the voice relay on port 5000:

environment:
- VOICE_PORT=5000ports:
- "5000:5000/udp"# was 4077:4077/udp

This applies to PORT, VOICE_PORT, and VIDEO_PORT. The internal PORT value is particularly useful if another service already occupies 4076. Note that for reverse proxy setups, the internal PORT is invisible to clients. Only the proxy's public-facing port matters to them.

CLI example:

./gc-server --port 8443 --admin myname --password mysecret --no-tls

Administration

Roles and Permissions

GoodComms uses a hierarchical role system. Roles with a higher Hierarchy number have authority over lower ones.

Default roles:

  • Owner (Hierarchy 101): Bypasses all permission checks.
  • Administrator (Hierarchy 100): Broad administrative access.
  • Default (Hierarchy 10): Base role for all new members.

Permissions span channel-level controls (view, send, voice, manage messages, manage users, webhooks) and server-wide controls (manage channels, manage roles, drive read/write/manage). See GETTING_STARTED.md for a moderator role walkthrough.

Security Hardening

  • Bootstrapping: No default passwords. Owner credentials must be set explicitly and removed after first login.
  • Revocation: JWT sessions are invalidated immediately on logout or credential change.
  • Privacy: All media, avatars, and drive files require a valid authentication token. No public routes.
  • Hardening: Rate limiting, SSRF protection for link previews, and parameterized queries throughout.

Known Limitations

All Platforms

  • Screen sharing: Starting a second stream in the same app session may not be visible to viewers. Restart the client before streaming again if this occurs.
  • Privacy Settings: A channel cannot be switched between Public and Private after it is created. If you need to change a channel's privacy, please delete it and create a new one.

Linux

  • Screen sharing: System audio loopback is not supported.
  • Audio: Per-user volume sliders can only lower volume, not boost.

Technical Specifications

  • Clients: Native Windows and Linux binaries (Rust). Chat UI: tiny-skia (CPU). Video pipeline: Direct3D 11 + Windows Graphics Capture + MFT H.264 (GPU, Windows); PipeWire + OpenH264 (software, Linux).
  • Server: Single Rust binary. Axum HTTP/WebSocket + UDP relay. SQLite via sqlx. Pure packet relay with zero media processing server-side.
  • Video: Simulcast SFU with FEC parity recovery for single-fragment packet loss. Quality tiers: Source / 1080p / 720p.
  • Audio: Opus codec. Jitter buffer, noise suppression (nnnoiseless), AGC, and push-to-talk.
  • Protocol: V5 binary header (20 bytes) for low-latency media relay.

Further Reading


Getting Help

Found a bug or have a question? Open an issue: github.com/GoodComms/goodcomms/issues


GoodComms v0.9.99 — Engineered for Privacy. Built with Rust.

About

A high-performance, self-hosted communication suite built in Rust. Features a native native media pipeline, zero-Electron architecture, and sovereign data control for chat, voice, and screen sharing.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

GoodComms v0.9.99

A self-hosted communication platform for communities that value privacy and control. Chat, voice, and screen sharing using native Rust clients, a lightweight server, and your data on hardware you own.


Why GoodComms?

Most communication platforms, even those that offer "self-hosting," still tie you to a centralized account system, ship as Electron web apps, or collect data somewhere in the pipeline. GoodComms does not.

  • No cloud accounts. You register on the server you connect to. That is the only place your account exists. No global GoodComms account, no OAuth, and no third-party identity provider.
  • No telemetry. No analytics, no tracking, and no external calls. The only optional network dependency is GIF search, which is controlled entirely by the server owner.
  • Pure native clients. Windows and Linux binaries compiled from Rust. No browser engine, no Electron, and no runtime. Download and run. This is the same model as old-school TeamSpeak, before everything moved to the cloud.
  • No surveillance logging. Server logs contain no IP addresses or account identifiers. Privacy by design.
  • Lightweight server. The server authenticates sessions, stores messages in SQLite, and routes media packets without ever processing or decoding them. CPU and RAM requirements are minimal; bandwidth and storage are the real scaling factors.

If you have a friend or community member willing to run a server, all your communication stays between you and them, not a corporation in the middle.


Key Features

  • Native Performance: Chat UI renders on the CPU (tiny-skia). Video pipeline runs on the GPU. Neither interferes with the other.
  • GPU-Accelerated Screen Sharing (Windows): Windows Graphics Capture + D3D11 + MFT H.264. Auto-detects NVIDIA, Intel, or AMD hardware. Software fallback on Linux via PipeWire.
  • Crystal Clear Voice: Opus audio with noise suppression, AGC, push-to-talk, per-user volume, and deafen support.
  • Role-Based Access Control: Hierarchical role system with channel-level and server-wide permissions. Private channels with explicit access control.
  • Server Drive: Built-in private file storage running on your own hardware with no third-party cloud.
  • Webhooks & Slash Commands: Push messages from external services into channels, or trigger external endpoints from chat commands.

For Users — Get Connected

Step 1: Download and Install

  • Windows (Recommended): Run gc-client_0.9.99_x64-setup.exe. Installs with a desktop shortcut. To update, run the new installer.
  • Windows (Portable): Run gc-client.exe directly. Create a data/ folder next to the .exe to enable Portable Mode. All settings, logs, and cache stay in that folder.
  • Linux: Portable binary. Requires PipeWire and xdg-desktop-portal for screen sharing.

Step 2: Add a Server and Log In

  1. Launch the app and click the + icon in the sidebar. Enter the address your admin gave you (e.g. chat.example.com or an IP address) and click Connect.
  2. Create a new account or log in with existing credentials. Accounts are local to each server as there is no global GoodComms account.
  3. Enable Save Password to get a one-click quick-join button on your next launch.

Step 3: Voice Channels

Voice-enabled channels show a Join Voice button. Once in voice, right-click any user for per-user volume controls. Your own mic mute and deafen are at the top of the app.

Step 4: Screen Sharing

Click Go Live in the bottom left and choose a window or display. Your stream attaches to the channel you had open. To watch someone else's stream, open their channel and click Watch next to their name.

Chat Formatting

FormatSyntax
Bold**text**
Italic*text*
Strikethrough~~text~~
Inline code`code`
Code block```code```
Slash commands/me, /shrug, /tableflip, /unflip

For Server Owners

Quick Start — Recommended Setup (Reverse Proxy)

The recommended production setup uses a reverse proxy to handle TLS. GoodComms listens on port 4076; your proxy (Caddy, Nginx, Traefik) forwards HTTPS traffic to it.

How your proxy reaches GoodComms depends on where your proxy runs:

Option A — Proxy on the host (Caddy installed directly on the server)

Expose port 4076 to the host's loopback interface. No shared Docker network needed. GoodComms is self-contained and your proxy hits it via localhost.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppedports:
- "127.0.0.1:4076:4076"# TCP — host-only, your proxy connects here
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logs
# Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:4076
}

Proxy on a different LAN machine? Replace 127.0.0.1:4076:4076 with 4076:4076 to bind to all interfaces, then point your proxy at this server's LAN IP (e.g. reverse_proxy 192.168.1.50:4076). Ensure your firewall blocks port 4076 from the internet as it is plain HTTP.

Option B — Proxy in Docker (Caddy running as a container)

Add both containers to the same Docker network. Caddy reaches GoodComms by container name. No port needs to be exposed to the host at all.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppednetworks:
- proxy-network # Must match the network your Caddy container is onports:
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logsnetworks:
proxy-network:
external: true # Your existing Caddy network
# Caddyfile
chat.yourdomain.com {
reverse_proxy gc-server:4076 # Container name resolves on the shared network
}

For standalone (no domain / LAN) and manual TLS setups, see Deployment Scenarios.

First-Time Setup (Owner Bootstrap)

  1. Uncomment ADMIN_USER and ADMIN_PASS in your compose file and set your credentials before first launch.
  2. Start the server: docker compose up -d
  3. Connect with the client and log in to claim Owner status.
  4. Security: Stop the server (docker compose down), remove the ADMIN_USER and ADMIN_PASS lines, then restart (docker compose up -d). Your account is now in the database. Credentials in a config file are a security risk.

Firewall: UDP ports 4077 and 4078 must be open. TCP is handled by your proxy. Without the UDP ports, voice and video will not work.

Configuration Reference

All options can be set via CLI flag or environment variable. Environment variables take precedence.

FeatureCLI FlagEnv VariableDefault
Bind IP-i, --ipIP_ADDR127.0.0.1
Main Port (TCP)-p, --portPORT443
HTTP Port--http-portHTTP_PORT80
Admin User-a, --adminADMIN_USER(first run only)
Admin Password-w, --passwordADMIN_PASS(first run only)
Voice Port (UDP)-v, --voice-portVOICE_PORT4077
Video Port (UDP)--video-portVIDEO_PORT4078
Database Path--db-pathDATABASE_PATHgoodcomms.db
File Upload DirSTORAGE_DIRuploads
Server Drive DirDRIVE_DIRdrive
Message RetentionRETENTION_DAYS0(disabled)
TLS CertificateTLS_CERT_PATH(auto self-signed)
TLS Private KeyTLS_KEY_PATH(auto self-signed)
Disable TLS--no-tlsNO_TLSfalse
Log Directory--log-dirLOG_DIRlogs

All ports are fully configurable. When using Docker Compose, changing a port requires updating both the environment variable and the ports: mapping. They must match. For example, to run the voice relay on port 5000:

environment:
- VOICE_PORT=5000ports:
- "5000:5000/udp"# was 4077:4077/udp

This applies to PORT, VOICE_PORT, and VIDEO_PORT. The internal PORT value is particularly useful if another service already occupies 4076. Note that for reverse proxy setups, the internal PORT is invisible to clients. Only the proxy's public-facing port matters to them.

CLI example:

./gc-server --port 8443 --admin myname --password mysecret --no-tls

Administration

Roles and Permissions

GoodComms uses a hierarchical role system. Roles with a higher Hierarchy number have authority over lower ones.

Default roles:

  • Owner (Hierarchy 101): Bypasses all permission checks.
  • Administrator (Hierarchy 100): Broad administrative access.
  • Default (Hierarchy 10): Base role for all new members.

Permissions span channel-level controls (view, send, voice, manage messages, manage users, webhooks) and server-wide controls (manage channels, manage roles, drive read/write/manage). See GETTING_STARTED.md for a moderator role walkthrough.

Security Hardening

  • Bootstrapping: No default passwords. Owner credentials must be set explicitly and removed after first login.
  • Revocation: JWT sessions are invalidated immediately on logout or credential change.
  • Privacy: All media, avatars, and drive files require a valid authentication token. No public routes.
  • Hardening: Rate limiting, SSRF protection for link previews, and parameterized queries throughout.

Known Limitations

All Platforms

  • Screen sharing: Starting a second stream in the same app session may not be visible to viewers. Restart the client before streaming again if this occurs.
  • Privacy Settings: A channel cannot be switched between Public and Private after it is created. If you need to change a channel's privacy, please delete it and create a new one.

Linux

  • Screen sharing: System audio loopback is not supported.
  • Audio: Per-user volume sliders can only lower volume, not boost.

Technical Specifications

  • Clients: Native Windows and Linux binaries (Rust). Chat UI: tiny-skia (CPU). Video pipeline: Direct3D 11 + Windows Graphics Capture + MFT H.264 (GPU, Windows); PipeWire + OpenH264 (software, Linux).
  • Server: Single Rust binary. Axum HTTP/WebSocket + UDP relay. SQLite via sqlx. Pure packet relay with zero media processing server-side.
  • Video: Simulcast SFU with FEC parity recovery for single-fragment packet loss. Quality tiers: Source / 1080p / 720p.
  • Audio: Opus codec. Jitter buffer, noise suppression (nnnoiseless), AGC, and push-to-talk.
  • Protocol: V5 binary header (20 bytes) for low-latency media relay.

Further Reading


Getting Help

Found a bug or have a question? Open an issue: github.com/GoodComms/goodcomms/issues


GoodComms v0.9.99 — Engineered for Privacy. Built with Rust.

About

A high-performance, self-hosted communication suite built in Rust. Features a native native media pipeline, zero-Electron architecture, and sovereign data control for chat, voice, and screen sharing.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

GoodComms v0.9.99

A self-hosted communication platform for communities that value privacy and control. Chat, voice, and screen sharing using native Rust clients, a lightweight server, and your data on hardware you own.


Why GoodComms?

Most communication platforms, even those that offer "self-hosting," still tie you to a centralized account system, ship as Electron web apps, or collect data somewhere in the pipeline. GoodComms does not.

  • No cloud accounts. You register on the server you connect to. That is the only place your account exists. No global GoodComms account, no OAuth, and no third-party identity provider.
  • No telemetry. No analytics, no tracking, and no external calls. The only optional network dependency is GIF search, which is controlled entirely by the server owner.
  • Pure native clients. Windows and Linux binaries compiled from Rust. No browser engine, no Electron, and no runtime. Download and run. This is the same model as old-school TeamSpeak, before everything moved to the cloud.
  • No surveillance logging. Server logs contain no IP addresses or account identifiers. Privacy by design.
  • Lightweight server. The server authenticates sessions, stores messages in SQLite, and routes media packets without ever processing or decoding them. CPU and RAM requirements are minimal; bandwidth and storage are the real scaling factors.

If you have a friend or community member willing to run a server, all your communication stays between you and them, not a corporation in the middle.


Key Features

  • Native Performance: Chat UI renders on the CPU (tiny-skia). Video pipeline runs on the GPU. Neither interferes with the other.
  • GPU-Accelerated Screen Sharing (Windows): Windows Graphics Capture + D3D11 + MFT H.264. Auto-detects NVIDIA, Intel, or AMD hardware. Software fallback on Linux via PipeWire.
  • Crystal Clear Voice: Opus audio with noise suppression, AGC, push-to-talk, per-user volume, and deafen support.
  • Role-Based Access Control: Hierarchical role system with channel-level and server-wide permissions. Private channels with explicit access control.
  • Server Drive: Built-in private file storage running on your own hardware with no third-party cloud.
  • Webhooks & Slash Commands: Push messages from external services into channels, or trigger external endpoints from chat commands.

For Users — Get Connected

Step 1: Download and Install

  • Windows (Recommended): Run gc-client_0.9.99_x64-setup.exe. Installs with a desktop shortcut. To update, run the new installer.
  • Windows (Portable): Run gc-client.exe directly. Create a data/ folder next to the .exe to enable Portable Mode. All settings, logs, and cache stay in that folder.
  • Linux: Portable binary. Requires PipeWire and xdg-desktop-portal for screen sharing.

Step 2: Add a Server and Log In

  1. Launch the app and click the + icon in the sidebar. Enter the address your admin gave you (e.g. chat.example.com or an IP address) and click Connect.
  2. Create a new account or log in with existing credentials. Accounts are local to each server as there is no global GoodComms account.
  3. Enable Save Password to get a one-click quick-join button on your next launch.

Step 3: Voice Channels

Voice-enabled channels show a Join Voice button. Once in voice, right-click any user for per-user volume controls. Your own mic mute and deafen are at the top of the app.

Step 4: Screen Sharing

Click Go Live in the bottom left and choose a window or display. Your stream attaches to the channel you had open. To watch someone else's stream, open their channel and click Watch next to their name.

Chat Formatting

FormatSyntax
Bold**text**
Italic*text*
Strikethrough~~text~~
Inline code`code`
Code block```code```
Slash commands/me, /shrug, /tableflip, /unflip

For Server Owners

Quick Start — Recommended Setup (Reverse Proxy)

The recommended production setup uses a reverse proxy to handle TLS. GoodComms listens on port 4076; your proxy (Caddy, Nginx, Traefik) forwards HTTPS traffic to it.

How your proxy reaches GoodComms depends on where your proxy runs:

Option A — Proxy on the host (Caddy installed directly on the server)

Expose port 4076 to the host's loopback interface. No shared Docker network needed. GoodComms is self-contained and your proxy hits it via localhost.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppedports:
- "127.0.0.1:4076:4076"# TCP — host-only, your proxy connects here
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logs
# Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:4076
}

Proxy on a different LAN machine? Replace 127.0.0.1:4076:4076 with 4076:4076 to bind to all interfaces, then point your proxy at this server's LAN IP (e.g. reverse_proxy 192.168.1.50:4076). Ensure your firewall blocks port 4076 from the internet as it is plain HTTP.

Option B — Proxy in Docker (Caddy running as a container)

Add both containers to the same Docker network. Caddy reaches GoodComms by container name. No port needs to be exposed to the host at all.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppednetworks:
- proxy-network # Must match the network your Caddy container is onports:
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logsnetworks:
proxy-network:
external: true # Your existing Caddy network
# Caddyfile
chat.yourdomain.com {
reverse_proxy gc-server:4076 # Container name resolves on the shared network
}

For standalone (no domain / LAN) and manual TLS setups, see Deployment Scenarios.

First-Time Setup (Owner Bootstrap)

  1. Uncomment ADMIN_USER and ADMIN_PASS in your compose file and set your credentials before first launch.
  2. Start the server: docker compose up -d
  3. Connect with the client and log in to claim Owner status.
  4. Security: Stop the server (docker compose down), remove the ADMIN_USER and ADMIN_PASS lines, then restart (docker compose up -d). Your account is now in the database. Credentials in a config file are a security risk.

Firewall: UDP ports 4077 and 4078 must be open. TCP is handled by your proxy. Without the UDP ports, voice and video will not work.

Configuration Reference

All options can be set via CLI flag or environment variable. Environment variables take precedence.

FeatureCLI FlagEnv VariableDefault
Bind IP-i, --ipIP_ADDR127.0.0.1
Main Port (TCP)-p, --portPORT443
HTTP Port--http-portHTTP_PORT80
Admin User-a, --adminADMIN_USER(first run only)
Admin Password-w, --passwordADMIN_PASS(first run only)
Voice Port (UDP)-v, --voice-portVOICE_PORT4077
Video Port (UDP)--video-portVIDEO_PORT4078
Database Path--db-pathDATABASE_PATHgoodcomms.db
File Upload DirSTORAGE_DIRuploads
Server Drive DirDRIVE_DIRdrive
Message RetentionRETENTION_DAYS0(disabled)
TLS CertificateTLS_CERT_PATH(auto self-signed)
TLS Private KeyTLS_KEY_PATH(auto self-signed)
Disable TLS--no-tlsNO_TLSfalse
Log Directory--log-dirLOG_DIRlogs

All ports are fully configurable. When using Docker Compose, changing a port requires updating both the environment variable and the ports: mapping. They must match. For example, to run the voice relay on port 5000:

environment:
- VOICE_PORT=5000ports:
- "5000:5000/udp"# was 4077:4077/udp

This applies to PORT, VOICE_PORT, and VIDEO_PORT. The internal PORT value is particularly useful if another service already occupies 4076. Note that for reverse proxy setups, the internal PORT is invisible to clients. Only the proxy's public-facing port matters to them.

CLI example:

./gc-server --port 8443 --admin myname --password mysecret --no-tls

Administration

Roles and Permissions

GoodComms uses a hierarchical role system. Roles with a higher Hierarchy number have authority over lower ones.

Default roles:

  • Owner (Hierarchy 101): Bypasses all permission checks.
  • Administrator (Hierarchy 100): Broad administrative access.
  • Default (Hierarchy 10): Base role for all new members.

Permissions span channel-level controls (view, send, voice, manage messages, manage users, webhooks) and server-wide controls (manage channels, manage roles, drive read/write/manage). See GETTING_STARTED.md for a moderator role walkthrough.

Security Hardening

  • Bootstrapping: No default passwords. Owner credentials must be set explicitly and removed after first login.
  • Revocation: JWT sessions are invalidated immediately on logout or credential change.
  • Privacy: All media, avatars, and drive files require a valid authentication token. No public routes.
  • Hardening: Rate limiting, SSRF protection for link previews, and parameterized queries throughout.

Known Limitations

All Platforms

  • Screen sharing: Starting a second stream in the same app session may not be visible to viewers. Restart the client before streaming again if this occurs.
  • Privacy Settings: A channel cannot be switched between Public and Private after it is created. If you need to change a channel's privacy, please delete it and create a new one.

Linux

  • Screen sharing: System audio loopback is not supported.
  • Audio: Per-user volume sliders can only lower volume, not boost.

Technical Specifications

  • Clients: Native Windows and Linux binaries (Rust). Chat UI: tiny-skia (CPU). Video pipeline: Direct3D 11 + Windows Graphics Capture + MFT H.264 (GPU, Windows); PipeWire + OpenH264 (software, Linux).
  • Server: Single Rust binary. Axum HTTP/WebSocket + UDP relay. SQLite via sqlx. Pure packet relay with zero media processing server-side.
  • Video: Simulcast SFU with FEC parity recovery for single-fragment packet loss. Quality tiers: Source / 1080p / 720p.
  • Audio: Opus codec. Jitter buffer, noise suppression (nnnoiseless), AGC, and push-to-talk.
  • Protocol: V5 binary header (20 bytes) for low-latency media relay.

Further Reading


Getting Help

Found a bug or have a question? Open an issue: github.com/GoodComms/goodcomms/issues


GoodComms v0.9.99 — Engineered for Privacy. Built with Rust.

About

A high-performance, self-hosted communication suite built in Rust. Features a native native media pipeline, zero-Electron architecture, and sovereign data control for chat, voice, and screen sharing.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

GoodComms v0.9.99

A self-hosted communication platform for communities that value privacy and control. Chat, voice, and screen sharing using native Rust clients, a lightweight server, and your data on hardware you own.


Why GoodComms?

Most communication platforms, even those that offer "self-hosting," still tie you to a centralized account system, ship as Electron web apps, or collect data somewhere in the pipeline. GoodComms does not.

  • No cloud accounts. You register on the server you connect to. That is the only place your account exists. No global GoodComms account, no OAuth, and no third-party identity provider.
  • No telemetry. No analytics, no tracking, and no external calls. The only optional network dependency is GIF search, which is controlled entirely by the server owner.
  • Pure native clients. Windows and Linux binaries compiled from Rust. No browser engine, no Electron, and no runtime. Download and run. This is the same model as old-school TeamSpeak, before everything moved to the cloud.
  • No surveillance logging. Server logs contain no IP addresses or account identifiers. Privacy by design.
  • Lightweight server. The server authenticates sessions, stores messages in SQLite, and routes media packets without ever processing or decoding them. CPU and RAM requirements are minimal; bandwidth and storage are the real scaling factors.

If you have a friend or community member willing to run a server, all your communication stays between you and them, not a corporation in the middle.


Key Features

  • Native Performance: Chat UI renders on the CPU (tiny-skia). Video pipeline runs on the GPU. Neither interferes with the other.
  • GPU-Accelerated Screen Sharing (Windows): Windows Graphics Capture + D3D11 + MFT H.264. Auto-detects NVIDIA, Intel, or AMD hardware. Software fallback on Linux via PipeWire.
  • Crystal Clear Voice: Opus audio with noise suppression, AGC, push-to-talk, per-user volume, and deafen support.
  • Role-Based Access Control: Hierarchical role system with channel-level and server-wide permissions. Private channels with explicit access control.
  • Server Drive: Built-in private file storage running on your own hardware with no third-party cloud.
  • Webhooks & Slash Commands: Push messages from external services into channels, or trigger external endpoints from chat commands.

For Users — Get Connected

Step 1: Download and Install

  • Windows (Recommended): Run gc-client_0.9.99_x64-setup.exe. Installs with a desktop shortcut. To update, run the new installer.
  • Windows (Portable): Run gc-client.exe directly. Create a data/ folder next to the .exe to enable Portable Mode. All settings, logs, and cache stay in that folder.
  • Linux: Portable binary. Requires PipeWire and xdg-desktop-portal for screen sharing.

Step 2: Add a Server and Log In

  1. Launch the app and click the + icon in the sidebar. Enter the address your admin gave you (e.g. chat.example.com or an IP address) and click Connect.
  2. Create a new account or log in with existing credentials. Accounts are local to each server as there is no global GoodComms account.
  3. Enable Save Password to get a one-click quick-join button on your next launch.

Step 3: Voice Channels

Voice-enabled channels show a Join Voice button. Once in voice, right-click any user for per-user volume controls. Your own mic mute and deafen are at the top of the app.

Step 4: Screen Sharing

Click Go Live in the bottom left and choose a window or display. Your stream attaches to the channel you had open. To watch someone else's stream, open their channel and click Watch next to their name.

Chat Formatting

FormatSyntax
Bold**text**
Italic*text*
Strikethrough~~text~~
Inline code`code`
Code block```code```
Slash commands/me, /shrug, /tableflip, /unflip

For Server Owners

Quick Start — Recommended Setup (Reverse Proxy)

The recommended production setup uses a reverse proxy to handle TLS. GoodComms listens on port 4076; your proxy (Caddy, Nginx, Traefik) forwards HTTPS traffic to it.

How your proxy reaches GoodComms depends on where your proxy runs:

Option A — Proxy on the host (Caddy installed directly on the server)

Expose port 4076 to the host's loopback interface. No shared Docker network needed. GoodComms is self-contained and your proxy hits it via localhost.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppedports:
- "127.0.0.1:4076:4076"# TCP — host-only, your proxy connects here
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logs
# Caddyfile
chat.yourdomain.com {
reverse_proxy localhost:4076
}

Proxy on a different LAN machine? Replace 127.0.0.1:4076:4076 with 4076:4076 to bind to all interfaces, then point your proxy at this server's LAN IP (e.g. reverse_proxy 192.168.1.50:4076). Ensure your firewall blocks port 4076 from the internet as it is plain HTTP.

Option B — Proxy in Docker (Caddy running as a container)

Add both containers to the same Docker network. Caddy reaches GoodComms by container name. No port needs to be exposed to the host at all.

services:
goodcomms-server:
image: goodcomms/gc-server:latestcontainer_name: gc-serverrestart: unless-stoppednetworks:
- proxy-network # Must match the network your Caddy container is onports:
- "4077:4077/udp"# Voice (Opus)
- "4078:4078/udp"# Video (H.264)environment:
- IP_ADDR=0.0.0.0
- PORT=4076
- NO_TLS=true
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive# First run only — remove after logging in:# - ADMIN_USER=your_username# - ADMIN_PASS=your_secure_password
- LOG_DIR=/app/logsvolumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./logs:/app/logsnetworks:
proxy-network:
external: true # Your existing Caddy network
# Caddyfile
chat.yourdomain.com {
reverse_proxy gc-server:4076 # Container name resolves on the shared network
}

For standalone (no domain / LAN) and manual TLS setups, see Deployment Scenarios.

First-Time Setup (Owner Bootstrap)

  1. Uncomment ADMIN_USER and ADMIN_PASS in your compose file and set your credentials before first launch.
  2. Start the server: docker compose up -d
  3. Connect with the client and log in to claim Owner status.
  4. Security: Stop the server (docker compose down), remove the ADMIN_USER and ADMIN_PASS lines, then restart (docker compose up -d). Your account is now in the database. Credentials in a config file are a security risk.

Firewall: UDP ports 4077 and 4078 must be open. TCP is handled by your proxy. Without the UDP ports, voice and video will not work.

Configuration Reference

All options can be set via CLI flag or environment variable. Environment variables take precedence.

FeatureCLI FlagEnv VariableDefault
Bind IP-i, --ipIP_ADDR127.0.0.1
Main Port (TCP)-p, --portPORT443
HTTP Port--http-portHTTP_PORT80
Admin User-a, --adminADMIN_USER(first run only)
Admin Password-w, --passwordADMIN_PASS(first run only)
Voice Port (UDP)-v, --voice-portVOICE_PORT4077
Video Port (UDP)--video-portVIDEO_PORT4078
Database Path--db-pathDATABASE_PATHgoodcomms.db
File Upload DirSTORAGE_DIRuploads
Server Drive DirDRIVE_DIRdrive
Message RetentionRETENTION_DAYS0(disabled)
TLS CertificateTLS_CERT_PATH(auto self-signed)
TLS Private KeyTLS_KEY_PATH(auto self-signed)
Disable TLS--no-tlsNO_TLSfalse
Log Directory--log-dirLOG_DIRlogs

All ports are fully configurable. When using Docker Compose, changing a port requires updating both the environment variable and the ports: mapping. They must match. For example, to run the voice relay on port 5000:

environment:
- VOICE_PORT=5000ports:
- "5000:5000/udp"# was 4077:4077/udp

This applies to PORT, VOICE_PORT, and VIDEO_PORT. The internal PORT value is particularly useful if another service already occupies 4076. Note that for reverse proxy setups, the internal PORT is invisible to clients. Only the proxy's public-facing port matters to them.

CLI example:

./gc-server --port 8443 --admin myname --password mysecret --no-tls

Administration

Roles and Permissions

GoodComms uses a hierarchical role system. Roles with a higher Hierarchy number have authority over lower ones.

Default roles:

  • Owner (Hierarchy 101): Bypasses all permission checks.
  • Administrator (Hierarchy 100): Broad administrative access.
  • Default (Hierarchy 10): Base role for all new members.

Permissions span channel-level controls (view, send, voice, manage messages, manage users, webhooks) and server-wide controls (manage channels, manage roles, drive read/write/manage). See GETTING_STARTED.md for a moderator role walkthrough.

Security Hardening

  • Bootstrapping: No default passwords. Owner credentials must be set explicitly and removed after first login.
  • Revocation: JWT sessions are invalidated immediately on logout or credential change.
  • Privacy: All media, avatars, and drive files require a valid authentication token. No public routes.
  • Hardening: Rate limiting, SSRF protection for link previews, and parameterized queries throughout.

Known Limitations

All Platforms

  • Screen sharing: Starting a second stream in the same app session may not be visible to viewers. Restart the client before streaming again if this occurs.
  • Privacy Settings: A channel cannot be switched between Public and Private after it is created. If you need to change a channel's privacy, please delete it and create a new one.

Linux

  • Screen sharing: System audio loopback is not supported.
  • Audio: Per-user volume sliders can only lower volume, not boost.

Technical Specifications

  • Clients: Native Windows and Linux binaries (Rust). Chat UI: tiny-skia (CPU). Video pipeline: Direct3D 11 + Windows Graphics Capture + MFT H.264 (GPU, Windows); PipeWire + OpenH264 (software, Linux).
  • Server: Single Rust binary. Axum HTTP/WebSocket + UDP relay. SQLite via sqlx. Pure packet relay with zero media processing server-side.
  • Video: Simulcast SFU with FEC parity recovery for single-fragment packet loss. Quality tiers: Source / 1080p / 720p.
  • Audio: Opus codec. Jitter buffer, noise suppression (nnnoiseless), AGC, and push-to-talk.
  • Protocol: V5 binary header (20 bytes) for low-latency media relay.

Further Reading


Getting Help

Found a bug or have a question? Open an issue: github.com/GoodComms/goodcomms/issues


GoodComms v0.9.99 — Engineered for Privacy. Built with Rust.

About

A high-performance, self-hosted communication suite built in Rust. Features a native native media pipeline, zero-Electron architecture, and sovereign data control for chat, voice, and screen sharing.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Contributors