Fix Vast.ai SSH problems with step-by-step tests for listening SSH, firewall rules, port mappings, blocked inbound traffic, CGNAT, and public forwarded ports.
# What public IPv4 does the internet see?
curl -4 ifconfig.me
# What is listening locally?
ss -tulpen
sudo ss -tulpen
# Test a local web/API service
curl -v http://127.0.0.1:8080
curl -v http://127.0.0.1:8000/health
# Check common Linux firewalls
sudo ufw status verbose
sudo iptables -S
sudo nft list rulesetYOUR_SETUP_TOKEN is shown after signup/trial checkout and binds the client to your assigned endpoint.
curl -fsSL https://api.needports.com/install | sudo bash -s YOUR_SETUP_TOKEN --accept-tos
sudo needports setup --dry-run
sudo needports expose custom --public-port 30000 --local-port 8080 --name "Service" --confirm --restart
curl -v http://your-needports-endpoint:30000CGNAT port forwarding, Vast.ai port forwarding, NeedPorts client commands, and NeedPorts security model.
This usually means the SSH daemon is healthy but the public network path is blocked. Confirm the daemon first, then test the public path from outside the host.
# On the host
sudo ss -tulpen | grep ':22'
systemctl status ssh || systemctl status sshd
# From another machine, not the same LAN
nc -vz your-public-host.example 22
ssh -vvv [email protected]
If local SSH is listening but the outside test times out, changing SSH keys will not fix the network path. Use a public forwarded port or fix the upstream firewall/NAT.
Docker port publishing creates a host listener; it does not guarantee public internet reachability. Check the published host port, then map that host port to an assigned NeedPorts public port.
docker ps --format 'table {{.Names}} {{.Ports}}'
ss -tulpen | grep 8080
curl -v http://127.0.0.1:8080
sudo needports expose custom --public-port 30001 --local-port 8080 --name "Docker Web UI" --confirm --restart
curl -v http://your-needports-endpoint:30001
Binding to localhost is not always a problem if the NeedPorts client runs on the same host and forwards to 127.0.0.1. It is a problem if Docker, the tunnel client, or another network namespace cannot reach the service.
# Local process bind check
ss -tulpen | grep 8000
curl -v http://127.0.0.1:8000/health
curl -v http://$(hostname -I | awk '{print $1}'):8000/health
If only localhost works, expose from the same host or adjust the service bind address intentionally. Do not bind sensitive admin panels publicly unless they have strong authentication.
$ nc -vz public-ip 8000
nc: connect to public-ip port 8000 (tcp) failed: timed out
$ curl http://127.0.0.1:8000/health
ok
$ nc -vz your-needports-endpoint 30001
Connection to your-needports-endpoint 30001 port [tcp/*] succeeded!
$ curl http://your-needports-endpoint:30001/health
ok
Start with a NeedPorts trial, map one service, and test the public port from another network before depending on it for production traffic.
Start a trialRead more guides