PostgreSQL's log location is not fixed — it depends on three settings: log_destination, logging_collector, and log_directory. On Debian and Ubuntu the package enables file logging at /var/log/postgresql/postgresql-<version>-<cluster>.log. On RHEL and CentOS the logging collector writes to the log/ subdirectory inside the data directory, typically /var/lib/pgsql/<version>/data/log/. When logging_collector is off and log_destination is stderr (the upstream default and the Docker default), output goes to the process's stderr — captured by the systemd journal or by docker logs.
Quick Reference: PostgreSQL Log File Paths
| Platform / Install method | Default log location |
|---|---|
| Ubuntu / Debian (apt) | /var/log/postgresql/postgresql-<ver>-<cluster>.log |
| RHEL / CentOS / Fedora (dnf) | /var/lib/pgsql/<ver>/data/log/ |
| PGDG repo (RHEL) | /var/lib/pgsql/<ver>/data/log/ |
| Amazon Linux | /var/lib/pgsql/data/log/ |
| Homebrew (macOS, Apple Silicon) | /opt/homebrew/var/log/postgresql@<ver>.log |
| Homebrew (macOS, Intel) | /usr/local/var/log/postgres.log |
Docker (official postgres) | stderr (docker logs) |
| Upstream default (no collector) | stderr → systemd journal (journalctl -u postgresql) |
| Data directory (relative) | <data_directory>/log/ when log_directory = 'log' |
How to View and Tail PostgreSQL Logs
On Debian/Ubuntu, find and tail the current file:
sudo tail -f /var/log/postgresql/postgresql-*.log
When using the systemd journal:
sudo journalctl -u postgresql -f
sudo journalctl -u postgresql@16-main -f # versioned unit
Ask PostgreSQL for the exact active file:
SELECT pg_current_logfile();
Grep for errors and fatals:
sudo grep -E 'ERROR|FATAL|PANIC' /var/log/postgresql/postgresql-*.log
In Docker:
docker logs -f <container>
Finding the Exact Path When It Varies
The authoritative answer comes from the running server:
SHOW log_destination; -- stderr, csvlog, jsonlog, syslog (or a combination)
SHOW logging_collector; -- on means PostgreSQL manages log files itself
SHOW data_directory; -- e.g. /var/lib/pgsql/16/data
SHOW log_directory; -- absolute, or relative to data_directory
SHOW log_filename; -- e.g. postgresql-%Y-%m-%d_%H%M%S.log
If logging_collector is on, the file lives at log_directory (joined to data_directory when relative). If it's off and log_destination is stderr, look in the journal or docker logs.
Ubuntu / Debian Detail
Debian uses a cluster system. Config lives at /etc/postgresql/<version>/<cluster>/postgresql.conf, the data directory at /var/lib/postgresql/<version>/<cluster>, and logs at /var/log/postgresql/. The package ships with logging_collector effectively redirecting to those files. Edit settings, then reload or restart:
sudo -u postgres psql -c "SELECT pg_reload_conf();"
sudo systemctl restart postgresql@16-main # for changes requiring restart
RHEL / CentOS / Fedora Detail
Config and data both live under /var/lib/pgsql/<version>/data/, with logs in the log/ subdirectory. The unit is postgresql-<version>. SELinux confines the postgres process, so relocating logs outside the data directory needs a matching file context (postgresql_log_t).
Docker Detail
The official postgres image logs to stderr, so docker logs <container> is the default way to read them and there is no file inside the container. To write files, mount a volume and pass logging flags:
docker run -d --name pg \
-v /host/pglog:/var/log/postgresql \
-e POSTGRES_PASSWORD=secret postgres \
-c logging_collector=on \
-c log_directory=/var/log/postgresql \
-c log_filename=postgresql.log
Changing the Log Location and Verbosity
Key parameters in postgresql.conf:
log_destination = 'stderr' # or 'csvlog', 'jsonlog', combine with commas
logging_collector = on # required for PostgreSQL-managed files (needs restart)
log_directory = 'log' # relative to data_directory, or absolute
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_min_duration_statement = 250 # log queries slower than 250 ms
log_line_prefix = '%m [%p] %q%u@%d ' # timestamp, pid, user@db
log_statement = 'ddl' # none, ddl, mod, or all
logging_collector requires a full restart. Most other logging parameters take effect with SELECT pg_reload_conf();.
Log Rotation
PostgreSQL's built-in collector rotates on its own when log_rotation_age (default 1d) or log_rotation_size (default 10MB) is reached, naming files via log_filename patterns. With log_truncate_on_rotation = on plus a time-based log_filename (e.g. postgresql-%a.log for day-of-week), it cycles through a fixed weekly set. On Debian, an external rotation also exists at /etc/logrotate.d/postgresql-common:
sudo logrotate -f /etc/logrotate.d/postgresql-common
Use either the built-in collector rotation or logrotate — not both on the same files.
Common Errors You'll Find in PostgreSQL Logs
FATAL: password authentication failed for user "x"— wrong password or apg_hba.confrule usingmd5/scramthe client can't satisfy.FATAL: no pg_hba.conf entry for host "1.2.3.4"— the client IP/database/user combo isn't allowed; add a rule and reload.ERROR: relation "foo" does not exist— wrong schema/search_path or the table truly is missing.FATAL: sorry, too many clients already— connections hitmax_connections; add pooling (PgBouncer) or raise the limit.could not extend file ... No space left on device— the data volume is full; free space or grow the disk before the DB stops accepting writes.deadlock detected— two transactions blocked each other; PostgreSQL aborted one. Review the logged statements to fix lock ordering.
Troubleshooting: Logs Missing or Empty
- Collector off — with
logging_collector = off, there is no file; checkjournalctl -u postgresqlordocker logs. - Wrong directory —
log_directorymay be relative todata_directory; resolve it withSHOW data_directory;+SHOW log_directory;, or justSELECT pg_current_logfile();. - Verbosity too low —
log_min_messages/log_statementmay be filtering out what you expect; raise them andpg_reload_conf(). - Permissions — files in the data directory are owned by the
postgresuser (mode 600); usesudo -u postgresor root. - Server won't start — startup failures (bad config, port in use) appear in the journal even when file logging is configured, because the collector isn't running yet.
- Docker — no file inside the image unless you enabled the collector and mounted a volume; otherwise use
docker logs.