Open Source, General Purpose, Sovereign, Decentralized, Peer to Peer Internet.
- Share your local HTTP/TCP with anyone, without any central server.
- Host your own HTTP bridge using
malai http-bridgeto access exposed services via web browser. - Built on top of iroh, a p2p networking library.
Malai is a simple tool that can be used to expose any local service (HTTP, TCP and, SSH, etc.) to the world. It can be paired up with an ACL system (like Kulfi) to control access to the exposed services.
# Clone the repository
git clone https://github.com/ovo-Tim/kulfi
cd kulfi
# Build malai
cargo build --release -p malai
# The binary will be available at target/release/malaiStep 1: Run an HTTP bridge (on a server with a public domain):
# On your server (e.g., bridge.example.com)
malai http-bridge --port 80Step 2: Expose a local HTTP service (e.g., running on port 3000):
# On your local machine
malai http 3000 --bridge bridge.example.com --publicThis will generate or use an existing identity and expose your service. The service
will be accessible via https://<your-id52>.bridge.example.com through your HTTP bridge.
Expose a local HTTP service to the kulfi network:
malai http <PORT> [OPTIONS]
Options:
--host <HOST> Host serving the HTTP service [default: 127.0.0.1]
--bridge <BRIDGE> HTTP bridge domain to use (required for web access) [env: MALAI_HTTP_BRIDGE]
--public Make the service public (required)Example:
malai http 8080 --host 127.0.0.1 --bridge bridge.example.com --publicNote: You need to run your own HTTP bridge for web browser access. See the HTTP Bridge section below.
Expose a local TCP service (SSH, database, etc.):
malai tcp <PORT> [OPTIONS]
Options:
--host <HOST> Host serving the TCP service [default: 127.0.0.1]
--public Make the service public (required)Example:
malai tcp 22 --public # Expose SSHExpose a local UDP service (DNS, game servers, VoIP, etc.):
malai udp <PORT> [OPTIONS]
Options:
--host <HOST> Host serving the UDP service [default: 127.0.0.1]
--public Make the service public (required)Example:
malai udp 53 --public # Expose DNSExpose both TCP and UDP on the same port simultaneously:
malai tcp-udp <PORT> [OPTIONS]
Options:
--host <HOST> Host serving the TCP+UDP service [default: 127.0.0.1]
--public Make the service public (required)Example:
malai tcp-udp 25565 --public # Expose Minecraft server (uses both protocols)Share a folder over HTTP:
malai folder <PATH> [OPTIONS]
Options:
--bridge <BRIDGE> HTTP bridge domain to use (required for web access) [env: MALAI_HTTP_BRIDGE]
--public Make the folder public (required)Example:
malai folder ./documents --bridge bridge.example.com --publicNote: You need to run your own HTTP bridge for web browser access.
Open a kulfi URL in your browser:
malai browse kulfi://<id52>/<path>Run an HTTP bridge server that forwards requests to kulfi services. You must host your own bridge to access HTTP services via web browser.
malai http-bridge [OPTIONS]
Options:
-t, --proxy-target <ID52> Forward to specific id52 (optional)
-p, --port <PORT> Port to listen on [default: 0 for random]Setting up your bridge:
- Get a server with a public IP and domain (e.g.,
bridge.example.com) - Configure wildcard DNS:
*.bridge.example.com→ your server IP - Run the bridge:
malai http-bridge --port 80(or use a reverse proxy with SSL) - Use
--bridge bridge.example.comwhen exposing services - Access services at:
https://<id52>.bridge.example.com
Run a TCP bridge server that forwards requests to a kulfi service:
malai tcp-bridge <PROXY_TARGET> [PORT]
Arguments:
<PROXY_TARGET> The id52 to forward TCP requests to
[PORT] Port to listen on [default: 0 for random]Run a UDP bridge server that forwards datagrams to a kulfi service:
malai udp-bridge <PROXY_TARGET> [PORT]
Arguments:
<PROXY_TARGET> The id52 to forward UDP datagrams to
[PORT] Port to listen on [default: 0 for random]Run an HTTP proxy (requires a remote proxy server):
malai http-proxy-remote --public # On remote server
malai http-proxy <REMOTE_ID52> --port 8080 # On local machineGenerate a new identity:
malai keygen [-f <FILE>]Create identity in system keyring:
malai identity create [-f <FILE>]Delete identity from system keyring:
malai identity delete --id52 <ID52>
# or
malai identity delete --file <FILE>For running multiple services, create a malai.toml file:
[malai]
log = "/var/log/malai.log" # Optional: log file path
[http.my_web_app]
identity = "id52_abc123..." # Optional: specific identity
secret_file = "/path/to/secret" # Optional: load identity from file
port = 3000
host = "127.0.0.1"
bridge = "bridge.example.com" # Your HTTP bridge domain
public = true
active = true
[http.another_service]
port = 8080
public = true
active = true
[tcp.ssh_service]
port = 22
host = "127.0.0.1"
public = true
active = true
# Multiple ports with per-port identities (required for multi-port)
[tcp.multi_port_app]
identity = ["id52_port1...", "id52_port2...", "id52_port3..."]
port = [4000, 4001, 4002] # Can also use "ports" instead of "port"
public = true
active = trueRun all services from config:
malai run --home /path/to/config/dir
# or
malai run --home /path/to/malai.toml
# or set MALAI_HOME environment variable
export MALAI_HOME=/path/to/config/dir
malai runMalai uses id52 identities for peer-to-peer connections. Identities can be:
- Generated on-the-fly: If no identity exists, one is created automatically
- Stored in system keyring: Use
malai identity createfor persistent identities - Stored in files: Use secret key files with
secret_fileoption in config - Specified per service: Each service in
malai.tomlcan use a different identity
An HTTP bridge allows you to access kulfi services through standard web browsers. You must host your own bridge on a server with a public domain.
Setup:
- Get a domain (e.g.,
bridge.example.com) pointing to your server - Configure wildcard DNS:
*.bridge.example.com→ server IP - Run bridge:
malai http-bridge --port 80 - Optionally use a reverse proxy (nginx/caddy) for automatic HTTPS
Usage:
- Expose service with bridge:
malai http 3000 --bridge bridge.example.com --public - Your service gets a unique
id52(e.g.,abc123...xyz) - Access via:
https://abc123...xyz.bridge.example.com - The bridge forwards requests to your local service via the kulfi P2P network
Why it's needed: Web browsers can't directly connect to kulfi's P2P protocol. The bridge acts as a gateway, translating HTTP requests to kulfi connections using the subdomain as the target id52.
MALAI_HTTP_BRIDGE: Default HTTP bridge domain for your services (set to your bridge domain)MALAI_HOME: Default configuration directory formalai run
Example:
export MALAI_HTTP_BRIDGE=bridge.example.com
malai http 3000 --public # Will use bridge.example.com automatically- The
--publicflag is required for all service exposure commands as a safety measure - Each service can use a separate identity for access control
- Identities can be managed through the system keyring for security
- Services not marked as
active = truein config will not start
# First, ensure you have an HTTP bridge running on a public server
# On your server: malai http-bridge --port 80
# Start your dev server (e.g., React on port 3000)
npm start
# In another terminal, expose it
malai http 3000 --bridge bridge.example.com --public
# Access via https://<your-id52>.bridge.example.com# Expose SSH service
malai tcp 22 --public
# On another machine, create a TCP bridge
malai tcp-bridge <your-id52> 2222
# Connect via the bridge
ssh user@localhost -p 2222# Expose a Minecraft server (uses both TCP and UDP)
malai tcp-udp 25565 --public
# On another machine, create bridges for both protocols
malai tcp-bridge <your-id52> 25565
# In another terminal:
malai udp-bridge <your-id52> 25565
# Players can now connect to localhost:25565# Share current directory (requires HTTP bridge)
malai folder . --bridge bridge.example.com --public
# Others can browse via https://<your-id52>.bridge.example.comCreate malai.toml:
[http.blog]
port = 8080
public = true
active = true
[http.api]
port = 3000
public = true
active = true
[tcp.database]
port = 5432
public = true
active = false # Disabled for now
[udp.dns]
port = 53
public = true
active = true
[tcp_udp.game_server]
port = 25565
public = true
active = true
# Expose multiple ports with per-port identities
[tcp.microservices]
identity = ["id52_service1...", "id52_service2...", "id52_service3..."]
port = [8001, 8002, 8003]
public = true
active = trueRun all active services:
malai runMulti-port services: When you specify multiple ports (e.g., port = [8001, 8002, 8003]), you must provide a matching array of identities or secret files, one per port:
# Per-port identities
[tcp.microservices]
identity = ["id52_service1...", "id52_service2...", "id52_service3..."]
port = [8001, 8002, 8003]
public = true
active = true
# Or per-port secret files
[tcp.microservices]
secret_file = ["/path/to/key1", "/path/to/key2", "/path/to/key3"]
port = [8001, 8002, 8003]
public = true
active = trueEach port gets its own identity so clients can distinguish which port to connect to. The array length must match the number of ports, or malai will fail to start the service.
This is useful for:
- Microservices running on different ports that need separate identities
- Game servers with multiple service ports
- Applications with separate API and admin ports
Kulfi is a peer to peer network, free from any corporate control. Data stays with the user, and devices controlled by the user, and not with some central company.
Kulfi will soon be available as an binary that you can download and run on your computer. We will support Linux, Windows and MacOS from day one. We also want to create Apps that can be distributed through App Stores, and also support mobile devices.
kulfi and malai are built on top of iroh, and uses BitTorrent's
Mainline DHT for peer discovery.
This project is licensed under the UPL license. UPL is MIT like license, with Apache 2.0 like patent grant clause.
We welcome contributions to Kulfi & Malai. Please read the CONTRIBUTING.md file for details on how to contribute.