Linux Log Locations: Where Does Each Service Write?

A precise guide to Linux log locations: the log file paths for each service, differences between distributions, and why journald has taken over /var/log.

6 min Updated 6 Oct 2026

The service is up, the user says "it worked yesterday," and you run a tail -f /var/log/syslog that shows no new lines. The problem is that on that server, the service in question doesn't write to syslog at all. Linux log locations aren't a fixed path; they depend on the distribution, the init system, and how the service was compiled. Until you separate these three, hunting for a log file is a waste of time.

Quick map: where each service writes

On most modern distributions, this table answers 90% of searches:

ServiceUsual pathNote
Kernel and boot/var/log/kern.log or dmesgOn RHEL family in /var/log/messages
Authentication and SSH/var/log/auth.logOn CentOS/Rocky: /var/log/secure
Nginx/var/log/nginx/access.logErrors in error.log in the same folder
Apache/var/log/apache2/ or /var/log/httpd/Differs by distribution
MySQL / MariaDB/var/log/mysql/error.logOn RHEL: /var/log/mysqld.log
PostgreSQL/var/log/postgresql/Or inside the data directory
PHP-FPM/var/log/php8.2-fpm.logVersion number in the filename
Dockerjournalctl -u dockerContainer logs are elsewhere

Don't memorize this table. The systemctl status nginx command tells you on its last line where the log is, and nginx -T prints the entire config with the access_log path. It's faster than guessing.

journald vs. files: which to trust

On Ubuntu 22.04 and above, and on almost all distributions that have systemd, a large portion of logs aren't text files at all. They're stored in journal binaries, under /var/log/journal/ or /run/log/journal/. If the first folder doesn't exist, logs stay in RAM and are wiped on every reboot. This is one of the most common reasons for "my logs from yesterday are gone."

To see whether the journal writes to disk or not:

ls -d /var/log/journal
journalctl --disk-usage

If the first command errors out, it means it's not persistent. Fix it with mkdir -p /var/log/journal && systemd-journald --flush and a service restart. The default journal size on typical installs grows up to 10% of the filesystem; on a server with a 40 GB disk that's about 4 GB, which will catch you off guard one morning with df -h if you're not paying attention.

Filters that actually help

journalctl -u nginx --since "1 hour ago" is a good starting point. To see only errors, add -p err, and to follow live, add -f. If you have a PID, journalctl _PID=1234 gives you exactly that process. The last one, when you have multiple workers and only one of them is misbehaving, is the difference between ten minutes and two hours.

One real limitation: journald doesn't hold web server access logs. Nginx and Apache write directly to files, because their volume is so high that writing to the journal isn't practical. So on the same server that has journald, you need to run both journalctl and tail on files. These two are complementary, not replacements for each other.

Where people go wrong

A common mistake I've seen a lot: someone runs rm /var/log/nginx/access.log to free up space, then runs df -h and sees the space wasn't freed. The reason is that Nginx still has the file open and the inode is alive; the file has vanished from the directory but its bytes remain on disk. The correct way is truncate -s 0 /var/log/nginx/access.log, or logrotate -f /etc/logrotate.d/nginx. If you've already rm'd it, find the deleted open files with lsof +L1 and reload the service.

The second mistake is subtler: some people think that because journalctl -u mysql produces output, MySQL's log is right there. In reality, systemd only captures the service's stdout; MySQL itself writes to error.log, and that file has more complete details. If you're looking for the cause of a crash, read the file, not the journal.

Log rotation: the thing that puts a server to sleep one night

logrotate runs daily by default, and service configs are in /etc/logrotate.d/. A typical block looks like this:

/var/log/nginx/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        invoke-rc.d nginx rotate >/dev/null 2>&1
    endscript
}

Two lines here are critical. create 0640 www-data adm determines the ownership of the new file; if it's wrong, after the first rotation Nginx can no longer write and the site comes up with a 500. And postrotate must force the service to reopen the file, otherwise the same open-inode problem repeats. With logrotate -d /etc/logrotate.d/nginx you can see the output without actually running it.

On servers with heavy traffic, daily rotation isn't enough. If your access.log reaches several gigabytes in 24 hours, replace daily with size 500M. Here it's a choice between two options: time-based rotation gives you predictable files and is easier for analysis; size-based rotation keeps the disk safer. On high-traffic web servers I choose size, because one heavy day can fill the disk before the rotation turn comes around.

When the server won't come up and you have no logs

The worst case is when the service doesn't start at all and produces no logs either. First run systemctl status myservice -l --no-pager; -l keeps lines from being truncated and lets you see the actual error message. If the service isn't managed by systemd, run it directly with strace -f -e trace=openat ./binary to see which file it opens and where it fails.

If the problem is with the OS itself and you've lost access, use rescue mode. The guide Reinstalling the server and working with rescue mode; saving data when you've lost access covers exactly this scenario. And if the logs show the problem is resource consumption rather than a specific service, Diagnosing the cause of high server load; a practical, step-by-step guide is the more appropriate path.

Distribution differences at a glance

On Debian and Ubuntu, /var/log/syslog collects everything and /var/log/auth.log is separate. On RHEL, Rocky, and AlmaLinux, there's no syslog; /var/log/messages and /var/log/secure have taken their place. On Alpine, which uses musl and busybox, even rsyslog may not be installed and everything is only in the journal. If you're writing a monitoring script, don't hardcode the path; check for the file's existence first.

One practical tip for fresh servers: before any problem comes up, run ls -la /var/log/ once and see what's there. Five minutes now, at two in the morning when the site is down, is a big saving. If you work on cloud infrastructure and want to do this right from the start, cloud servers let you keep the log disk separate, and the documentation and knowledge base has logrotate config examples too. For physical servers with NVMe disks, writing heavy logs isn't an I/O problem and you can raise rotate higher.

Frequently asked questions

Where are Linux logs by default?

The main folder is /var/log/, and most services have their own subfolder, like /var/log/nginx/ or /var/log/mysql/. On systems with systemd, part of the logs are stored in the journal and read with journalctl, not with cat.

How do I find out which file a service writes to?

The fastest way is systemctl status <service>, which shows the log path in its output. If that's not enough, lsof -p $(pidof nginx) | grep log lists all open log files for that process. For services that have configs, like Nginx, the nginx -T command prints the access_log value.

Why were my old logs wiped after a reboot?

Because journald is running in volatile mode and keeps logs in /run/log/journal/, which is on tmpfs. By creating /var/log/journal/ and restarting systemd-journald, persistent mode is enabled and logs stay on disk.

Can logs be sent to another server?

Yes, with rsyslog or with systemd-journal-upload. For low volume, rsyslog over UDP port 514 is enough; for environments where log integrity matters, TCP with TLS is the better choice. Just be aware that if the destination server goes down, local rsyslog may fill its queue and become a problem itself.

Was this page helpful?