diff --git a/.gitignore b/.gitignore index 9100277..54669ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ -# Binaries (root level only) -/tunnel-server -/tunnel-client -/server -/client - # Keys (never commit secrets) keys/ diff --git a/README.md b/README.md index be2e8b9..c4e2c51 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ http: ## Building ```bash -# Build both binaries locally +# Build both binaries locally (commit and push these for remote deployment) go build -o tunnel-server ./cmd/server/ go build -o tunnel-client ./cmd/client/ @@ -160,6 +160,75 @@ docker compose build # server image docker build --target client -t tunnel-client . # client image ``` +## Binaries and systemd (bare metal) + +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 host’s 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 key’s **public** half in its `authorized_keys` so the client can connect. + +**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. + +### Install from git.nixc.us (HTTPS raw) + +From a host with curl, install the binary and systemd unit directly from the repo (replace `main` with your branch if needed): + +```bash +REPO=https://git.nixc.us/colin/better-argo-tunnels/raw/branch/main +sudo curl -o /usr/local/bin/tunnel-client -L "$REPO/tunnel-client" +sudo chmod +x /usr/local/bin/tunnel-client +sudo curl -o /etc/systemd/system/tunnel-client.service -L "$REPO/systemd/tunnel-client.service" +``` + +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: +sudo cat /etc/tunnel-client/id_ed25519.pub +# (On the central server: append that line to 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 +``` + +### Client on a remote host (clone or copy) + +1. Install the binary (from repo clone or raw URL above): + + ```bash + sudo cp tunnel-client /usr/local/bin/ + sudo chmod +x /usr/local/bin/tunnel-client + ``` + +2. Copy the systemd unit and create env file: + + ```bash + sudo cp systemd/tunnel-client.service /etc/systemd/system/ + sudo cp systemd/tunnel-client.env.example /etc/tunnel-client.env + sudo edit /etc/tunnel-client.env # set TUNNEL_SERVER, TUNNEL_DOMAIN, TUNNEL_KEY + ``` + +3. Use a **dedicated** ed25519 key for this tunnel (not the host’s 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`. + +4. Enable and start: + + ```bash + sudo systemctl daemon-reload + sudo systemctl enable --now tunnel-client + sudo journalctl -u tunnel-client -f + ``` + +For a second tunnel on the same host, use a separate env and key (e.g. `/etc/tunnel-client-app2.env`, `/etc/tunnel-client/app2_id_ed25519`) and a second unit (e.g. copy to `tunnel-client-app2.service` with `EnvironmentFile=/etc/tunnel-client-app2.env`). + +### Server (optional, bare metal) + +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). +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 diff --git a/client b/client new file mode 100755 index 0000000..cd01ee0 Binary files /dev/null and b/client differ diff --git a/server b/server new file mode 100755 index 0000000..670d3cb Binary files /dev/null and b/server differ diff --git a/systemd/tunnel-client.env.example b/systemd/tunnel-client.env.example new file mode 100644 index 0000000..037c855 --- /dev/null +++ b/systemd/tunnel-client.env.example @@ -0,0 +1,10 @@ +# Copy to /etc/tunnel-client.env and set values. +# Required: +TUNNEL_SERVER=ingress.example.com:2222 +TUNNEL_DOMAIN=myapp.example.com +TUNNEL_KEY=/etc/tunnel-client/id_ed25519 + +# Optional (defaults shown): +# TUNNEL_PORT=8080 +# TUNNEL_AUTH_USER= +# TUNNEL_AUTH_PASS= diff --git a/systemd/tunnel-client.service b/systemd/tunnel-client.service new file mode 100644 index 0000000..f069268 --- /dev/null +++ b/systemd/tunnel-client.service @@ -0,0 +1,15 @@ +[Unit] +Description=Reverse SSH tunnel client for Traefik +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +# Load env from same directory as this unit, or override with drop-in +EnvironmentFile=-/etc/tunnel-client.env +ExecStart=/usr/local/bin/tunnel-client +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/systemd/tunnel-server.env.example b/systemd/tunnel-server.env.example new file mode 100644 index 0000000..4422e76 --- /dev/null +++ b/systemd/tunnel-server.env.example @@ -0,0 +1,15 @@ +# Copy to /etc/tunnel-server.env and set values. +# Required: +TRAEFIK_SSH_HOST=ingress.example.com +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 +# PORT_RANGE_START=10000 +# PORT_RANGE_END=10100 +# TRAEFIK_SSH_USER=root +# SWARM_SERVICE_NAME=better-argo-tunnels_tunnel-server +# TRAEFIK_ENTRYPOINT=websecure +# TRAEFIK_CERT_RESOLVER=letsencryptresolver diff --git a/systemd/tunnel-server.service b/systemd/tunnel-server.service new file mode 100644 index 0000000..e7be392 --- /dev/null +++ b/systemd/tunnel-server.service @@ -0,0 +1,14 @@ +[Unit] +Description=Reverse SSH tunnel server for Traefik +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +EnvironmentFile=-/etc/tunnel-server.env +ExecStart=/usr/local/bin/tunnel-server +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target