PostgreSQL intentionally refuses to run as the root user for security reasons. Switch to an unprivileged user (typically postgres) to start the database server successfully.
PostgreSQL enforces a critical security policy by refusing to execute as the root user. When you attempt to run pg_ctl, initdb, or the postmaster daemon as root, PostgreSQL detects this and immediately halts, returning the error "pg_ctl: cannot be run as root." This is not a bug or limitation—it is a deliberate design choice. Running a database server with root privileges creates a severe security vulnerability: if an attacker compromises PostgreSQL, they gain complete control over your entire system, including access to all files, user accounts, and system resources. PostgreSQL must be run by an unprivileged operating system user (conventionally named "postgres") to contain the blast radius of any potential breach.
The safest and most common approach is to switch to the postgres user before running any PostgreSQL commands. Use the su command with the - flag to get a login shell with the postgres user's environment:
su - postgresNow you can run PostgreSQL commands without sudo:
pg_ctl start -D /var/lib/postgresql/14/main
initdb -D /path/to/data/directoryYou can verify you're running as the correct user with whoami.
If you need to run PostgreSQL commands from a non-root user account, use sudo -u postgres to execute them as the postgres user without an interactive shell:
sudo -u postgres pg_ctl start -D /var/lib/postgresql/14/main
sudo -u postgres initdb -D /path/to/data/directory
sudo -u postgres psqlThis approach is convenient for one-off commands or scripts.
To connect to a running PostgreSQL server, use the postgres user directly:
sudo -u postgres psqlAlternatively, if you're already logged in as another user, specify the user with the -U flag:
psql -U postgresDo NOT attempt to connect as the root user—PostgreSQL won't recognize a root role unless explicitly created, which is extremely unusual.
If you're running PostgreSQL in a Docker container and hitting this error, update your Dockerfile or docker-compose.yml to ensure the postgres user is used. Example Dockerfile:
USER postgres
CMD ["postgres", "-D", "/var/lib/postgresql/data"]For docker-compose.yml, ensure the container is not running as root:
services:
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: password
user: "999:999" # postgres UID:GIDAlways verify the official postgres Docker image documentation for best practices.
PostgreSQL's refusal to run as root is a well-intentioned security boundary that cannot be bypassed. Some Linux distributions (like Debian/Ubuntu) create a dedicated "postgres" system user during installation with UID typically around 999. On macOS with Homebrew, this check is similarly enforced. In containerized environments, ensure your base image or init scripts properly switch to the postgres user before launching the daemon. If you're building a custom container, avoid using root as the default user; instead, create a non-root user and use the USER directive. SELinux or AppArmor policies may add additional restrictions, so consult your security policy if you encounter permission denials even when running as postgres.
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL
ERROR 42501: must be owner of table
How to fix "must be owner of table" in PostgreSQL
trigger cannot change partition destination
How to fix "Trigger cannot change partition destination" in PostgreSQL
SSL error: certificate does not match host name
SSL error: certificate does not match host name in PostgreSQL
No SSL connection
No SSL connection to PostgreSQL