A resilient text-first Internet bridge for mesh radios: Update your blog from a can on a string from the smoldering rubble.
Part of the Deadlight ecosystem secure, performant, privacy-focused tools for resilient connectivity on low-bandwidth, high-latency, and intermittently connected networks.
· Project Blog · Why This Exists · Getting Started · Hardware · Dashboard · Usage · Configuration · How It Works · Real-World Use Cases · Performance · Roadmap · License
deadmesh transforms LoRa mesh networks into practical Internet gateways. Built on the proxy.deadlight foundation, it adds transparent mesh networking that lets any device on a Meshtastic mesh access standard Internet protocols HTTP/HTTPS, email, DNS, FTP, as if they had normal connectivity.
What makes this different from other mesh solutions:
- Standard protocols work unchanged: browse websites, send email, use apps
- Transparent fragmentation & reassembly over Meshtastic LoRa packets
- Full MITM proxy with caching, compression, ad-blocking, rate-limiting
- Works with off-the-shelf Meshtastic hardware
- Truly off-grid: solar-powered nodes can relay traffic across kilometers
- Real-time embedded dashboard with live mesh visibility (nodes, SNR, positions, telemetry, chat)
- Connection pooling + TLS session reuse to minimize airtime
Think of it as giving your Meshtastic network the capabilities of a satellite terminal, running on $30 hardware with zero monthly fees.
Meshtastic networks are incredible for messaging and telemetry, but they weren't designed for general Internet access. Each protocol (HTTP, SMTP, DNS) would need custom mesh-aware implementations, a chicken-and-egg problem where applications won't add mesh support without users, and users won't adopt mesh without applications.
deadmesh sits in the middle:
- Mesh side: Speaks fluent Meshtastic (protobuf over LoRa serial with proper API handshake)
- Internet side: Speaks every protocol your applications already use
- Bridges transparently: Fragments outgoing requests, reassembles incoming responses
Result: Your mesh network works with everything: email clients, web browsers, update tools, API services, without modifying a single line of application code.
- Disaster Response: Coordinate rescue operations when cell towers are down
- Rural Connectivity: Share one satellite uplink across dozens of kilometers
- Censorship Resistance: Maintain communication during Internet blackouts
- Off-Grid Networks: Festival/protest/research networks that disappear when powered off
- Development Projects: Bring Internet services to areas with zero infrastructure
- Universal Protocol Support: HTTP/HTTPS, SMTP/IMAP, SOCKS4/5, WebSocket, FTP. If it runs over TCP/IP, it works
- Transparent TLS Interception: Inspect and cache HTTPS traffic with HTTP/1.1 ALPN negotiation to minimize mesh bandwidth
- Intelligent Fragmentation: Automatically chunks large requests/responses into ~220-byte Meshtastic packets
- Serial API Handshake: Proper
want_configinitialization, auto-discovers node ID, receives full mesh state on startup - Live Mesh Visibility: Decodes all Meshtastic packet types (text messages, positions, telemetry, node info, routing)
- Store-and-Forward: Delay-tolerant networking handles intermittent mesh connectivity
- Connection Pooling: Reuses upstream connections aggressively with TLS session reuse to reduce LoRa airtime cost
- Plugin Extensibility: Ad blocking, rate limiting, compression, caching, custom protocol handlers
- Hardware Flexibility: USB serial, Bluetooth, or TCP-connected radios
- Auto-Detection: Auto-discovers Meshtastic devices on serial ports and auto-detects local node ID from device
- Embedded Dashboard: Real-time gateway monitor with SSE streaming, self-contained in the binary, no external assets
- Live Node Table: Persistent mesh node database; names, hops, SNR, battery, position, last heard, updated from every packet type
The killer feature that makes deadmesh actually pleasant to use on LoRa.
- Type
mesh://en.wikipedia.orginstead ofhttp://to get a clean, ultra-compressed, text-only version (~98% smaller). - Clear, helpful denial messages when something is impossible (e.g. “YouTube would take 47 hours and 312% of your daily duty cycle” + instant alternatives).
- Shared cache that gets smarter every day, the whole mesh becomes a living knowledge appliance.
- Volunteers can “seed” gateways with USB sticks (i.e. dead librarian society).
Full details and philosophy → SMART_MESH_ROUTING.md
(deadmesh should feel like the network is on your side.)
Software:
- Linux (Raspberry Pi, x86 server, or similar)
- GLib 2.0+, OpenSSL 1.1+, json-glib-1.0
- GCC or Clang
- Python 3 + pip (for nanopb protobuf generation during build)
Optional (for Meshtastic CLI testing):
- Python meshtastic package (
pip install meshtastic)
Hardware (see Hardware for details):
- Meshtastic-compatible LoRa radio (ESP32-based recommended)
- Gateway node: Raspberry Pi or similar with Internet connection
- Client nodes: any Meshtastic device (phone, handheld, custom)
-
Install system dependencies:
# Debian/Ubuntu/Raspberry Pi OS sudo apt-get install build-essential pkg-config libglib2.0-dev \ libssl-dev libjson-glib-dev libmicrohttpd-dev protobuf-compiler xxdVerify they're all found:
pkg-config --modversion glib-2.0 openssl json-glib-1.0 # Should print three version numbers — if any fail, the build will fail -
Set up Python environment for protobuf generation:
The nanopb generator that compiles Meshtastic protobufs requires specific Python packages. Use a venv to avoid conflicts with system Python:
python3 -m venv venv source venv/bin/activate pip install protobuf grpcio-toolsKeep this venv active for the build step. You can deactivate it after
makecompletes. -
Clone and build:
git clone https://github.com/gnarzilla/deadmesh.git cd deadmesh make clean && make UI=1 deactivate # exit venv after build
A successful build produces:
bin/deadmesh bin/plugins/adblocker.so bin/plugins/meshtastic.so bin/plugins/ratelimiter.so tools/mesh-sim -
Connect your Meshtastic radio:
# Most devices appear as /dev/ttyACM0 or /dev/ttyUSB0 ls -l /dev/ttyACM0 /dev/ttyUSB0 2>/dev/null # Add yourself to the dialout group sudo usermod -a -G dialout $USER # Log out and back in for group change to take effect
-
Generate CA certificate (for HTTPS interception):
Create the cert directory first, then generate a local CA:
mkdir -p ~/.deadlight openssl genrsa -out ~/.deadlight/ca.key 4096 openssl req -new -x509 -days 3650 \ -key ~/.deadlight/ca.key \ -out ~/.deadlight/ca.crt \ -subj "/CN=deadmesh CA/O=deadlight/C=US" chmod 600 ~/.deadlight/ca.key chmod 644 ~/.deadlight/ca.crt
Install it system-wide so curl and other tools trust it:
sudo cp ~/.deadlight/ca.crt /usr/local/share/ca-certificates/deadmesh.crt sudo update-ca-certificatesCopying from another machine? If you already have a CA from a previous install (e.g. WSL), copy both
ca.crtandca.keyto~/.deadlight/on the new machine instead of generating new ones. -
Configure — create
deadmesh.conf:[core] port = 8080 max_connections = 50 log_level = info [meshtastic] enabled = true serial_port = /dev/ttyACM0 baud_rate = 115200 mesh_node_id = 0 ; 0 = auto-detect from device fragment_size = 220 ack_timeout = 30000 max_retries = 3 hop_limit = 3 [ssl] enabled = true ca_cert_file = /home/youruser/.deadlight/ca.crt ca_key_file = /home/youruser/.deadlight/ca.key [network] connection_pool_size = 5 connection_pool_timeout = 600 upstream_timeout = 120
Important: Use absolute paths for
ca_cert_fileandca_key_file— replaceyouruserwith your actual username. The~shortcut expands to/root/when running withsudo, which is not where your certs are. -
Run the gateway:
./bin/deadmesh -c deadmesh.conf -v
You should see:
Configuration loadedandConfig applied— config is validMeshtastic: sent want_config handshake— serial API initializedMeshtastic: auto-detected local node ID: XXXXXXXX— device recognizedMeshtastic: NodeInfo update for XXXXXXXX— mesh nodes populating- Live packet stream:
POSITION,TELEMETRY,TEXT,NODEINFOfrom mesh
If you see
Configuration validation failed: Cannot read CA cert file— the path in your config doesn't match where you put the certs. Double-check the absolute path and that~/.deadlight/ca.crtexists. -
Open the dashboard at
http://localhost:8081to monitor gateway activity. -
Test the proxy:
# HTTP curl -x http://localhost:8080 http://example.com # HTTPS curl --cacert ~/.deadlight/ca.crt -x http://localhost:8080 https://example.com # SOCKS5 curl --socks5 localhost:8080 http://example.com
The deadmesh-client binary runs a tiny local HTTP proxy that tunnels traffic over the mesh to your gateway.
Build note: Serial mode requires a compile-time flag
# Add -DCLIENT_TRANSPORT_SERIAL to client target in Makefile (see earlier instructions)
make clean client UI=1Run on client device (replace with your gateway's node ID)
./bin/deadmesh-client --gateway 14e7cdaf --device /dev/ttyACM0 -v
# or Bluetooth serial
./bin/deadmesh-client --gateway 14e7cdaf --device /dev/rfcomm0 -vOnce running (listen on localhost:8888)
export http_proxy=http://localhost:8888
curl http://example.com
deadmesh works under WSL2 with USB/IP passthrough for the Meshtastic radio:
# PowerShell (Admin) — install and attach USB device
winget install usbipd
usbipd list # Find your radio's BUSID
usbipd bind --busid <BUSID> # One-time bind
usbipd attach --wsl --busid <BUSID> # Attach to WSL (repeat after replug)# WSL — verify device
ls -l /dev/ttyACM0
sudo usermod -a -G dialout $USERNote: You must re-run
usbipd attachfrom PowerShell each time the radio is unplugged, the PC sleeps, or WSL restarts.
| Device | Chip | Connection | Status |
|---|---|---|---|
| Seeed Wio Tracker L1 | nRF52840 + SX1262 | USB CDC (/dev/ttyACM0) |
✓ Verified |
| RAK WisBlock (RAK4631) | nRF52840 + SX1262 | USB CDC | Expected to work |
| Heltec LoRa 32 V3 | ESP32-S3 + SX1262 | USB CDC (CH9102) | Testing |
| Heltec V4 | ESP32-S3 | USB CDC | Expected to work |
| Lilygo T-Beam | ESP32 + SX1276/8 | USB UART (CP2104) | Expected to work |
| Lilygo T-Echo | nRF52840 + SX1262 | USB CDC | Expected to work |
| Station G2 | ESP32-S3 | USB CDC | Expected to work |
Option 1: Raspberry Pi Gateway (most versatile)
- Raspberry Pi 4/5 (2GB+ RAM)
- Any Meshtastic radio from table above
- Connection: USB serial
- Power: 5V/3A supply or 12V solar panel + battery
Option 2: x86/ARM Server (development / high-throughput)
- Any Linux box with USB port
- Works under WSL2 with USB/IP passthrough
- Meshtastic radio via USB
Option 3: Industrial/Outdoor
- Weatherproof enclosure with Raspberry Pi
- High-gain directional antenna (5-8 dBi)
- Solar panel + LiFePO4 battery for 24/7 operation
Any Meshtastic-compatible device works:
- Android/iOS: Meshtastic app on phone (Bluetooth to radio)
- Handheld: RAK WisBlock, Lilygo T-Echo, Heltec LoRa 32
- Custom: ESP32 + LoRa module + deadmesh client build
For best Internet gateway performance:
# In Meshtastic app or CLI
meshtastic --set lora.region US --set lora.modem_preset LONG_FAST
meshtastic --set lora.tx_power 30 # Check local regulations
meshtastic --set lora.hop_limit 3 # Adjust for network sizedeadmesh ships with a real-time gateway dashboard embedded directly in the binary. No external files, no dependencies, nothing to serve separately.
Access: http://localhost:8081 (configurable via plugin.stats.web_port)
Features:
- Live stats: active links, packets relayed, bytes bridged, mesh node count, gateway uptime
- Live mesh node table: node ID, name, hops, SNR, battery level, GPS position indicator, last heard age (ticks in real time)
- Gateway log stream via SSE (Server-Sent Events) zero polling
- Tabbed left panel: Mesh Nodes (default) and Proxy Links
- Green RF terminal aesthetic with antenna favicon in browser tab
Build with dashboard support:
make clean && make UI=1Create deadmesh.conf:
[core]
port = 8080
max_connections = 50
log_level = info
[meshtastic]
enabled = true
serial_port = /dev/ttyACM0
baud_rate = 115200
mesh_node_id = 0 ; 0 = auto-detect from device on startup
custom_port = 100 ; Meshtastic portnum for deadmesh traffic
fragment_size = 220 ; max payload bytes per LoRa packet
ack_timeout = 30000 ; ms — 30s for mesh ACKs
max_retries = 3
hop_limit = 3
[ssl]
enabled = true
ca_cert_file = /home/youruser/.deadlight/ca.crt
ca_key_file = /home/youruser/.deadlight/ca.key
[network]
connection_pool_size = 5
connection_pool_timeout = 600
upstream_timeout = 120Important: Use absolute paths for cert files. Running with
sudochanges~to/root/.
On mesh client devices, configure proxy settings:
# Linux/Mac
export http_proxy=http://gateway-ip:8080
export https_proxy=http://gateway-ip:8080
# Or point any application at:
# HTTP Proxy: gateway-ip port 8080
# SOCKS5: gateway-ip port 8080On Android (Meshtastic app + ProxyDroid):
- Install ProxyDroid
- Set proxy host to gateway IP, port 8080
- Connect Meshtastic app via Bluetooth to your radio
# HTTP through gateway
curl -x http://localhost:8080 http://example.com
# HTTPS (with CA cert — use absolute path)
curl --cacert /home/youruser/.deadlight/ca.crt -x http://localhost:8080 https://example.com
# SOCKS5
curl --socks5 localhost:8080 http://example.com
# SOCKS4
curl --socks4 localhost:8080 http://example.com
# Send email via mesh relay
curl -x http://localhost:8080 \
--mail-from sender@example.com \
--mail-rcpt recipient@example.com \
--upload-file message.txt \
smtp://smtp.gmail.com:587
# SSH over mesh (SOCKS5 proxy)
ssh -o ProxyCommand="nc -X 5 -x localhost:8080 %h %p" user@remote-serverUse the mesh simulator to feed fake mesh packets to the gateway:
# Terminal 1 — gateway pointed at sim PTY
./tools/mesh-sim # note the /dev/pts/X name it prints
# Then edit deadmesh.conf serial_port = /dev/pts/X and restart gateway
# Terminal 2 — inside sim, type:
http 01234567 http://example.com
statusThis helps develop/test the gateway receive & proxy path without real LoRa.
pip install meshtastic
meshtastic --info --port /dev/ttyACM0Note: Stop deadmesh before using the Meshtastic CLI — they cannot share the serial port simultaneously.
[core] — port, bind address, max connections, log level, worker threads
[meshtastic] — serial port, baud rate, node ID (0=auto-detect), custom portnum, fragment size, ACK timeout, retries, hop limit, gateway announcement
[ssl] — CA cert/key paths (use absolute paths), cipher suites, certificate cache
[network] — connection pool size/timeout, upstream timeout, DNS, keepalive
[vpn] — optional TUN/TAP gateway for routing entire device traffic through mesh
[plugins] — enable/disable individual plugins, plugin directory, autoload list
[plugin.compressor] — compression algorithms, minimum size threshold (strongly recommended over LoRa)
[plugin.cache] — cache directory, max size, TTL (reduces repeat mesh traffic significantly)
[plugin.ratelimiter] — priority queuing and rate limiting
[plugin.stats] — dashboard port, update interval, history size
Bandwidth conservation:
[plugin.compressor]
enabled = true
min_size = 512
algorithms = gzip,brotli
[plugin.cache]
enabled = true
max_size_mb = 500
ttl_hours = 24Latency tolerance (multi-hop paths):
[meshtastic]
ack_timeout = 60000
max_retries = 5
[network]
upstream_timeout = 300
connection_pool_timeout = 600For redundancy across a large mesh:
[meshtastic]
gateway_mode = true
announce_interval = 300Multiple deadmesh gateways on the same channel will announce themselves, allowing clients to route via the nearest available gateway.
┌─────────────┐ ┌──────────────┐ ┌──────────┐
│ Mesh Client │ LoRa Packets │ deadmesh │ TCP/IP │ Internet │
│ (Phone / ├─────────────────>│ Gateway ├───────────────>│ Services │
│ Handheld) │ (868/915 MHz) │ │ │ │
│ │ │ - Fragment │ │ HTTP │
│ Meshtastic │ │ - Reassemble │ │ SMTP │
│ App │<─────────────────┤ - TLS Proxy │<───────────────┤ IMAP │
└─────────────┘ │ - Cache │ └──────────┘
│ - Compress │
└──────┬───────┘
│
┌──────┴───────┐
│ Serial API │
│ 0x94 0xC3 │
│ protobuf │
│ want_config │
└──────┬───────┘
│ USB
┌──────┴───────┐
│ Meshtastic │
│ Radio │
│ (LoRa) │
└──────────────┘
1. Open serial port (/dev/ttyACM0) at 115200 baud
2. Send want_config handshake (ToRadio protobuf)
3. Receive MyNodeInfo → auto-detect local node ID
4. Receive device config, module config, channel config
5. Receive NodeInfo for all known mesh nodes → populate node table
6. Begin receiving live mesh packets (position, telemetry, text, etc.)
7. Filter for custom portnum (100) for proxy session traffic
8. All other packets update node table (hops, SNR, battery, position)
Request (client → Internet):
HTTP GET request (1500 bytes)
└─> Split into 7 LoRa packets (~220 bytes each)
└─> Each tagged with sequence number + session ID
└─> Sent hop-by-hop through mesh to gateway on portnum 100
└─> Gateway reassembles → proxies to Internet
Response (Internet → client):
HTTP response (50KB HTML)
└─> Compressed if plugin.compressor enabled (~5-10KB)
└─> Cached if cacheable (saves future airtime)
└─> Fragmented into LoRa packets with flow control
└─> Client reassembles → delivers to application
Meshtastic uses a length-prefixed binary protocol over serial:
┌────────┬────────┬───────────┬───────────┬─────────────────┐
│ 0x94 │ 0xC3 │ len_hi │ len_lo │ protobuf payload│
│ magic0 │ magic1 │ (MSB) │ (LSB) │ (FromRadio/ │
│ │ │ │ │ ToRadio) │
└────────┴────────┴───────────┴───────────┴─────────────────┘
The framing layer handles sync recovery, if magic bytes are lost mid-stream, the state machine re-synchronizes automatically.
See ARCHITECTURE.md for LoRa to socket abstraction layer.
deadmesh auto-detects protocols by inspecting initial bytes, no configuration needed:
| Initial bytes | Protocol | Handler |
|---|---|---|
GET / HTTP/1.1 |
HTTP | Forward to upstream |
CONNECT host:443 |
HTTPS tunnel | TLS interception (HTTP/1.1 ALPN) |
EHLO / HELO |
SMTP | Email relay |
A001 NOOP |
IMAP | Mail client support |
\x05 |
SOCKS5 | Transparent tunneling |
\x04 |
SOCKS4 | Legacy tunneling |
| Port | Type | Handling |
|---|---|---|
| 1 | TEXT_MESSAGE | Logged for mesh visibility |
| 3 | POSITION | Node table updated (lat/lon/alt) |
| 4 | NODEINFO | Node table updated (name, position, SNR) |
| 5 | ROUTING | Logged |
| 67 | TELEMETRY | Node table updated (battery level) |
| 100 | DEADMESH (custom) | Routed to proxy session manager |
Every packet received updates the in-memory node table keyed by node ID. The table persists for the lifetime of the gateway process and is exposed via /api/nodes. Fields populated per source:
- NodeInfo (startup dump): short name, long name, position, SNR, last heard timestamp
- Any decoded packet header: hops away (
hop_start - hop_limit), SNR, last heard - POSITION_APP: latitude, longitude, altitude
- TELEMETRY_APP: battery level
Encryption layers:
- LoRa PHY: AES-256 at the Meshtastic layer (channel PSK)
- TLS: End-to-end between client and final destination (HTTP/1.1 negotiated via ALPN)
- Proxy MITM (optional): deadmesh terminates TLS for caching/inspection — requires clients to trust the gateway CA
Trust model: Gateway holds the root CA. Mesh uses Meshtastic channel encryption. Clients trust the gateway CA by installing ca.crt.
Privacy: Mesh node IDs are pseudonymous. For operational security in sensitive deployments, rotate node IDs and channel keys regularly, and avoid PII in mesh metadata.
Scenario: Earthquake destroys cell infrastructure
Setup: Solar-powered deadmesh gateway at field hospital (satellite uplink). Rescue teams carry Meshtastic handhelds (10km range per hop). Coordinate via email, share maps, update databases.
Result: Teams stay connected across 50+ km² with zero functioning infrastructure.
Scenario: Village 30km from nearest fiber
Setup: One gateway at village center (WiMAX or satellite backhaul). Residents install Meshtastic radios on roofs. Multi-hop mesh covers entire valley.
Result: 100+ households share a single Internet connection. Hardware cost ~$50/household, no monthly fees.
Scenario: Large gathering needs coordination without government-controlled infrastructure
Setup: Organizers carry deadmesh gateways with LTE failover. Attendees use Meshtastic app on phones. Network disappears forensically when powered down.
Result: Thousands communicate freely. No persistent logs, no fixed infrastructure to seize.
Scenario: Government shuts down Internet during protests
Setup: Journalist has Meshtastic radio + deadmesh on laptop. Connects to gateway run by colleague 15km away (who has connectivity). Files stories via mesh SMTP relay.
Result: Censorship bypassed. Reports reach editors despite blackout.
LoRa physical layer (LONG_FAST preset):
- Raw bitrate: ~5.5 kbps
- Effective throughput: ~3-4 kbps after protocol overhead
- Latency: 500ms–5s per hop
Real-world application performance:
- Email: 10-20 messages/minute (text)
- Web browsing: 30-60 seconds per page (with caching)
- DNS: ~2 seconds per lookup (cache aggressively)
- API calls: 5-10 seconds per request
- File transfer: ~400 bytes/sec (~1.4 MB/hour)
Optimization tips:
- Enable compression — 3-10x improvement for text content
- Enable caching — repeat requests cost zero airtime
- Use image proxies — reduce image sizes before they hit the mesh
- Batch requests — avoid chatty protocols
Single gateway: 10-20 concurrent mesh clients comfortably. EU duty cycle regulations (1% airtime) are typically the binding constraint.
Multi-gateway: Horizontally scalable. Gateways announce availability; clients route via nearest. Adding gateways directly adds capacity.
Bottlenecks in order: LoRa duty cycle → mesh hop count (>4 hops = diminishing returns) → gateway uplink bandwidth.
- HTTP/HTTPS/SOCKS4/SOCKS5 proxy, verified working
- TLS interception with upstream certificate mimicry
- Connection pooling with TLS session reuse
- Serial API handshake (
want_config) for Meshtastic 2.x firmware - Auto-detect local node ID from device
- Full mesh packet decoding: text, position, telemetry, nodeinfo, routing
- Embedded SSE dashboard
- Plugin system: ad blocker, rate limiter, meshtastic transport
- Mesh simulator for development (
tools/mesh-sim) - WSL2 support via USB/IP passthrough
- Live node table in dashboard: names, hops, SNR, battery, position, last heard
- Sortable node table columns
- Real-time last-heard age (client-side tick, no polling)
- Tabbed dashboard panel (Mesh Nodes / Proxy Links)
-
/api/nodesendpoint: full node table as JSON - Node table persisted in
DeadlightContextaccessible to all subsystems - SSE push for node table updates (not polling anymore, live SSE)
- Text message panel: display mesh chat in dashboard
- SSE stream stability (cross-thread write fix, 6+ hour uptime confirmed)
- TCP keepalive + stale connection detection (HUP/ERR pre-check)
- UTF-8/emoji correct JSON escaping in node names and messages
- Ghost connection cleanup (Chrome prefetch/prerender connections detected and cleaned within 2s)
- End-to-end proxy session test over real LoRa
- Node topology map: visualize mesh graph from hop data
- Adaptive fragmentation based on live mesh conditions
- Exponential backoff retry
- Android client app (native deadmesh on-device)
-
mesh://scheme handler — gateway-side URL prefix for forced LoRa optimization - Smart mesh router — whitelist/blacklist/API substitution table
- Content transformation pipeline — readability strip, image drop, size cap
- Wikipedia plaintext fast path via MediaWiki API
- Multi-gateway coordination protocol
- Offline message queue (store-and-forward when gateway unreachable)
- Per-client/protocol bandwidth shaping
- WebRTC signaling over mesh (peer-to-peer voice/video)
- Per-node RSSI, airtime, channel utilization in dashboard
- Per-domain transformation profiles
- Automatic tier classification (ML-assisted or heuristic)
- Client-side
mesh://scheme handler for Android
- Full IPv6 support
- Meshtastic firmware integration (run deadmesh directly on ESP32)
- Satellite backhaul optimization (Starlink, Iridium)
- Mesh route prediction
# Debian/Ubuntu
sudo apt-get install build-essential pkg-config libglib2.0-dev \
libssl-dev libjson-glib-dev
# Python (for nanopb protobuf generation)
pip install protobuf grpcio-toolsmake clean && make UI=1 # Full build with dashboard
make clean && make # Build without dashboard
make # Incremental buildbin/deadmesh # Main binary
bin/plugins/adblocker.so # Ad blocker plugin
bin/plugins/meshtastic.so # Meshtastic transport plugin
bin/plugins/ratelimiter.so # Rate limiter plugin
tools/mesh-sim # Mesh network simulator
deadmesh is a specialized component of the Deadlight ecosystem, built on proxy.deadlight. Contributions welcome:
- Protocol optimizations: Improve mesh efficiency
- Hardware testing: Validate on different radio platforms
- Real-world deployments: Share use cases and lessons learned
- Dashboard improvements: Mesh visualization, node maps, telemetry charts
- Documentation: Non-English guides especially valuable for global deployments
See CONTRIBUTING.md for guidelines.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Blog: deadmesh.boo
- Support development: ko-fi/gnarzilla
deadmesh is one layer of a modular stack:
| Project | Lang | Role |
|---|---|---|
| proxy.deadlight | C | SMTP/SOCKS/HTTP/VPN proxy foundation |
| deadmesh (this) | C | LoRa-to-Internet mesh gateway |
| blog.deadlight | JS | <10KB pages, email posting, edge-first |
| vault.deadlight | C | Offline credential store, proxy integration |
| deadlight-bootstrap | JS | Cloudflare Workers + D1 framework |
Each component works standalone but the stack is designed to thrive together; blog.deadlight posting over deadmesh via proxy.deadlight with vault.deadlight managing credentials, all running on solar-powered hardware in a field somewhere.
Radio regulations: LoRa operates in license-free ISM bands, but transmission power and duty cycle are regulated. Check your local rules (FCC Part 15 in US, ETSI EN 300-220 in EU).
Encryption export: This software includes strong cryptography. Check export restrictions before deploying internationally.
Responsible use: This tool can bypass censorship and enable communication in emergencies. It can also be misused. Use ethically and legally. The authors are not responsible for misuse.
Privacy: Meshtastic mesh networks are pseudonymous, not anonymous. For operational security in high-risk environments: rotate node IDs, use ephemeral channel keys, avoid PII in mesh metadata.
MIT License — see LICENSE
Includes:
- Meshtastic Protobufs (GPL v3)
- nanopb (zlib license)
Status: v1.1 — proxy verified, mesh serial active, 90+ nodes visible, live dashboard with SSE streaming (6h+ uptime confirmed), emoji/UTF-8 correct | Maintained by: @gnarzilla | deadlight.boo




