Skip to main content
DevOpsintermediate

Where Are PostgreSQL Logs Stored? Default Paths (Ubuntu, CentOS, Docker)

PostgreSQL logs live at /var/log/postgresql/ on Debian, or in the data directory's log/ folder on RHEL. Find the exact path with SHOW data_directory and log_directory, plus how to tail and rotate.

9 min readUpdated June 2026

Want us to handle this for you?

Get expert help →

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 methodDefault 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 a pg_hba.conf rule using md5/scram the 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 hit max_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; check journalctl -u postgresql or docker logs.
  • Wrong directorylog_directory may be relative to data_directory; resolve it with SHOW data_directory; + SHOW log_directory;, or just SELECT pg_current_logfile();.
  • Verbosity too lowlog_min_messages/log_statement may be filtering out what you expect; raise them and pg_reload_conf().
  • Permissions — files in the data directory are owned by the postgres user (mode 600); use sudo -u postgres or 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.

Frequently Asked Questions

Find answers to common questions

On Debian and Ubuntu, logs go to /var/log/postgresql/postgresql--.log. On RHEL and CentOS, the logging collector writes to the log/ subdirectory of the data directory, typically /var/lib/pgsql//data/log/. The actual path depends on log_destination, logging_collector, and log_directory settings.

Connect with psql and run SHOW log_destination; SHOW logging_collector; SHOW data_directory; and SHOW log_directory;. If logging_collector is off and log_destination is stderr, output goes wherever the service was started, usually the systemd journal. Run SELECT pg_current_logfile(); to get the active file directly.

When logging_collector is off and log_destination is stderr, PostgreSQL writes to its standard error, which systemd captures in the journal. Read it with journalctl -u postgresql. To get dedicated log files instead, set logging_collector = on and restart the server.

The official postgres image logs to stderr by default, so docker logs shows them and there is no log file inside the container. To write files instead, mount a volume and set logging_collector = on plus log_directory in postgresql.conf or via command flags.

Set log_statement = 'all' to log every statement, or log_min_duration_statement = 250 to log only queries slower than 250 ms. Apply with SELECT pg_reload_conf(); for parameters that allow reload. Heavy query logging is verbose, so prefer log_min_duration_statement in production.

Need help shipping something?

Productized MVP development for founders. 8 SaaS apps shipped — yours could be next, in 6 weeks.