# Connection refused or timeout when connecting to Postgres

> Why psql, ORMs and pg_dump get ECONNREFUSED or time out against SupaHost, and how to connect through the Business SSH tunnel at 127.0.0.1:5432 instead.

Source: https://supahost.app/kb/connection-refused · Updated 2026-11-11

## What you see

One of these, from psql, an ORM, a GUI client or `pg_dump`:

```
psql: error: connection to server at "acme.supahost.space" (203.0.113.10), port 5432 failed: Connection timed out
```

```
Error: connect ECONNREFUSED 127.0.0.1:5432
```

```
channel 2: open failed: administratively prohibited: open failed
```

```
ssh: connect to host acme.supahost.space port 22: Connection timed out
```

## Why it happens

SupaHost never exposes Postgres to the internet. On every instance, port 5432 is bound to `127.0.0.1` inside the VM, so nothing outside the VM can reach it directly. Pointing a client at `acme.supahost.space:5432` or `app-one.acme.supahost.space:5432` will always time out or be refused.

The only direct route is an SSH tunnel, available on Business and Enterprise. Your SSH client forwards a local port to `127.0.0.1:5432` on the VM, and your tools connect to the local end. Each message above points to a different missing piece:

| Message | Meaning |
|---|---|
| Timeout on port 5432 | You're connecting to the public hostname. Use the tunnel. |
| `ECONNREFUSED 127.0.0.1:5432` | Nothing is listening locally: the tunnel isn't running, or it uses another local port. |
| `administratively prohibited` | The tunnel's destination isn't exactly `127.0.0.1:5432`. Keys only allow that one target, so `localhost:5432` is refused. |
| Timeout on port 22 | SSH isn't open for this instance: it isn't on Business or Enterprise, or it has no SSH key yet. |

## How to fix it

1. Add your public key in *Dashboard → your project → **Connect** tab → SSH & CLI* (field "Public key", button "Add key"). It's active within about a minute. Port 22 only opens once at least one key exists.

2. Open the tunnel in its own terminal and leave it running:

   ```bash
   ssh -N -L 5432:127.0.0.1:5432 supahost@acme.supahost.space
   ```

   The user is always `supahost`. `-N` means "forward only", so the command appears to hang. That's expected.

3. In another terminal, connect to the local end with the string from *Connect → Database → Show connection string*:

   ```bash
   psql "postgresql://postgres:<password>@127.0.0.1:5432/p_app_one" -c "select now();"
   ```

4. If local port 5432 is taken, forward another one (`-L 55432:127.0.0.1:5432`) and use port 55432 in the connection string.

5. If your client runs inside Docker on your machine, `127.0.0.1` is the container, not your laptop. Use `host.docker.internal` as the host, or run the tunnel inside the container.

6. For long-running servers, keep the tunnel up with a process supervisor or `autossh` and reconnect when it drops.

## On SupaHost

- On Builder and Pro there is no direct Postgres access. Use the Data API from your app, Studio's SQL editor for ad-hoc SQL, the MCP server's `execute_sql` for AI agents, and *Dashboard → your project → **Backups** tab* for a `pg_dump` export.
- `Permission denied (publickey)` means the key isn't on the instance yet or you used a user other than `supahost`.
- Browser, mobile and serverless apps shouldn't connect to Postgres at all. Use supabase-js against `https://app-one.acme.supahost.space`.

## Related

- [SSH access and direct Postgres](/docs/platform/ssh)
- [Connecting to your database](/docs/database/connecting)
- [Connecting directly to Postgres (psql, pg_dump, ORMs)](/kb/direct-postgres-connection)
- [FATAL: password authentication failed](/kb/password-authentication-failed)
