Home

Awesome

Punchmole

Punchmole is a simple tool to give your locally running HTTP(s) servers a public URL and is an easy to self-host alternative to ngrok and/or tunnelmole.

Implemented in Node with the goal to have as much flexibility and as little dependencies and code as possible.

The project has 2 components:

This service allows streaming of origin request (e.g. file-uploads, other than Tunnelmole which buffers request data completely in memory). The service also supports Websocket proxying depending on websocket endpoint url path

Client & Server are both solely configurable via ENV-variables.

Status

This project is experimental and currently used for some pet-projects, quickly hacked together in a few hours.

Well-known issues:

Server

The server opens a single HTTP port to which the Punchmole client connects and upgrades to a websocket connection.

Each request to this HTTP port is forwarded (based on clients HOST header) to a corresponding connected Punchmole client connection which can ultimately serve the request.

Environment variables

VariableDefault ValueDescription
PORT10000HTTP port on which the server listens
API_KEYSn/aA comma-separated list of API keys the server accepts connections for
PUNCHMOLE_ENDPOINT_URL_PATH/_punchmoleA WebSocket URL path which is used to determine if the incoming connection is for punchmole to register and connect a punchmole client or a user request which needs to be forwarded

Installation

npm install -g punchmole

Run

PORT=10000 \
API_KEYS=api-key1,api-key2,random-string-nobody-can-guess \
PUNCHMOLE_ENDPOINT_URL_PATH=/_punchmole \
punchmole-server 

Run on docker

docker build -t punchmole .
docker run -e API_KEYS=api-key1,api-key2,random-string-nobody-can-guess punchmole

Usage in own Node code

The server can also easily get used in your own project:

import { PunchmoleServer } from "punchmole";

PunchmoleServer(
    PORT, // port number to listen on
    API_KEYS, // array of api keys (random strings)
    PUNCHMOLE_ENDPOINT_URL_PATH, // /_punchmole is the default path
    console // console, {info: {}, debug: {}, error: {}} for no logs or e.g. an instance of log4js
)

Client

The client connects to the Punchmole server, with first connection the client shares the given API key and a domain it wants to receive requests for.

Environment variables

VariableDefault ValueDescription
PUNCHMOLE_API_KEYn/aAn API-key the server accepts
DOMAINn/aThe domain the client wants to receive requests for
TARGET_URLhttp://localhost:3000URL to which the incoming requests are forwarded to, either local or within the private network
PUNCHMOLE_ENDPOINT_URLws://localhost:10000/_punchmoleWebsocket URL of the Punchmole server, make sure if you want to change /_punchmole to adjust PUNCHMOLE_ENDPOINT_URL_PATH in punchmole server

Installation

npm install -g punchmole

Run

PUNCHMOLE_ENDPOINT_URL=ws://localhost:10000/_punchmole \
TARGET_URL=http://localhost:3000 \
API_KEY=api-key1 \
DOMAIN=testdomain.com \
punchmole

Usage in own Node code

The client can also easily get used in your own project:

import { PunchmoleClient } from "punchmole";

const punchmoleEvents = PunchmoleClient(
    "API KEY",
    "DOMAIN",
    "TARGET URL",
    "PUNCHMOLE ENDPOINT URL"
)
punchmoleEvents.addListener("registered", (result) => console.log(result))
punchmoleEvents.addListener("request", (result) => console.log(result))
punchmoleEvents.addListener("request-end", (result) => console.log(result))