Getwebup documentation

Everything about the getwebup command-line tool: installation, HTTP and TCP tunnels, the config file, the request inspector, domains and the REST API.

Quick start

Three commands take a site running on your computer to a public HTTPS address:

# 1. Install (macOS / Linux; see below for Windows)
$ curl -fsSL https://connect.getwebup.in/install.sh | sh
# 2. Connect the CLI to your account (copy the token from the dashboard)
$ getwebup config add-authtoken <YOUR_AUTHTOKEN>
# 3. Expose http://localhost:3000
$ getwebup http 3000

The CLI shows the public URL, for example https://brave-otter-3f9a.tunnel.devai.in, and every request it forwards. Press Ctrl+C to stop the tunnel. No account yet? Sign up for free and copy your authtoken from the dashboard.

Installation

Getwebup is a single self-contained binary for Windows, macOS and Linux on x86-64 and ARM. The install scripts download the right build from this site, verify its SHA-256 checksum and put it on your PATH.

Windows

Run this in PowerShell (no administrator rights needed):

PS> irm https://connect.getwebup.in/install.ps1 | iex

It installs getwebup.exe to %LOCALAPPDATA%\getwebup and adds that folder to your user PATH. Open a new terminal afterwards so the PATH change takes effect.

macOS and Linux

$ curl -fsSL https://connect.getwebup.in/install.sh | sh

The script detects your system with uname (Intel and Apple silicon Macs; Linux on x86-64, ARM64 and ARMv7), installs to /usr/local/bin (using sudo when needed) or to ~/.local/bin when sudo is not available. Set GETWEBUP_INSTALL_DIR to choose another folder.

Manual download

Download the binary for your platform from the downloads page, rename it to getwebup (getwebup.exe on Windows), make it executable and put it in a folder on your PATH. Check the installation with:

$ getwebup version

Connect your account

The CLI identifies your account with an authtoken. Your first one is shown right after sign-up; create more on the Authtokens page. Save it once per machine:

$ getwebup config add-authtoken <YOUR_AUTHTOKEN>

This writes the token to the config file in your user profile:

SystemConfig file
Windows%AppData%\getwebup\getwebup.yml
macOS~/Library/Application Support/getwebup/getwebup.yml
Linux~/.config/getwebup/getwebup.yml

Run getwebup config check to validate the file and print the settings in effect (the token is masked). In CI or containers, set the GETWEBUP_AUTHTOKEN environment variable or pass --authtoken instead; both override the file.

Getwebup Cloud API key

Getwebup Cloud customers connect with their existing Getwebup API key from cloud.getwebup.in instead of an authtoken. Save it without showing it on screen:

$ getwebup config add-api-key

The CLI asks for the key with hidden input; getwebup config add-api-key - reads it from standard input instead, so it never appears in a command line. The install scripts save it for you when GETWEBUP_API_KEY is set, or ask for it with hidden input:

$ curl -fsSL https://connect.getwebup.in/install.sh | sh # then paste the key at the prompt

The key is only ever sent to the Getwebup control server it was saved for, over HTTPS; the CLI refuses other servers unless you pass --trust-server. In CI, set GETWEBUP_API_KEY (GETWEBUP_AUTHTOKEN wins when both are set).

HTTP tunnels

$ getwebup http <address> [flags]

Forwards a public HTTPS address to a local web server. WebSockets, server-sent events, uploads and streaming responses work unchanged. The address can be:

AddressForwards to
3000http://localhost:3000
localhost:8080http://localhost:8080
192.168.1.20:80a web server on another machine in your network
https://localhost:8443a local HTTPS server (self-signed certificates are accepted)
FlagDescription
--subdomain NAMEUse a subdomain you reserved, giving https://my-app.tunnel.devai.in for my-app. See reserved subdomains.
--domain HOSTServe the tunnel on a verified custom domain such as dev.example.com. See custom domains.
--basic-auth USER:PASSAsk visitors for a username and password. Repeat the flag to allow several users.
--host-header VALUErewrite sends the local address as Host, any other value is sent as is. Default: the public hostname. See host header rewriting.
--inspect=falseDo not record this tunnel's traffic in the request inspector (default true).
--name NAMELabel of the tunnel in the CLI and the dashboard.
--verify-upstream-tlsCheck the certificate of an https:// local address. Off by default because local certificates are usually self-signed.

Examples:

# a random address, for example brave-otter-3f9a.tunnel.devai.in
$ getwebup http 3000
# your reserved subdomain, protected with a password
$ getwebup http 8080 --subdomain my-app --basic-auth "demo:correct-horse"
# a local HTTPS app on your own domain, with the Host header rewritten
$ getwebup http https://localhost:8443 --domain dev.example.com --host-header rewrite

Random addresses are kept when the CLI reconnects after a network hiccup. For an address that never changes, reserve a subdomain or use a custom domain.

TCP tunnels

$ getwebup tcp <address> [--remote-port PORT] [--name NAME]

Forwards a public tcp://tcp.tunnel.devai.in:PORT address to any TCP service: SSH, databases, RDP, game servers, MQTT and more. Without --remote-port you get a random port in the range 20000–29999. To keep the same port, reserve it on the TCP Addresses page and pass it with --remote-port. TCP tunnels are available on paid plans.

# SSH into this machine from anywhere
$ getwebup tcp 22
#   Forwarding  tcp://tcp.tunnel.devai.in:24012 -> localhost:22
$ ssh -p 24012 you@tcp.tunnel.devai.in
# PostgreSQL on a reserved address
$ getwebup tcp 5432 --remote-port 24012

Config file and getwebup start

Define the tunnels you use every day in the config file and start them together. Tunnel names are up to you; each tunnel accepts the same options as the flags above.

# getwebup.yml
authtoken: <YOUR_AUTHTOKEN>
web_addr: 127.0.0.1:4040        # request inspector; "false" turns it off
tunnels:
  web:
    proto: http
    addr: "3000"
    subdomain: my-app
  api:
    proto: http
    addr: https://localhost:8443
    domain: api.example.com
    host_header: rewrite
    basic_auth:
      - "demo:correct-horse"
  docs:
    proto: http
    addr: "4000"
    inspect: false
  ssh:
    proto: tcp
    addr: "22"
    remote_port: 24012
$ getwebup start web api      # start the named tunnels
$ getwebup start --all        # start every tunnel in the file

Keys: proto (http or tcp), addr, subdomain, domain, remote_port, basic_auth, host_header and inspect. Unknown keys are reported as errors so typos never go unnoticed; run getwebup config check after editing. Use --config path to use another file.

Global flags

FlagDescription
--config PATHUse another config file.
--authtoken TOKENAuthtoken for this run (overrides GETWEBUP_AUTHTOKEN and the config file).
--server URLGetwebup server to connect to (overrides GETWEBUP_SERVER and the config file).
--web-addr ADDRInspector address, default 127.0.0.1:4040; false disables it.
--log DESTWrite logs to stdout, stderr, none or a file. Logging to stdout replaces the full-screen status view, which is handy in scripts and containers.
--log-level LEVELdebug, info, warn or error.
--log-format FORMATtext or json.

Request inspector

While the CLI runs, open http://127.0.0.1:4040 on the same machine. It lists every request that went through your HTTP tunnels, newest first, with method, path, status and duration. Select a request to see its headers and the request and response bodies (JSON is pretty-printed).

  • Replay sends the captured request to your local app again, which is ideal for debugging webhooks: fix your code, then replay the exact payload without asking the sender to retry.
  • Copy as cURL gives you a command line that reproduces the request.
  • Clear empties the list. The inspector keeps the last 200 requests in memory only; nothing is stored on disk or sent to Getwebup.

The inspector only listens on your own machine. If port 4040 is in use (for example by a second getwebup), pass --web-addr 127.0.0.1:4041. Turn it off with --web-addr false, or for one tunnel with --inspect=false.

Reserved subdomains

On paid plans you can reserve subdomains of tunnel.devai.in so that a tunnel always gets the same address, which is useful for OAuth callbacks, webhooks and links you shared with clients.

  1. Open Domains in the dashboard and reserve a name, for example my-app.
  2. Start the tunnel with it: getwebup http 3000 --subdomain my-app.
  3. Your site is online at https://my-app.tunnel.devai.in, and nobody else can use that address.

Names are 3 to 63 lowercase letters, digits and dashes. Some names (such as www, api or admin) are reserved by Getwebup.

Custom domains

Paid plans can serve tunnels on a domain you own, with an HTTPS certificate issued automatically.

  1. Open Domains and add your hostname, for example dev.example.com.
  2. At your DNS provider, create the two records shown in the dashboard:
TypeNameValuePurpose
CNAMEdev.example.comcustom.tunnel.devai.inSends visitors to Getwebup
TXT_getwebup-challenge.dev.example.comgetwebup-verify=<token from the dashboard>Proves that you own the domain
  1. Click Verify. The domain is marked Verified once the TXT record is visible; DNS changes usually take a few minutes, sometimes up to an hour.
  2. Start the tunnel: getwebup http 3000 --domain dev.example.com. The certificate is obtained on the first HTTPS request, which can take a few seconds.

Root domains (example.com without a subdomain) cannot have a CNAME record at most providers. Use your provider's ALIAS, ANAME or CNAME-flattening feature pointing to custom.tunnel.devai.in, or use a subdomain. If your provider appends the zone name automatically, enter only the part before it, for example _getwebup-challenge.dev.

Password protection

Keep work in progress private by requiring a username and password. Getwebup checks the credentials at the edge, before any request reaches your machine:

$ getwebup http 3000 --basic-auth "client:preview-2024" --basic-auth "me:another-secret"

Browsers show a login prompt; tools such as curl use curl -u client:preview-2024 https://brave-otter-3f9a.tunnel.devai.in. Use long, unique passwords: basic authentication is only as strong as the password.

Host header rewriting

By default your app receives the public hostname in the Host header (for example brave-otter-3f9a.tunnel.devai.in), and X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Proto describe the original request. Some development servers only answer to their own name and reply with errors such as "Invalid Host header" or a default virtual host. Rewrite the header in that case:

# send "localhost:8080" as the Host header
$ getwebup http 8080 --host-header rewrite
# send a fixed name, for a local virtual host
$ getwebup http 80 --host-header myproject.test

Bandwidth and limits

Each plan has a monthly bandwidth quota (traffic in both directions through all your tunnels, reset on the first day of each month, UTC), a throughput limit shared by your tunnels, a number of tunnels that can be online at once, and per-tunnel request and connection limits. The pricing page lists them and your Usage page shows where you stand. The CLI and the dashboard warn you at 80% of the quota; at 100% your tunnels show a "Bandwidth limit reached" page until the quota resets or your plan is upgraded.

Troubleshooting

Visitors see a warning page first

On plans with the visitor warning page (the Free plan by default), people who open your tunnel in a browser first see a short page explaining that the site is served through Getwebup, with a Visit site button. It protects everyone against phishing and is remembered for 7 days per browser. API clients, webhooks and scripts are not affected because the page is only shown to browsers. To skip it from your own code or tools, send the request header getwebup-skip-browser-warning with any value:

$ curl -H "getwebup-skip-browser-warning: 1" https://brave-otter-3f9a.tunnel.devai.in

Plans without the warning page never show it; compare plans on the pricing page.

Error pages served by Getwebup

CodeMeaningWhat to do
GW-404Unknown host.Check the address for typos; random addresses change when a tunnel is restarted after a while.
GW-OFFLINENo tunnel is online on this address.Start the CLI again. Reserved subdomains and custom domains come back on the same address.
GW-502The CLI could not reach your local app.Make sure the app is running and listening on the port you gave the CLI, for example open http://localhost:3000 on your machine. For HTTPS apps include the scheme: getwebup http https://localhost:8443.
GW-CONNSToo many simultaneous connections for your plan.Wait for open connections to finish or upgrade your plan.
GW-RATEToo many requests per minute for your plan.Requests are accepted again within a minute.
GW-QUOTAThe monthly bandwidth quota is used up.Wait for the reset on the first of the month or upgrade your plan.

The CLI cannot connect

  • Authentication failed: the authtoken was revoked or mistyped. Create a new one on the Authtokens page and run getwebup config add-authtoken again.
  • Tunnel limit reached: your plan allows a fixed number of online tunnels across all your machines. Stop one on the Tunnels page or with Ctrl+C.
  • Subdomain or domain errors: --subdomain only accepts names reserved by your account and --domain only verified domains. Check the Domains page.
  • Firewalls and proxies: the CLI only needs outgoing HTTPS (port 443) to https://connect.getwebup.in. It honours the HTTPS_PROXY environment variable.
  • Network drops: the CLI reconnects automatically with back-off and keeps your random address when it can. Run with --log stdout --log-level debug to see what happens.

REST API

Automate your account with the JSON API at https://connect.getwebup.in/api/v1. Authenticate every request with an authtoken in the Authorization header; we recommend a dedicated token per integration.

$ export GETWEBUP_AUTHTOKEN=<YOUR_AUTHTOKEN>
# your account, plan and usage
$ curl -H "Authorization: Bearer $GETWEBUP_AUTHTOKEN" https://connect.getwebup.in/api/v1/me
# tunnels online right now
$ curl -H "Authorization: Bearer $GETWEBUP_AUTHTOKEN" https://connect.getwebup.in/api/v1/tunnels
# reserve a subdomain
$ curl -X POST -H "Authorization: Bearer $GETWEBUP_AUTHTOKEN" \
       -H "Content-Type: application/json" -d '{"subdomain":"my-app"}' \
       https://connect.getwebup.in/api/v1/domains
# stop a tunnel
$ curl -X DELETE -H "Authorization: Bearer $GETWEBUP_AUTHTOKEN" https://connect.getwebup.in/api/v1/tunnels/<TUNNEL_ID>
EndpointDescription
GET /meAccount, plan limits and this month's usage.
GET /tunnelsYour online tunnels.
DELETE /tunnels/{id}Stop one of your tunnels.
GET /domainsReserved subdomains and custom domains, with DNS records.
POST /domainsReserve {"subdomain":"my-app"} or add {"hostname":"dev.example.com"}.
POST /domains/{id}/verifyCheck the DNS records of a custom domain.
DELETE /domains/{id}Release a subdomain or remove a custom domain.
GET /tcp-addressesYour reserved TCP addresses.
POST /tcp-addressesReserve a TCP address: {"port":0} picks a free port.
DELETE /tcp-addresses/{id}Release a TCP address.
GET /usageBandwidth this month, per day.
GET /authtokensYour authtokens (never the secret value).
POST /authtokensCreate a token: {"name":"ci"}. The response contains the token once.
DELETE /authtokens/{id}Revoke a token.

Requests and responses use JSON; send Content-Type: application/json with a body. Times are RFC 3339 in UTC. Errors use the HTTP status code and a body such as {"error":{"code":"limit_reached","message":"..."}}, where message is safe to show to people.