Avoid Unix Socket Connections with Postgres PGHOST
I had a long, meandering journey to get Postgres to properly connect. I was using an Elixir client, Postgrex, but this advice will probably apply generally. Here's how to avoid a particular problem in getting your postgres clients to connect with tcp/ip on localhost.
Defining TCP/IP
By default, if you tell your clients to use localhost
as the postgres host, they'll try to use tcp/ip. In other words, they'll connect on localhost:5432
.
There's an alternate way that a postgres client could talk to the database, and that's through unix sockets, or inter-process communication (IPC). Sometimes that can be better for performance or security.
But I wanted to connect to postgres using TCP/IP, localhost:5432. So I set up my Ecto config:
config :phx1, Phx1.Repo,
username: "postgres",
password: "postgres",
hostname: "localhost",
database: "phx1_dev",
stacktrace: true,
show_sensitive_data_on_connection_error: true,
pool_size: 10
Or sometimes I started up iex -S mix
, and would use Postgres directly (what Ecto uses as a dependency):
{:ok, pid} = Postgrex.start_link(hostname: "localhost", username: "postgres", password: "postgres", database: "postgres")
The problem is that neither worked for me.
The Error
Constantly, consistently, eternally!, i would get this:
13:05:11.485 [error] Postgrex.Protocol (#PID<0.213.0>) failed to connect: ** (DBConnection.ConnectionError) tcp connect (/tmp/.s.PGSQL.5432): no such file or directory - :enoent
Why in the world would it be trying to connect to /tmp/.s.PGSQL.5432
? That is one of the default unix socket locations for Postgres. But I was specifying localhost
-- everywhere!
Other oddities in this journey:
- Many different postgres configurations didn't work (local postgres, docker, unix sockets, shared volumes, egh)
- It also failed using other drivers, epgsql and pgo.
- It worked ok using Erlang odbc.
- It worked ok using a tiny testbed in node-postgres.
- It worked ok on a separate computer.
- It worked didn't work ok on a still another computer.
- It didn't matter whether the odbc link failed or not (after installing unixodbc-dev or odbc-postgresql) on Erlang install.
Then finally, my search for light in the darkness came to a joyful end.
The Solution
I'm not even sure what caused this to come into my mind -- probably the grace of divine intervention -- but I ran:
env | rg PG
And saw:
PGHOST=/tmp
Well. There's a connection: Postgres host specification, and in the same directory as the error specified.
Turns out that I had an old line my .zshrc
from some setup long ago:
export PGHOST=/tmp
Once I removed that line and started a new terminal session, my mix ecto.create
worked, my Postgrex.start_link
worked, and I was exultant.
That is one powerful variable that the Elixir Postgres drivers really respect!