gmmff

module
v1.3.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 21, 2026 License: MIT

README

A view from space of a giant worm hole sucking in your favorite file types... oh the horror!

gmmff — peer-to-peer file transfer

gmmff (pronounced gimph) is a brutally simple, cryptographically sound peer-to-peer file and message transfer system.

gmmff consists of two parts: a signaling server that brokers the initial connection, and a CLI client that handles the actual transfer. The server never sees file contents — once two (or more) peers are connected, all data flows directly between them over an encrypted WebRTC data channel.


Architecture overview

Peer A ──┐                          ┌── Peer B
         │  wss://host/ws           │
         └──── Signaling server ────┘
                    │
               Redis (slot state)
  1. Peer A runs gmmff create and receives a one-time 3-word code
  2. Peer A shares that code out-of-band with Peer B
  3. Peer B runs gmmff join <code> on any machine, anywhere
  4. CPace PAKE authenticates both sides — the signaling server stays blind
  5. The SDP offer/answer is HMAC-signed with the PAKE shared key, preventing man-in-the-middle substitution
  6. A direct WebRTC/DTLS control channel opens; the signaling server's job is done
  7. Both peers enter the session REPL and can freely exchange files and messages
Phase What the server does
slot.create Generates a UUID + 3-word code, persists in Redis with 10-min TTL
slot.join Resolves code → slot, links the responder, sends slot.ready to both
Relay Forwards pake.*, sdp.*, ice.* frames opaquely to the other peer
bye / expire Deletes both Redis keys; notifies peer

The server cannot intercept the session. PAKE authentication happens entirely between the two clients, and the DTLS session key is bound to the PAKE shared secret via HMAC — so a compromised signaling server cannot substitute its own SDP fingerprints.

If you want to learn more, see the dedicated Architecture document.


Application overview

Installing

Please use the guide here for installing gmmff.

Building

Please use the guide here for building gmmff.

CLI

CLI Guide

WASM Webclient

WASM Guide

Local-network mode (no internet required)

Local mode Guide

Starting a pure chat session (CLI)

For a text-only session without file transfer, use gmmff chat:

# Machine A
gmmff chat --server wss://your-server/ws

# Machine B — gmmff join detects the session type and routes to the chat REPL
gmmff join river-stone-fog --server wss://your-server/ws

Commands

See the Commands Guide


Environment variables

See the Commands Guide and the env example


STUN/TURN configuration

See the STUN/TURN Guide


Quick Start

Option A — Docker Compose
git clone https://github.com/iamdoubz/gmmff
cd gmmff
cp configs/.env.example configs/.env
docker compose up -d
# Server available at ws://localhost:8080/ws
Option B — Local Go + Redis

Prerequisites: Go 1.23+, Redis 7+

# Start Redis
redis-server

# Run with in-memory store (no Redis needed for dev)
go run ./cmd/gmmff serve --memory --log-pretty --log-level debug

# Or with Redis
go run ./cmd/gmmff serve --log-pretty --log-level debug
Verify
curl http://localhost:8080/healthz   # → ok
curl http://localhost:8080/readyz    # → ok (or 503 if Redis is down)
curl http://localhost:8080/metrics   # → JSON counters

Server configuration

All flags have environment variable equivalents with the GMMFF_ prefix. Copy configs/.env.example to .env and adjust.

Flag Env var Default Description
--addr GMMFF_ADDR :8080 Listen address
--redis-url GMMFF_REDIS_URL redis://localhost:6379/0 Redis URL
--memory false Use in-memory store (dev only)
--log-level GMMFF_LOG_LEVEL info trace|debug|info|warn|error
--log-pretty false Human-readable logs
--slot-ttl 10m Slot expiry duration
--tls-cert GMMFF_TLS_CERT TLS certificate path
--tls-key GMMFF_TLS_KEY TLS private key path
--web GMMFF_WEB_DIR Path to web/static/ — serves browser UI at / alongside signaling
--csp-report-only false Use CSP-Report-Only header for debugging — NOT for production

Production TLS: use a reverse proxy (Caddy, nginx, AWS ALB). The server speaks plain HTTP internally; the proxy handles TLS termination and forwards wss:// connections.


Browser UI (Wasm)

The same Go code that powers the CLI compiles to WebAssembly and runs directly in the browser — one codebase, two delivery targets.


Theming

Copy web/static/themes/default.json, edit the values, and point the THEME_URL constant at the top of app.js at your new file. Every CSS custom property is overridable — colors, spacing, radii, fonts, max-width — with no build step required.


Translations

The UI ships with 32 languages including English, Spanish, French, German, Italian, Swedish, Portuguese, Arabic, Bengali, Persian, Finnish, Hindi, Indonesian, Japanese, Korean, Marathi, Malay, Dutch, Norwegian, Polish, Russian, Thai, Filipino, Turkish, Ukrainian, Urdu, Vietnamese, Chinese (Simplified and Traditional), Tamil, and Sinhala. The language picker in the footer auto-detects your browser preference and persists your choice for 7 days.

To add a language: copy web/static/i18n/en.json, translate the values, save as web/static/i18n/<code>.json, and add an entry to web/static/i18n/languages.json. No build step required.


ICE settings

A collapsible ICE servers panel sits below the tab bar, shared across all tabs. STUN servers you add are appended to the default. TURN servers use the same Option A format as the CLI (turn:host:port?transport=udp&secret=s). Settings persist in localStorage for 7 days.


Deployment

For production deployments, see the dedicated guides in the docs/ directory:

  • docs/SYSTEMD.md — Creating a dedicated system user, installing the binary and service file, managing configuration without editing the service file, and Redis Unix socket access.
  • docs/NGINX.md — Configuring nginx as a reverse proxy with TLS termination, WebSocket upgrade headers, timeout tuning, and endpoint access control.

Security model

See Security Documentation for more information.


Wire protocol

See Protocol Documentation for more information.


Privacy & logging

Logs contain only:

  • Timestamp
  • Component name (broker, store, main)
  • Slot UUID (opaque — means nothing to outsiders)
  • Error code (e.g. ERR_REDIS_UNAVAILABLE)
  • HTTP method + path + status code

Logs never contain: file names, file sizes, IP addresses, user agents, slot codes, or any data that could identify a transfer or a user.


Project structure

gmmff/
├── cmd/gmmff/              # Binary entrypoint (Cobra CLI)
│   ├── main.go             # Root command + serve subcommand + shared helpers
│   ├── create.go           # gmmff create — starts file+message session, session REPL
│   ├── chat.go             # gmmff chat — pure chat; gmmff join — joins any session
│   └── local.go            # gmmff local — self-contained local-network mode
├── internal/
│   ├── broker/             # WebSocket hub, message router, HTTP server
│   │   ├── broker.go
│   │   └── server.go
│   ├── store/              # Redis + in-memory slot persistence
│   │   └── store.go
│   ├── slot/               # Slot domain model & state machine
│   │   └── slot.go
│   ├── crypto/             # Slot code generation (3-word passphrase)
│   │   └── codegen.go
│   ├── log/                # Privacy-safe structured logger
│   │   └── log.go
│   ├── archive/            # On-the-fly zip for multi-file transfers
│   │   └── archive.go
│   ├── chat/               # Pure text chat session (CLI REPL + idle timer)
│   │   └── session.go
│   ├── pake/               # HKDF subkey derivation + SDP MAC signing
│   │   └── session.go
│   ├── peer/               # WebRTC + PAKE orchestration; StartSession/JoinSession
│   │   └── peer.go
│   ├── peerconfig/         # Shared Config type (avoids peer↔session import cycle)
│   │   └── peerconfig.go
│   ├── session/            # Bidirectional session coordinator (Option B architecture)
│   │   └── session.go
│   ├── signaling/          # WebSocket signaling client
│   │   ├── client_native.go  # gorilla/websocket (CLI)
│   │   ├── client_js.go      # browser native WebSocket (Wasm)
│   │   └── b64.go
│   ├── transfer/           # Binary chunk protocol (send + receive state machines)
│   │   └── transfer.go
│   ├── localmode/          # Self-contained local-network mode
│   │   ├── embed.go        # //go:embed of web/static (built by make build)
│   │   ├── tls.go          # Self-signed cert generation
│   │   ├── mdns.go         # mDNS registration and peer discovery
│   │   └── local.go        # Orchestrator: broker + web server + session REPL
│   └── turn/               # TURN URL parsing and ephemeral credential derivation
│       └── turn.go
├── pkg/protocol/           # Wire message types (shared server/client)
│   └── protocol.go
├── web/                    # browser UI (Wasm)
│   ├── cmd/gmmff-wasm/     # Go→Wasm entry point (syscall/js bridge)
│   │   └── main.go
│   ├── static/             # served files
│   │   ├── index.html      # mobile-first single-page UI (Files + Chat tabs)
│   │   ├── css/
│   │   │   └── app.css     # all styles (no inline CSS)
│   │   ├── js/
│   │   │   └── app.js      # all UI logic (no inline JS)
│   │   ├── themes/
│   │   │   └── default.json
│   │   └── i18n/
│   │       ├── languages.json
│   │       ├── en.json
│   │       └── ...         # es, fr, de, it, sv, pt-BR, pt-PT, ta, si
│   └── server.go           # dev-only static file server
├── configs/
│   ├── .env.example        # environment variable reference
│   ├── gmmff.conf          # nginx reverse proxy configuration
│   └── gmmff.service       # systemd service unit
├── docs/
│   ├── ARCHITECTURE.md     # signaling server architecture deep-dive
│   ├── BUILD.md            # how to build gmmff from source
│   ├── CLI.md              # cli usage and examples
│   ├── CMDS.md             # all flags and env variables used here
│   ├── INSTALL.md          # installation guide (generic)
│   ├── LOCAL.md            # gmmff local usage document
│   ├── NGINX.md            # nginx reverse proxy setup guide
│   ├── PROTOCOL.md         # wire protocol
│   ├── SECURITY.md         # shows and explains each step used to secure communications
│   ├── SYSTEMD.md          # dedicated system user + systemd setup guide
│   ├── TURN.md             # flags to use STUN and TURN servers with gmmff
│   └── WASM.md             # how to use the wasm webclient
├── Dockerfile
├── docker-compose.yml
├── go.mod
├── go.sum
└── README.md

Features

Current
  • Local-network modegmmff local is a fully self-contained mode with embedded server, auto TLS, mDNS discovery, and QR code; no internet or external server required
  • Multi-peer sessionsgmmff create --max-peers N allows 2–10 participants; 2-peer sessions are bidirectional, 3–10 peer sessions broadcast from the initiator to all
  • Signaling server — Go, Redis-backed, privacy-safe structured logs, Docker-ready
  • CPace PAKE — zero-knowledge authentication; server stays blind to the shared secret
  • SDP MAC binding — HMAC-signed SDP with HKDF-derived subkeys; prevents MITM via signaling relay
  • DTLS 1.3 — all data channel traffic encrypted end-to-end via Pion WebRTC
  • Multi-file and directory transfers — multiple files and directories zipped on the fly
  • Transfer queue — multiple transfers serialized automatically; each gets its own progress bar
  • Resumable transfers — partial + meta sidecar files; progress bars pick up at the correct offset
  • Clean cancellationCtrl+C or \q delivers clean messages to all peers; partial file preserved
  • SHA-256 integrity — full-file hash verified before TransferOK is sent
  • Secure chat — pure text chat (gmmff chat) or inline messaging within a file session
  • Sliding window — configurable in-flight chunks (--window); default 2
  • Configurable chunk size — up to SCTP maximum 65526 bytes (--chunk-size)
  • STUN multi-server — append additional STUN servers via --stun (repeatable) or GMMFF_STUN
  • TURN support — long-term and ephemeral credentials, mixed auth types, transport hints, max 3 servers
  • Browser UI (Wasm) — same Go source compiled to WebAssembly; Files tab + Chat tab
  • Drag and drop — drop files anywhere on the browser UI to queue them for sending
  • 32 languages — English, Spanish, French, German, Italian, Swedish, Portuguese (BR/EU), Arabic, Bengali, Persian, Finnish, Hindi, Indonesian, Japanese, Korean, Marathi, Malay, Dutch, Norwegian, Polish, Russian, Thai, Filipino, Turkish, Ukrainian, Urdu, Vietnamese, Chinese (Simplified/Traditional), Tamil, Sinhala; language picker with 7-day persistence
  • ICE settings panel — configurable STUN/TURN in the browser UI, persisted 7 days
  • Share links + QR codes — shareable URLs and scannable QR codes on all code screens
  • Display names — both initiator and joiner can set a name; names are announced to peers on connect and used as message labels throughout the session
Backlog
  • Browser extension — use your favourite browser to send/receive files
  • Docker images — pipeline to package, build, and publish Docker images
  • More languages — 32 languages shipped; contributions welcome
  • Trusted local CA — one-time CA install for iOS Safari support in gmmff local
  • Quantum-safe encryption — post-quantum algorithms with elliptic-curve fallback
Probably won't do
  • wasm webclient: window slider (defaults to 2, 1–16 range)
  • Password-protected zips — optional encryption on the zip archive

Inspiration

https://xkcd.com/949

xkcd comic explaining the difficulties of sending large files between two people


License

MIT — see LICENSE. All dependencies are MIT or Apache-2.0.

Directories

Path Synopsis
cmd
gmmff command
Command gmmff is the signaling server for the gmmff peer-to-peer file transfer system.
Command gmmff is the signaling server for the gmmff peer-to-peer file transfer system.
internal
archive
Package archive provides on-the-fly zip archiving for multi-file transfers.
Package archive provides on-the-fly zip archiving for multi-file transfers.
broker
Package broker implements the WebSocket signaling broker for gmmff.
Package broker implements the WebSocket signaling broker for gmmff.
chat
Package chat implements a symmetric bidirectional text chat session over a WebRTC data channel.
Package chat implements a symmetric bidirectional text chat session over a WebRTC data channel.
crypto
Package crypto provides gmmff cryptographic utilities:
Package crypto provides gmmff cryptographic utilities:
localmode
Package localmode provides the self-contained local-network mode for gmmff.
Package localmode provides the self-contained local-network mode for gmmff.
log
Package log provides the gmmff privacy-safe structured logger.
Package log provides the gmmff privacy-safe structured logger.
pake
Package pake provides the session key material derived from the CPace handshake and uses it to cryptographically bind the WebRTC SDP exchange to the shared secret.
Package pake provides the session key material derived from the CPace handshake and uses it to cryptographically bind the WebRTC SDP exchange to the shared secret.
peer
Package peer orchestrates the WebRTC connection lifecycle for gmmff.
Package peer orchestrates the WebRTC connection lifecycle for gmmff.
peerconfig
Package peerconfig defines the peer connection configuration type shared between the peer and session packages.
Package peerconfig defines the peer connection configuration type shared between the peer and session packages.
session
Package session implements the bidirectional file + message session introduced by gmmff create / gmmff join.
Package session implements the bidirectional file + message session introduced by gmmff create / gmmff join.
signaling
Package signaling implements the gmmff WebSocket signaling client.
Package signaling implements the gmmff WebSocket signaling client.
slot
Package slot defines the domain model for a gmmff rendezvous slot.
Package slot defines the domain model for a gmmff rendezvous slot.
store
Package store implements the Redis-backed persistence layer for gmmff slots.
Package store implements the Redis-backed persistence layer for gmmff slots.
transfer
Package transfer defines the application-level file transfer protocol that runs over a WebRTC data channel.
Package transfer defines the application-level file transfer protocol that runs over a WebRTC data channel.
turn
Package turn handles TURN server configuration for gmmff.
Package turn handles TURN server configuration for gmmff.
pkg
protocol
Package protocol defines the wire message types exchanged over the WebSocket signaling channel between gmmff peers and the signaling server.
Package protocol defines the wire message types exchanged over the WebSocket signaling channel between gmmff peers and the signaling server.
web
Command gmmff-web serves the gmmff browser UI for development.
Command gmmff-web serves the gmmff browser UI for development.
cmd/gmmff-wasm command
Command gmmff-wasm is the WebAssembly build of gmmff for browser use.
Command gmmff-wasm is the WebAssembly build of gmmff for browser use.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL