Macha Logo

Self-hosting

Run your own tunnel server on any VPS. Your users connect to it instead of macha.live — traffic never leaves your infrastructure.

Docker setup

Prerequisites: A VPS with Docker installed, and a domain with a wildcard DNS A record: *.tunnel.yourcompany.com → your-vps-ip.
docker-compose.yml
services:
  macha:
    image: ghcr.io/dhineshk/macha-server:latest
    restart: unless-stopped
    ports:
      - "80:8080"     # public HTTP (put Caddy in front for HTTPS)
      - "9000:9000"   # agent control plane
      - "9001:9001"   # agent data plane
    environment:
      DOMAIN: tunnel.yourcompany.com
      AUTH_TOKEN: change-me-to-a-random-secret
docker compose up -d

That's it — the server is running. Now point agents at it:

macha --port 3000 --subdomain myapp \
      --server tunnel.yourcompany.com \
      --token your-secret

Tunnel URLs will read https://myapp.tunnel.yourcompany.com.

Server environment variables

VariableDefaultDescription
DOMAINmacha.liveBase domain used in tunnel URLs and Host-header parsing
PUBLIC_SCHEMEhttpshttps or http — prefix in the URL returned to agents
AUTH_TOKEN(none)If set, agents must pass this token in REGISTER or be rejected
PUBLIC_PORT8080Port the public HTTP listener binds on inside the container
CONTROL_PORT9000Port agents use to register (control plane)
DATA_PORT9001Port agents use for on-demand data connections (data plane)
TLS_CERT(none)Path to PEM certificate — enables TLS on ports 9000/9001
TLS_KEY(none)Path to PEM private key — required with TLS_CERT
RUST_LOG(none)Log verbosity — e.g. server=info or server=debug

HTTPS with Caddy

Caddy handles wildcard TLS certificates automatically using Let's Encrypt. Add this alongside your docker-compose.yml:

Caddyfile
*.tunnel.yourcompany.com {
    tls {
        dns <your-dns-provider>
    }
    reverse_proxy macha:8080
}
docker-compose.yml (with Caddy)
services:
  caddy:
    image: caddy:latest
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
    environment:
      <DNS_PROVIDER_API_TOKEN_VAR>: <your-token>

  macha:
    image: ghcr.io/dhineshk/macha-server:latest
    restart: unless-stopped
    expose: ["8080"]
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      DOMAIN: tunnel.yourcompany.com
      AUTH_TOKEN: change-me

volumes:
  caddy_data:
Caddy supports wildcard certs via DNS challenge. Check the Caddy docs for your DNS provider's plugin (Cloudflare, Route53, etc.).

TLS for agent connections

By default ports 9000 and 9001 are plain TCP. If you want the agent-to-server connection encrypted (important if AUTH_TOKEN is set), add TLS:

docker-compose.yml additions
environment:
  TLS_CERT: /certs/fullchain.pem
  TLS_KEY:  /certs/privkey.pem
volumes:
  - /etc/letsencrypt/live/tunnel.yourcompany.com:/certs:ro

Then agents must connect with --tls:

macha --port 3000 --subdomain myapp \
      --server tunnel.yourcompany.com \
      --token my-secret \
      --tls

For self-signed certificates, use --tls-ca /path/to/ca.pem instead of --tls.