# Finding and reading logs

When something goes wrong, the log usually tells you why. This page shows where TurboStack keeps
the main logs, how to open them over Secure Shell (SSH), and a few commands for reading and
analyzing them.

Logs are grouped by service, one directory per service under `/var/log/`. Depending on your
access, you see the logs for the services running under your own account.

> [!TIP]
> For a quick visual overview of resource use (CPU, memory, disk) without opening logs, use the
> host [Health](../platform/hosts/health.md) tab. Open the logs when you need the exact error.

## Where the logs are

Connect to the host over SSH first (see the host [SSH](../platform/hosts/ssh.md) tab), then read
the files below. Each of your websites (vhosts) has its own log file named after your system user
and, if set, the application name.

| Service | Location |
| --- | --- |
| Nginx access (per website) | `/var/log/nginx/<user>_<app>.log` |
| Nginx errors | `/var/log/nginx/error.log` |
| Apache access (per website) | `/var/log/apache2/<user>_<app>.log` |
| PHP / PHP-FPM errors | `/var/log/php/<user>_<app>.log` |
| MySQL error log | `/var/log/mysql/error.log` |
| Application logs | inside the application, for example a framework's own `var/log/` or `storage/logs/` directory |

Notes on reading the table:

- `<user>` is your system user (the operating system account), and `<app>` is the application
  name if the website has one. A website without an application name uses just `<user>.log`.
- The **access log** records every request. The **error log** records problems, and is where a
  `502` or `504` is explained (look for `connect() failed` or `upstream prematurely closed`).
- On some older or RedHat-based hosts, Apache logs live under `/var/log/httpd/` instead of
  `/var/log/apache2/`. The file names follow the same pattern.
- The MySQL error-log path above (`/var/log/mysql/error.log`) is the standard Debian host path. On
  cPanel/DirectAdmin (RedHat-based) hosts the MySQL error log is at `/var/lib/mysql/error.log`
  instead.
- Application frameworks keep their own logs inside the application directory. For example,
  Magento writes to `var/log/`, and Laravel writes to `storage/logs/laravel.log`. Check the
  application-specific troubleshooting page for the exact path.

## On cPanel and DirectAdmin hosts

The paths above are for the default TurboStack (customstack) host. Hosts running the cPanel or
DirectAdmin control panel expose the same logs through the panel's own web interface, so you can
read them in the browser instead of over SSH.

On DirectAdmin:

- **Admin Tools > Log Viewer** shows the general service logs (Apache, Nginx, Exim, system
  messages).
- **User Tools > Site Summary / Statistics / Logs** shows the Apache logs for the current day, with
  older, compressed logs under **Backed up Web Logs**.

On cPanel (these are reached from the user account, not the admin):

- **Metrics > Errors** shows the most recent error-log entries for your domain - useful for PHP
  errors, missing files and permission issues.
- **Metrics > Raw Access** lets you download the raw access logs, both today's and the aggregated
  per-month `.gz` files.
- **Metrics > Awstats** (or Webalizer) gives a graphical view of traffic, referrers, bots and
  bandwidth.
- **Email > Track Delivery** shows mail delivery attempts, successes and failures.

## Log rotation

TurboStack rotates logs automatically with `logrotate` (via `/etc/logrotate.d/*`) so they cannot
fill the disk. Rotation runs daily at 00:00 server time. Today's and yesterday's logs stay
uncompressed as plain `.log` files, so you can read them directly with `cat`. Logs older than two
days are compressed to save space and get a `.gz` extension (for example `access.log.2.gz`); read
those with `zcat`.

Logs are kept for 30 days by default. Some services deviate from the 30-day policy to conserve disk
space.

To read them:

- Read a current, uncompressed log with `cat`, `less`, or `tail -f` to follow it live:

  ```bash
  tail -f /var/log/nginx/<user>_<app>.log
  ```

- Read a compressed, rotated log with `zcat`, `zless`, or `zgrep` (no need to unpack it first):

  ```bash
  zcat /var/log/nginx/<user>_<app>.log.1.gz | less
  ```

## Reading logs efficiently

Access logs share a common format, so a few `awk` and `grep` one-liners answer most questions.
Replace `<logfile>` with the path from the table above.

Show the five IP addresses making the most requests:

```bash
awk '{print $1}' <logfile> | sort | uniq -c | sort -nr | head -5
```

Show the five most-requested paths:

```bash
awk '{print $7}' <logfile> | sort | uniq -c | sort -nr | head -5
```

Show the total requests per HTTP status code:

```bash
awk '{print $9}' <logfile> | sort | uniq -c | sort -nr
```

Show the five most common user agents:

```bash
awk -F\" '{print $6}' <logfile> | sort | uniq -c | sort -nr | head -5
```

### Combining the two

A burst of `403` responses can mean scraping or someone probing for a way in. Find the IP
addresses causing the most of them:

```bash
grep " 403 " <logfile> | awk '{print $1}' | sort | uniq -c | sort -nr | head -5
```

If a small set of IP addresses is responsible for abusive traffic, you can add them to your
firewall block list. TurboStack also blocks many of these sources automatically; see the
[Security overview](../concepts/security-overview.md).

## Related

- [Host SSH tab](../platform/hosts/ssh.md)
- [Health](../platform/hosts/health.md)
- [Fixing 502, 503 and 504 errors](site-down-5xx.md)
- [Fixing 403, 413 and 429 errors](http-4xx-errors.md)
- [Disk full and freeing up space](disk-space.md)
- [Security overview](../concepts/security-overview.md)
