PgDeck

Connect to remote PostgreSQL

Connecting to a remote PostgreSQL server.

Remote connection failures fall into four buckets, and the error message tells you which one you are in. Reading it before changing anything saves most of the time people spend on this.

Short answer: A timeout means packets are being dropped: a firewall or security group. Connection refused means you reached the host but nothing is listening on that port, usually listen_addresses. A pg_hba error means the network is fine and only the access rule needs changing. For production, prefer an SSH tunnel over opening port 5432 at all.

PgDeck PostgreSQL desktop client with schema navigation, table filtering, row editing, and SQL tools

Why developers use PgDeck

PgDeck is shaped around PostgreSQL tasks that happen every day: connect, inspect, filter, edit, query, manage structure, copy, and export.

Timeout means firewall; refused means nothing is listening
listen_addresses needs a restart, pg_hba.conf only a reload
pg_hba rules are first-match-wins, read top to bottom
Never use the trust method on a network-reachable server
An SSH tunnel keeps port 5432 closed entirely

Secure connections

Save PostgreSQL connection details with encrypted passwords, SSL settings, URL import, testing, search, edit, and delete actions.

Schema and data grid

Browse schemas and tables, search the table list, pin favorites, filter rows, sort columns, resize columns, and paginate results.

SQL workspace

Run SELECT and non-SELECT statements from multi-tab SQL editors with syntax highlighting and interactive query results.

Staged editing

Edit cells, add rows, duplicate rows, set NULL, stage deletes, review pending changes, and commit everything in one transaction.

How to connect to a remote PostgreSQL database

  1. Read the error first

    These three errors point at three different layers, and fixing the wrong one wastes an afternoon. A hang then timeout is a dropped packet — firewall. An immediate refusal is nothing listening — listen_addresses or the wrong port. A message naming pg_hba.conf means you connected successfully and only the access rule is missing.

    # Is anything listening at all?
    nc -zv db.example.com 5432
    
    # Or with psql, which reports the real error
    psql "postgres://user@db.example.com:5432/mydb"
  2. Make the server listen beyond localhost

    By default PostgreSQL binds only to localhost, so remote connections are refused immediately no matter what the firewall allows. listen_addresses changes that. This one requires a full restart — a reload is not enough.

    # postgresql.conf
    listen_addresses = '*'          # or a specific interface IP
    
    sudo systemctl restart postgresql
  3. Add a pg_hba.conf rule

    pg_hba.conf decides who may connect from where and how they authenticate. Rules are read top to bottom and the first match wins. Use scram-sha-256, never trust — trust accepts any connection with no password at all. Restrict the source range as tightly as you can; a /32 for a single host is ideal.

    # pg_hba.conf — hostssl also requires encryption
    # TYPE     DATABASE  USER  ADDRESS          METHOD
    hostssl    mydb      app   203.0.113.7/32   scram-sha-256
    
    SELECT pg_reload_conf();   -- pg_hba.conf needs only a reload
  4. Open the firewall to specific sources only

    On a cloud provider this is the security group; on a plain server it is ufw or firewalld. Allow only the addresses that need access. Exposing 5432 to 0.0.0.0/0 is found by automated scanners within hours and is a standing cause of database compromise.

    # Ubuntu, single source address
    sudo ufw allow from 203.0.113.7 to any port 5432 proto tcp
    
    # AWS: security group inbound rule, source = your IP, not 0.0.0.0/0
  5. Better: do not expose the port at all

    An SSH tunnel forwards a local port to the database through a host you already trust, so PostgreSQL stays bound to localhost and the firewall stays closed. Your client then connects to 127.0.0.1 and the traffic emerges on the far side. This is the right default for production.

    # Forward local 5433 to the database, via the bastion
    ssh -L 5433:localhost:5432 user@bastion.example.com
    
    # Then point the client at:
    postgres://user:password@127.0.0.1:5433/mydb
  6. Or let the client manage the tunnel

    Keeping an ssh -L command alive in a terminal works but is easy to lose. Clients with built-in SSH tunnel support open and maintain it as part of the saved connection. PgDeck includes SSH tunnels in the Pro plan, which is the usual way to reach a private RDS instance behind a bastion.

The four layers, in order

Network reachability, then a listening socket, then the host-based access rule, then the password. Each produces a distinct error, and they must be fixed in that order — there is no point adding a pg_hba rule while a security group is still dropping your packets. Work from the outside in and each step tells you whether to continue.

listen_addresses and why a reload is not enough

listen_addresses controls which network interfaces the server binds to at startup, so changing it requires a restart to take effect. pg_hba.conf is re-read on demand, so it only needs a reload. Editing listen_addresses and reloading is a common dead end: the file is correct and the server is still bound to localhost.

pg_hba.conf is first-match-wins

Rules are evaluated top to bottom and the first line matching the connection's database, user, and address is applied — even if it rejects and a later line would have accepted. A new rule added at the bottom of a file that already has a broad reject above it will never fire. Order matters more than content here.

Do not use trust, ever, on anything remote

The trust method accepts any connection matching the rule with no password whatsoever. It exists for local sockets during initial setup. On a rule covering a network address it means anyone who can reach the port owns the database. If you find trust on a host line in an existing configuration, treat it as an incident rather than a configuration preference.

Why tunnelling beats opening the port

An exposed 5432 is discovered by internet-wide scanners within hours and subjected to continuous credential attempts. An SSH tunnel means the database is not reachable from the internet at all: authentication happens at the SSH layer with keys rather than passwords, the traffic is encrypted regardless of sslmode, and there is no database port to find. The extra setup is a few lines once, or a field in a client's connection dialog.

Related PostgreSQL guides

More on choosing, comparing, and running a PostgreSQL desktop client.

How do I connect to a remote PostgreSQL database?

Set listen_addresses in postgresql.conf and restart, add a matching host or hostssl rule in pg_hba.conf and reload, then allow the port through the firewall from your specific address. For production, prefer an SSH tunnel so the port never needs to be exposed.

Why does my remote PostgreSQL connection time out?

A timeout means packets are being dropped, which is a firewall or cloud security group rather than PostgreSQL. Check that inbound TCP 5432 is allowed from your current address. If the connection is refused immediately instead, the problem is listen_addresses or the port, not the firewall.

What does "no pg_hba.conf entry for host" mean?

Good news, mostly: the network is working and you reached the server. PostgreSQL has no rule permitting your address, database, and user combination. Add a host or hostssl line with scram-sha-256 and reload. Remember rules are first-match-wins, so placement in the file matters.

Do I need to restart PostgreSQL after changing pg_hba.conf?

No, a reload is enough — SELECT pg_reload_conf() or systemctl reload postgresql. Changing listen_addresses in postgresql.conf does require a full restart, which is a common reason the change appears to have no effect.

Is it safe to expose PostgreSQL on port 5432?

Not to the open internet. Exposed database ports are found by automated scanners within hours and attract continuous credential attempts. Restrict the source to specific addresses at minimum, and preferably keep the port closed and reach the database through an SSH tunnel or a bastion host.