SSH local publisher — expose local services via reverse tunnels + Caddy
sshoyu <subdomain> <localport>-R <remoteport>:<local-ip>:<localport>Run on any machine to install the sshoyu client:
curl -fsSL http://abreudenis.com/install.sh | sh
This will:
sshoyu to /usr/local/bin/sshoyu~/.ssh/sshoyu_id_ed25519sshoyu <subdomain> <localport>
# Expose a local web app on port 3000
sshoyu myapp 3000
# → https://myapp.abreudenis.com
# Expose Portainer on port 9443
sshoyu portainer 9443
# → https://portainer.abreudenis.com
# Expose a plain HTTP service on port 80
sshoyu site 80
# → https://site.abreudenis.com
Press Ctrl+C to close the tunnel. The subdomain is removed from Caddy immediately.
SSHOYU_KEY=~/.ssh/other_key sshoyu myapp 3000
*.abreudenis.com to your server's IPwget https://github.com/abreudenis83/sshoyu/releases/latest/download/sshoyu-server_<version>_all.deb
sudo dpkg -i sshoyu-server_<version>_all.deb
During installation you will be asked for:
| Question | Description | Default |
|---|---|---|
| SSH hostname | Public hostname clients will connect to | — |
| SSH port | Port sshd listens on for sshoyu connections | 22 |
| SSH user | System user created for tunnel connections | sshoyu |
sudo dpkg-reconfigure sshoyu-server
# Remove package (keeps config and user)
sudo dpkg -r sshoyu-server
# Remove everything including config and user
sudo dpkg --purge sshoyu-server
# Authorize a new client key
sudo sshoyu --add-key "ssh-ed25519 AAAA... user@host"
# List all authorized keys
sudo sshoyu --list-keys
# Revoke a client key
sudo sshoyu --remove-key "ssh-ed25519 AAAA... user@host"
# List active tunnels
sudo sshoyu --list-tunnels
# Close a specific tunnel
sudo sshoyu --close-tunnel <subdomain>
The package installs a systemd service (sshoyu-monitor) that runs every 15 seconds and removes stale Caddyfile blocks when tunnels die.
systemctl status sshoyu-monitor
journalctl -u sshoyu-monitor -f
/etc/sshoyu/sshoyu.conf (server-side):
SSH_HOST=your-domain.com
SSH_PORT=22
SSH_USER=sshoyu
CADDYFILE_PATH=/etc/caddy/Caddyfile
MIN_REMOTE_PORT=3000
LOCK_FILE_DIR=/tmp