Use Synous
Use OpenSSH to give your local service a temporary public HTTPS URL. You don’t need to install a client.
Create a public URL
-
Start your local service. This example uses
localhost:8080. -
Connect to Synous.
ssh -T -R 80:localhost:8080 t.synous.dev -
If SSH prints an authorization link, open it and sign in with GitHub. A connection without a key can be allowed once. An unknown key can be allowed once, for 24 hours, for 30 days, or forever.
-
Open the printed public URL. Keep SSH connected while you use the route.
Public: https://otter-lake.synous.dev Press Ctrl-C to stop.
Anyone who knows the active URL can send requests to it unless the route is private. A private route requires sign-in.
Authentication
Synous associates every tunnel with a GitHub account and chooses the authentication path automatically:
- A recognized key connects immediately.
- An unknown key prints a short-lived browser link. The authorization page shows the key fingerprint, client, source IP, and expiration before you choose Once, 24 hours, 30 days, Forever, or Deny.
- If no public key is offered, stock SSH uses keyboard-interactive browser approval. It asks no questions and prints No client identity was offered, an authorization link, and Waiting for approval…. You can choose Allow once or Deny.
The Once choice applies only to the waiting connection. The other choices save an offered key for that account until their expiration, and Forever keeps it until it is revoked. A no-key approval cannot be saved; reconnecting requires another approval.
To explicitly connect without offering a public-key identity:
ssh -T -o PubkeyAuthentication=no \
-o PreferredAuthentications=keyboard-interactive \
-R 80:localhost:8080 t.synous.devYou can also authenticate directly with a key already registered to GitHub by including your GitHub username:
ssh -T -R 80:localhost:8080 GITHUB_USERNAME@t.synous.dev- Add the public key to GitHub under SSH and GPG keys.
- Keep your private key on your computer. OpenSSH doesn’t send it to Synous.
- Allow up to five minutes for a GitHub key addition or removal to affect a new connection. Removing a key doesn’t close an existing tunnel.
If OpenSSH offers the wrong key, select the key explicitly:
ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes -T \
-R 80:localhost:8080 GITHUB_USERNAME@t.synous.devIf an environment needs a disposable conventional identity, this one-liner creates an Ed25519 key in a temporary directory, uses it for the tunnel, and deletes it when SSH exits:
d=$(mktemp -d); trap 'rm -rf "$d"' EXIT; ssh-keygen -q -t ed25519 -N '' -f "$d/key"; ssh -T -i "$d/key" -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -R 80:localhost:8080 t.synous.devFor unattended keyless automation, sign in to the dashboard and create a single-use syn_... credential. Put that credential before @t.synous.dev in the SSH command. It is a bearer secret, expires after 10 minutes, and is consumed when SSH connects.
SSH session
When you connect from a terminal, Synous shows an interactive view of the public URL and recent requests. Press q or Ctrl-C to disconnect. Without an allocated terminal, Synous prints the same information as line-oriented output.
Pass options to the connect command, which runs by default:
| Option | Effect |
|---|---|
--name NAME | Use the stable hostname NAME-<github-user>.synous.dev. NAME is 1 to 23 letters or digits. |
--new | Draw a new hostname instead of resuming a held one. |
--private | Allow only your GitHub account to open the route. |
--allow LOGIN,... | Also allow these GitHub logins. This option implies --private and is repeatable. |
--auth USER:PASSWORD | Also allow one HTTP Basic credential. This option implies --private. |
--quiet | Hide per-request access log lines from the SSH output. The dashboard still records recent requests. |
ssh -T -R 80:localhost:8080 t.synous.dev connect --name api --private --quietWrite connect before the options. The word stops the local ssh client from reading the options as its own, and ssh -T -R 80:localhost:8080 t.synous.dev alone still runs connect.
Run ssh t.synous.dev help to list SSH session options. The help command doesn’t require a remote forward. A client that opens no session, such as ssh -N, can’t pass options. It receives a hostname that you can see only in the dashboard.
Private routes
Routes are public by default. Add an access option to the connect command:
ssh -T -R 80:localhost:8080 t.synous.dev connect --private
ssh -T -R 80:localhost:8080 t.synous.dev connect --allow alice,bob
ssh -T -R 80:localhost:8080 t.synous.dev connect --auth demo:demo-password--private allows only the route owner. --allow LOGIN,... also allows the listed GitHub logins. The owner is always allowed. --allow is repeatable.
--auth USER:PASSWORD also allows one HTTP Basic credential. The password appears in your shell history and can appear in the process list. Use --auth for demos, not for secrets.
When a browser opens a private route, Synous shows a page with a Sign in with GitHub button. After sign-in, Synous returns the browser to the original route and path. The route session lasts for 12 hours or until the route ends.
Your local service receives these headers on an authenticated private-route request:
X-Synous-Usercontains the GitHub login or Basic username.X-Synous-Authcontainsgithuborbasic.
Synous removes the Basic Authorization header that authenticates a request before it proxies the request. Other Authorization headers pass through unchanged. Synous reserves /.synous-basic and the /.synous/ path prefix for sign-in on private routes. A public route receives these paths unchanged.
Backend protocols
Choose the remote-forward port based on how your local service accepts traffic. Synous supports only remote ports 80 and 443.
| Local service | Remote forward | Backend connection |
|---|---|---|
| HTTP or WebSocket | -R 80:localhost:8080 |
Cleartext HTTP |
| HTTPS or secure WebSocket | -R 443:localhost:8443 |
TLS with support for self-signed certificates |
Synous supports HTTP/1.1, HTTP/2, streaming, server-sent events, WebSockets, protocol upgrades, and gRPC. Use remote port 80 for a cleartext gRPC backend and port 443 for a TLS gRPC backend.
Request data
Your local service receives the public host, path, and standard X-Forwarded-* headers. Synous also sets these protected headers:
X-Synous-Remote-IPcontains the public client IP address.X-Synous-Request-Startcontains the UTC request start time.X-Synous-Forwarded-Hostcontains the public hostname.X-Synous-Forwarded-Protocontainshttps.X-Synous-Usercontains the GitHub login or Basic username for an authenticated private-route request.X-Synous-Authcontainsgithuborbasicfor an authenticated private-route request.
Synous removes client-supplied X-Synous-* headers before it adds trusted values.
The dashboard keeps up to 100 completed request records for each active route. A record includes the method, URI including the query string, client IP address, status, duration, and byte counts. It doesn’t include headers or bodies.
Route lifetime
- Each SSH connection gets one public hostname.
- The route ends when SSH disconnects. Synous then holds the hostname for 10 minutes for the same GitHub account and SSH key fingerprint.
- Reconnect within 10 minutes to resume the hostname. Synous prints
(resumed)after the public URL. A connection without a key resumes only a hostname that was held without a key. - Use
--nameto give each tunnel a stable hostname if more than one hostname is held for you. Without it, Synous draws a new hostname and lists the held ones. - Add
--newto draw a new hostname instead of resuming one. --name NAMEgives the stable hostnameNAME-<github-user>.synous.dev. No other account can receive it. A second connection with the same name is refused while the first one is active.- A hostname returns to the pool 10 minutes after its connection ends, and Synous might assign it to another account later.
- Live counters and recent request records clear when the route ends.
- A client that opens no session, such as
ssh -N, receives a hostname that you can see only in the dashboard.
Keep secrets out of request paths and query strings. For more information about data handling, see the Synous privacy policy.
Errors
| Status | Meaning | Action |
|---|---|---|
404 | The route isn’t active. | Check the SSH connection and use the latest URL. |
502 | The local service didn’t accept the connection. | Check the local port and backend protocol. |
503 | Synous is temporarily at capacity. | Retry after the interval in Retry-After. |
504 | The local forwarding stream timed out. | Check the SSH client and local service, and then retry. |
A route supports 16 active requests by default. A long-lived stream or WebSocket uses one slot until it closes.