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!