Configuration via .env file
All modes support a .env file instead of listing environment variables inline.
A fully commented template is provided above as server.env.example.
With Docker Compose, use env_file: in place of environment::
services:
goodcomms-server:
env_file: .env # reads key=value pairs from .env in the same directory
ports:
- "4077:4077/udp"
- "4078:4078/udp"
For systemd, use EnvironmentFile= in the service unit (see Mode D). For the bare binary on Linux: set -a; source .env; set +a; ./gc-server
Mode A: Reverse Proxy
RecommendedBest for: production deployments with a domain, using Caddy, Nginx, or Traefik.
- TCP 4076 — internal plaintext for the proxy to forward (not exposed publicly)
- UDP 4077 / 4078 — voice and video, exposed directly for low latency
services:
goodcomms-server:
image: goodcomms/gc-server:latest # pin a version tag for reproducible deploys
container_name: gc-server
restart: unless-stopped
networks:
- proxy-network
ports:
- "4077:4077/udp" # Voice
- "4078:4078/udp" # Video
# Note: TCP 4076 is NOT exposed; the proxy reaches it via proxy-network
environment:
- IP_ADDR=0.0.0.0
- PORT=4076 # Internal TCP port for proxy to forward to
- VOICE_PORT=4077
- VIDEO_PORT=4078
- NO_TLS=true # Proxy handles TLS - critical
- TRUST_PROXY=true # Rate limiting keys on X-Forwarded-For - required behind a proxy
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive
- RETENTION_DAYS=0
# Optional: GIF integration
# - GIPHY_API_KEY=your_key_here
# - KLIPY_API_KEY=your_key_here
# Optional: Admin bootstrap (first run only)
# - ADMIN_USER=admin
# - ADMIN_PASS=changeme
volumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
networks:
proxy-network:
external: true
Caddyfile example:
chat.yourdomain.com {
reverse_proxy gc-server:4076
}
Proxy on the host instead of in Docker? See the walkthrough on the Get Started page — it covers both wirings step by step.
Mode B: Standalone Self-Signed
Best for: LAN parties, home servers, or quick testing. No domain or proxy required.
- TCP 443 — HTTPS with auto-generated self-signed certs; TCP 80 redirects to HTTPS
- UDP 4077 / 4078 — voice and video
services:
goodcomms-server:
image: goodcomms/gc-server:latest # pin a version tag for reproducible deploys
container_name: gc-server
restart: unless-stopped
ports:
- "443:443" # HTTPS
- "80:80" # HTTP redirect
- "4077:4077/udp" # Voice
- "4078:4078/udp" # Video
environment:
- IP_ADDR=0.0.0.0
- PORT=443
- HTTP_PORT=80
- VOICE_PORT=4077
- VIDEO_PORT=4078
# NO_TLS is false by default - self-signed certs auto-generated
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive
volumes:
- ./data:/app/data # Also stores auto-generated certs
- ./uploads:/app/uploads
- ./drive:/app/drive
Client behavior: connecting via IP (e.g. https://192.168.1.50) automatically accepts self-signed certs; connecting via a domain requires a valid TLS certificate.
Mode C: Standalone Manual TLS
Best for: production with your own certificates (Let's Encrypt, Certbot, etc.) and no proxy.
services:
goodcomms-server:
image: goodcomms/gc-server:latest # pin a version tag for reproducible deploys
container_name: gc-server
restart: unless-stopped
ports:
- "443:443" # HTTPS
- "80:80" # HTTP redirect
- "4077:4077/udp" # Voice
- "4078:4078/udp" # Video
environment:
- IP_ADDR=0.0.0.0
- PORT=443
- HTTP_PORT=80
- VOICE_PORT=4077
- VIDEO_PORT=4078
- TLS_CERT_PATH=/app/certs/fullchain.pem
- TLS_KEY_PATH=/app/certs/privkey.pem
- DATABASE_PATH=/app/data/goodcomms.db
- STORAGE_DIR=/app/uploads
- DRIVE_DIR=/app/drive
volumes:
- ./data:/app/data
- ./uploads:/app/uploads
- ./drive:/app/drive
- ./certs:/app/certs:ro # Mount your cert files read-only
Mode D: Bare Binary (systemd)
Best for: servers without Docker. The binary accepts the same environment
variables and CLI flags as every mode above. Download gc-server from the
downloads page, then:
chmod +x gc-server
sudo mv gc-server /opt/goodcomms/gc-server
sudo mkdir -p /opt/goodcomms/{data,uploads,drive}
sudo useradd --system --no-create-home --shell /bin/false goodcomms
sudo chown -R goodcomms:goodcomms /opt/goodcomms
Copy server.env.example to /opt/goodcomms/.env, edit it, then create /etc/systemd/system/goodcomms.service:
[Unit]
Description=GoodComms Server
After=network.target
[Service]
Type=simple
User=goodcomms
WorkingDirectory=/opt/goodcomms
EnvironmentFile=/opt/goodcomms/.env
ExecStart=/opt/goodcomms/gc-server
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable goodcomms
sudo systemctl start goodcomms
sudo journalctl -u goodcomms -f # follow logs
To bootstrap the owner account: set ADMIN_USER / ADMIN_PASS in
.env, start, log in once with the client, then remove them and restart.
Windows can run the same way (PowerShell env vars + gc-server.exe) or as a service via
NSSM — the Docker path is the best-tested for production.
Key Ports
| Port | Protocol | Purpose |
|---|---|---|
| 443 / 4076 | TCP | WebSocket / HTTP signaling (proxied or direct) |
| 80 | TCP | HTTP to HTTPS redirect (standalone modes) |
| 4077 | UDP | Voice (Opus) — must be directly reachable, cannot be proxied |
| 4078 | UDP | Video (H.264) — must be directly reachable, cannot be proxied |
Voice and video silently fail if UDP 4077/4078 are blocked — this is the most common setup issue. Check the server firewall, cloud security groups, and router forwarding.
Environment Variables
| Variable | Default | Description |
|---|---|---|
| PORT | 443 | Main TCP port |
| NO_TLS | false | Set to true when behind a proxy |
| TRUST_PROXY | false | Rate limiting keys on the first X-Forwarded-For hop. Required behind a reverse proxy (Mode A); leave off otherwise |
| VOICE_PORT | 4077 | UDP voice port |
| VIDEO_PORT | 4078 | UDP video port |
| DATABASE_PATH | data/goodcomms.db | SQLite database |
| STORAGE_DIR | uploads | Chat file uploads |
| DRIVE_DIR | drive | Server drive files |
| RETENTION_DAYS | 0 | Auto-delete old media (0 = disabled) |
| ADMIN_USER / ADMIN_PASS | - | Bootstrap the owner account (first run only — remove afterwards) |
| GIPHY_API_KEY / KLIPY_API_KEY | - | Optional GIF search integration |
New to GoodComms? Start with the Get Started guide. Questions or issues? Open an issue on GitHub.