Keep the psql Password Off the Command Line with .pgpass
Keep a password out of the command line with a .pgpass file in the form host:port:database:user:password. libpq ignores it when group or others can read it.
A script connects to PostgreSQL often and you do not want the password in the command or in the environment.
docker network create pgnet > /dev/null
docker run -d --name pgpass --network pgnet -e POSTGRES_PASSWORD=pw postgres:17-alpine > /dev/null
until [ "$(docker logs pgpass 2>&1 | grep -c 'ready to accept connections')" -ge 2 ]; do sleep 1; done
docker exec pgpass psql -U postgres -qc "create role app login password 'p@ss'"
docker run --rm --network pgnet postgres:17-alpine sh -c '
echo "pgpass:5432:postgres:app:p@ss" > /tmp/pgpass
chmod 644 /tmp/pgpass
PGPASSFILE=/tmp/pgpass psql -w -h pgpass -U app postgres -tAc "select current_user" 2>&1 | sed "s/ (172[0-9.]*)//"
chmod 600 /tmp/pgpass
PGPASSFILE=/tmp/pgpass psql -w -h pgpass -U app postgres -tAc "select current_user" 2>&1
'
docker rm -f pgpass > /dev/null
docker network rm pgnet > /dev/nullWARNING: password file "/tmp/pgpass" has group or world access; permissions should be u=rw (0600) or less
psql: error: connection to server at "pgpass", port 5432 failed: fe_sendauth: no password supplied
appEach line of ~/.pgpass holds hostname:port:database:username:password, and the first line that matches the connection is used. libpq refuses a file with group or world access: the run with mode 644 printed password file ... has group or world access and then no password supplied, because -w prevents a prompt. After chmod 600 the same command connected as app. PGPASSFILE points to another location. See The Password File.
A colon or backslash inside a field must be escaped with a backslash, and a star in a field matches anything. The file is not checked on Windows, which has its own location. Use -w in scripts, so a missing entry fails at once rather than waiting for a prompt that nobody sees. This run used PostgreSQL 17.