Deployment guide

sish

Overview

sish is an open source, self-hosted SSH tunneling server, a drop-in alternative to ngrok and serveo that you run on your own infrastructure. It runs an SSH server whose only job is forwarding and multiplexing, so anyone can expose a local service on a public URL with a command they already know: an ordinary ssh remote forward. End users need no custom client, no third-party relay sits in the path, and there is no per-seat bill.

This guide covers deploying and configuring the SecureAnyCloud sish image on Ubuntu 24.04 on Azure. The image installs sish 2.23.0 from the official prebuilt release binary and runs it under systemd as the sish.service tunnel server. Its SSH tunnel ingress listens on port 2222, kept separate from the standard SSH service on port 22 that you use to manage the VM. It terminates HTTP and HTTPS for your tunnels on ports 80 and 443, and sish handles its own HTTPS from a per-instance certificate.

There is no web interface and no database. The flat /etc/sish/config.yml plus the per-instance key material is the whole configuration.

Secure by default, with no known credentials. A tunnel server that anyone can connect to is an abuse risk, so this image forces authentication on and ships the authorized key list empty. On the first boot of every VM, a one-shot service generates a unique SSH host identity for the server, a unique authorized tunnel key for you and a per-instance TLS certificate. It then writes your private tunnel key to a root-only credentials file and renders the config with this VM's tunnel domain.

Only that key, plus any additional public keys you choose to add, may open a tunnel. The server refuses to start until this setup completes, so there is never an open, unauthenticated window.

What you get:

  • sish 2.23.0 from the official prebuilt release binary, run under systemd as sish.service
  • An SSH tunnel ingress on :2222 (separate from the management SSH service on :22) and HTTP and HTTPS tunnel routers on :80 and :443
  • HTTP(S), TCP, TLS and alias tunnels multiplexed from many clients through one server
  • A per-instance tunnel domain of the form <public-ip>.sslip.io, so tunnel URLs resolve out of the box with no DNS setup
  • Authentication forced on with an empty authorized key list, so only keys you authorize may open a tunnel
  • A unique per-instance authorized tunnel key generated on first boot and written to /root/sish-credentials.txt (root only)
  • A built-in tunnel self-test (/opt/sish/tunnel-selftest.sh) that proves a real tunnel round-trips, self-contained on the one VM
  • 24/7 SecureAnyCloud support

Prerequisites

Before you deploy this image, make sure you have:

  • An active Azure subscription, an SSH public key, and a VNet and subnet in the target region
  • A subscription to the sish listing on Azure Marketplace
  • Network Security Group rules that allow TCP 22 (VM administration), TCP 2222 (the sish tunnel ingress your clients connect to), and TCP 80 and TCP 443 (the HTTP and HTTPS tunnel routers your public URLs are served on)

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for a personal or small-team tunnel server. sish is a lightweight Go daemon, so larger sizes are only needed for very high concurrent tunnel throughput.

1

Deploy from the Azure Portal

Search for sish in the Marketplace, select the SecureAnyCloud publisher and click Create. Configure the Network Security Group to allow TCP 2222 (tunnel ingress) and TCP 80 and TCP 443 (the public HTTP and HTTPS routers) from wherever your clients and users are. Also allow TCP 22 for administration.

2

Deploy from the Azure CLI

RG="sish-prod"; LOCATION="eastus"; VM_NAME="sish1" IMAGE_URN="sac1647283583153:sish-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:sish-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 2222 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1002
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 443 --priority 1003
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1004
3

First boot: retrieve your tunnel domain and authorized key

On first boot, the image generates a unique SSH host identity for the server, a unique authorized tunnel key for you and a per-instance TLS certificate. It resolves this VM's public IP, renders /etc/sish/config.yml with a per-instance <public-ip>.sslip.io tunnel domain, and starts sish. This completes within seconds. Connect over SSH as azureuser and read the credentials:

sudo cat /root/sish-credentials.txt

The file records your per-instance sish.domain (the tunnel domain your public URLs are subdomains of), the sish.ssh_ingress_port (2222), and sish.tunnel_key_path, the path to your private tunnel key on the server (/root/sish-tunnel-key). Copy that key to any machine you want to open tunnels from. Keep it private, because anyone who has it can open tunnels through your server.

4

Confirm the server is running

Confirm that sish.service is active, that sish --version reports 2.23.0, and that ss shows the server listening on :2222 for the tunnel ingress and on :80 and :443 for the HTTP and HTTPS routers. The standard SSH management service stays on :22.

systemctl is-active sish.service /opt/sish/sish --version | head -3 sudo ss -tlnp | grep -E ':2222|:80 |:443|:22 ' | awk '{print $1, $4}'
5

Open your first tunnel

To publish a local service, run an ssh remote forward from the machine the service runs on. Use your tunnel key and point at your server's tunnel domain. For an HTTP app on local port 8080, request a subdomain (myapp here):

ssh -p 2222 -i sish-tunnel-key -R myapp:80:localhost:8080 <your-domain>

sish prints the public URLs your app is now reachable at: http://myapp.<your-domain> and https://myapp.<your-domain>. Replace <your-domain> with the sish.domain value from your credentials file. Replace sish-tunnel-key with the copy of your private tunnel key. Leave the command running for as long as you want the tunnel open.

You can also forward a raw TCP service with -R 0:localhost:<port> (sish assigns a public port) or create a private alias reachable only through authenticated SSH.

6

Prove a tunnel round-trips: run the self-test

The image ships a tunnel self-test. It starts a small local HTTP service, opens an authenticated tunnel through sish, fetches the assigned public URL and confirms that the local service's response comes back through the tunnel. Everything is self-contained on this one VM, with no external client required. The test also proves that an unauthenticated tunnel attempt is rejected.

sudo bash /opt/sish/tunnel-selftest.sh

The test prints SISH_SELFTEST_OK when the round trip succeeds and the unauthenticated attempt is correctly refused.

7

Authorize more clients

sish watches its authorized keys directory and reloads it automatically. To let a teammate open tunnels, copy their SSH public key onto the server and place it in /etc/sish/pubkeys/:

scp teammate.pub azureuser@<public-ip>:/tmp/
sudo install -m 0640 /tmp/teammate.pub /etc/sish/pubkeys/teammate.pub

sish picks up the new key within a second, and no restart is needed. Remove a key from that directory to revoke access just as quickly.

8

Secure by default

This image ships with no known credentials. Authentication is forced on in /etc/sish/config.yml, and the authorized key list is generated per VM at first boot and stored root-only, so only keys you authorize may open a tunnel. The tunnel ingress on :2222 is kept separate from the management SSH service on :22.

grep -E '^authentication:|^ssh-address:|^domain:' /etc/sish/config.yml
sudo ls -1 /etc/sish/pubkeys/
9

Use your own domain and Let's Encrypt

The default tunnel domain is <public-ip>.sslip.io, which resolves out of the box. To use your own domain, point a wildcard DNS record (for example *.tunnels.example.com) at this VM's public IP. Then set your domain and enable on-demand Let's Encrypt certificates for browser-trusted HTTPS by editing /etc/sish/config.yml:

# set your domain and enable Let's Encrypt (browser trusted HTTPS), then restart sish # edit /etc/sish/config.yml on the server: domain: "tunnels.<your-domain>" # add: https-ondemand-certificate: true and https-ondemand-certificate-accept-terms: true sudo systemctl restart sish.service

With a real wildcard record and on-demand certificates, every new subdomain gets a valid certificate automatically the first time it is requested.

Troubleshooting

A client cannot connect to the ingress. Confirm that the NSG allows TCP 2222 from the client and that the client uses the correct private tunnel key. Check the server logs with sudo journalctl -u sish -n 50.

A tunnel URL returns nothing. Confirm that the NSG allows TCP 80 and TCP 443, that the ssh -R tunnel is still running on the client, and that the local service it points at is up. The sish.domain in the URL must match your server's configured domain.

Check server health. sudo systemctl status sish and sudo journalctl -u sish show service logs. sudo /opt/sish/tunnel-selftest.sh proves the full round trip end to end on the server itself.

Support

SecureAnyCloud provides 24/7 technical support for this sish image. Our engineers help with pointing a wildcard domain at the server, enabling Let's Encrypt, authorizing additional users, configuring HTTP, TCP, TLS and alias tunnels, tuning binding and rate-limiting policies, firewall and NSG rules, and sish version upgrades. Critical issues receive a one-hour average response time. Contact sales@secureanycloud.com.

All product and company names are trademarks or registered trademarks of their respective holders. Use of these names does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch sish 2.23.0 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure