Use tunnel user's keys on ingress.nixc.us
ci/woodpecker/push/woodpecker Pipeline was successful Details

- stack.production.yml: mount /home/tunnel/.ssh/ for host_key,
  authorized_keys, and deploy_key (tunnel user's keys on ingress.nixc.us)
- README + systemd env examples: reference tunnel user authorized_keys

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leopere 2026-02-15 19:57:54 -05:00
parent dc66cbb160
commit 29acb88398
Signed by: colin
SSH Key Fingerprint: SHA256:nRPCQTeMFLdGytxRQmPVK9VXY3/ePKQ5lGRyJhT5DY8
4 changed files with 17 additions and 14 deletions

View File

@ -37,7 +37,7 @@ ssh-keygen -t ed25519 -f keys/host_key -N ""
# Client key (for tunnel clients)
ssh-keygen -t ed25519 -f keys/id_ed25519 -N ""
# Authorize the client
# Authorize the client (install this file as the tunnel user's authorized_keys on ingress.nixc.us)
cat keys/id_ed25519.pub > keys/authorized_keys
# Deploy key for SSHing into the Traefik host
@ -109,7 +109,7 @@ docker run -d \
| `PORT_RANGE_START` | First allocatable tunnel port | `10000` |
| `PORT_RANGE_END` | Last allocatable tunnel port | `10100` |
| `SSH_HOST_KEY` | Path to SSH host private key | `/keys/host_key` |
| `AUTHORIZED_KEYS` | Path to authorized_keys file | `/keys/authorized_keys` |
| `AUTHORIZED_KEYS` | Path to authorized_keys file (tunnel users keys from ingress.nixc.us) | `/keys/authorized_keys` |
| `TRAEFIK_SSH_HOST` | Traefik host to SSH into **(required)** | - |
| `TRAEFIK_SSH_USER` | SSH user on the Traefik host | `root` |
| `TRAEFIK_SSH_KEY` | SSH key for Traefik host (path or PEM) **(required)** | - |
@ -164,7 +164,7 @@ docker build --target client -t tunnel-client . # client image
The repo ships compiled `tunnel-server` and `tunnel-client` for remote hosts that run without Docker. Use the included systemd units under `systemd/`.
**Keys:** Do not reuse the hosts SSH keys or share one key between hosts or tunnels. Generate a dedicated ed25519 key per tunnel (or per host). The **central tunnel server** must have that keys **public** half in its `authorized_keys` so the client can connect.
**Keys:** Do not reuse the hosts SSH keys or share one key between hosts or tunnels. Generate a dedicated ed25519 key per tunnel (or per host). Add that keys **public** half to the **tunnel** users `authorized_keys` on **ingress.nixc.us** (the reverse tunnel server).
**Multiple tunnels:** Run one systemd instance per tunnel (different env file and optional unit name), e.g. `tunnel-client@app1.service` and `tunnel-client@app2.service` each with their own env and key.
@ -184,9 +184,9 @@ Then add a dedicated key for this tunnel, env file, and authorize on the server:
```bash
sudo mkdir -p /etc/tunnel-client
sudo ssh-keygen -t ed25519 -f /etc/tunnel-client/id_ed25519 -N ""
# Add the public key to the central server's authorized_keys:
# Add the public key to the tunnel user's authorized_keys on ingress.nixc.us:
sudo cat /etc/tunnel-client/id_ed25519.pub
# (On the central server: append that line to authorized_keys)
# On ingress.nixc.us as tunnel user: append that line to ~tunnel/.ssh/authorized_keys
sudo cp systemd/tunnel-client.env.example /etc/tunnel-client.env # or curl from $REPO/systemd/tunnel-client.env.example
sudo edit /etc/tunnel-client.env # set TUNNEL_SERVER, TUNNEL_DOMAIN, TUNNEL_KEY=/etc/tunnel-client/id_ed25519
sudo systemctl daemon-reload && sudo systemctl enable --now tunnel-client
@ -208,7 +208,7 @@ sudo systemctl daemon-reload && sudo systemctl enable --now tunnel-client
sudo edit /etc/tunnel-client.env # set TUNNEL_SERVER, TUNNEL_DOMAIN, TUNNEL_KEY
```
3. Use a **dedicated** ed25519 key for this tunnel (not the hosts keys). Put the private key on the host (e.g. `/etc/tunnel-client/id_ed25519`) and set `TUNNEL_KEY` in env. Ensure the **central server** has the matching **public** key in its `authorized_keys`.
3. Use a **dedicated** ed25519 key for this tunnel (not the hosts keys). Put the private key on the host (e.g. `/etc/tunnel-client/id_ed25519`) and set `TUNNEL_KEY` in env. Add the matching **public** key to the **tunnel** users `~/.ssh/authorized_keys` on **ingress.nixc.us**.
4. Enable and start:
@ -224,13 +224,13 @@ For a second tunnel on the same host, use a separate env and key (e.g. `/etc/tun
If you run the tunnel server without Docker:
1. Install binary and keys under e.g. `/etc/tunnel-server/` (host_key, authorized_keys, traefik_deploy_key).
1. Install binary and keys under e.g. `/etc/tunnel-server/` (host_key, authorized_keys from the tunnel user on ingress.nixc.us, traefik_deploy_key).
2. Copy `systemd/tunnel-server.service` to `/etc/systemd/system/` and `systemd/tunnel-server.env.example` to `/etc/tunnel-server.env`. Set `TRAEFIK_SSH_HOST`, `TRAEFIK_SSH_KEY`, and paths to keys.
3. `systemctl enable --now tunnel-server`.
## Security Notes
- Only clients whose public keys are in `authorized_keys` can connect
- Only clients whose public keys are in the tunnel users `authorized_keys` on ingress.nixc.us can connect
- The server uses a stable host key for client verification
- SSH tunnels encrypt all traffic between client and server
- The server authenticates to the Traefik host with a separate deploy key

View File

@ -23,10 +23,11 @@ services:
TASK_ID: "{{.Task.ID}}"
ENVIRONMENT: "production"
volumes:
- /root/.ssh/tunnel_host_key:/keys/host_key:ro
- /root/.ssh/authorized_keys:/keys/authorized_keys:ro
- /root/.ssh/ca-userkey:/keys/deploy_key:ro
- /root/.ssh/ca-userkey-cert.pub:/keys/deploy_key-cert.pub:ro
# Tunnel user's keys on ingress.nixc.us (clients connect here; authorized_keys = tunnel user's)
- /home/tunnel/.ssh/tunnel_host_key:/keys/host_key:ro
- /home/tunnel/.ssh/authorized_keys:/keys/authorized_keys:ro
- /home/tunnel/.ssh/ca-userkey:/keys/deploy_key:ro
- /home/tunnel/.ssh/ca-userkey-cert.pub:/keys/deploy_key-cert.pub:ro
ports:
- target: 2222
published: 2222

View File

@ -1,9 +1,11 @@
# Copy to /etc/tunnel-client.env and set values.
# Required:
TUNNEL_SERVER=ingress.example.com:2222
TUNNEL_SERVER=ingress.nixc.us:2222
TUNNEL_DOMAIN=myapp.example.com
TUNNEL_KEY=/etc/tunnel-client/id_ed25519
# Add this key's public half to the tunnel user's ~/.ssh/authorized_keys on ingress.nixc.us.
# Optional (defaults shown):
# TUNNEL_PORT=8080
# TUNNEL_AUTH_USER=

View File

@ -6,7 +6,7 @@ TRAEFIK_SSH_KEY=/etc/tunnel-server/traefik_deploy_key
# Optional (defaults shown):
# SSH_PORT=2222
# SSH_HOST_KEY=/etc/tunnel-server/host_key
# AUTHORIZED_KEYS=/etc/tunnel-server/authorized_keys
# AUTHORIZED_KEYS=/etc/tunnel-server/authorized_keys (tunnel user's authorized_keys from ingress.nixc.us)
# PORT_RANGE_START=10000
# PORT_RANGE_END=10100
# TRAEFIK_SSH_USER=root