SpipCP
Operations

Site logs

Tail a site's access, error, and app logs live from the panel โ€” filter/grep client-side, export the watched window, and resume a killed tail from its exact byte offset with no gap and no duplicate.

The Logs tab on the site workspace tails a site's logs live, straight from inside the instance โ€” no SSH, no log shipper. It's the first thing to reach for when a site misbehaves: drive some traffic, watch the access/error lines appear, grep for the request in question, and export the exact window under review.

Where it runs

The logs are read inside the instance โ€” there's no copy on the panel server. The browser holds a short-lived (60s) link that the worker re-checks before streaming the log. Open the site workspace and the Logs tab.

Sources

The Source dropdown lists the log sources for the site's type. There's no per-site log config โ€” the set depends on the site type:

Site typeSources
staticAccess (nginx), Error (nginx)
PHP / WordPressAccess (nginx), Error (nginx), App (php-fpm)
NodeApp (node) โ€” the app unit's journal

The nginx access/error sources are files (/var/log/nginx/access.log, โ€ฆ/error.log); the app sources come from the system journal (php8.5-fpm.service or the Node app unit). The dropdown marks a source that can't resume after a disconnect as ยท live (no resume), making the resume behavior clear up front (see below).

Live tail

Selecting a source opens the live tail. New lines appear within about a second, with their real timestamps. The tab starts from the current end โ€” new lines appear from now, not a replay of the whole file (so a busy site doesn't dump 50k lines on open).

Log lines can't smuggle terminal escape codes into the page; those are also stripped from anything exported.

Filter / grep

The Filter / grep box narrows the view over the lines already shown:

  • a plain substring โ€” e.g. GET /wp-login
  • a /regex/ pattern โ€” e.g. /5\d\d/ for 5xx, /40\d/ for 4xx

It only changes what's displayed, not what's tailed, so it can be toggled on and off without losing the stream.

Download window

Download window exports the slice that's been watched:

  • For an nginx file source, it exports the exact bytes between when the tail opened and the latest line seen โ€” re-read from the file inside the instance, not rebuilt from the browser.
  • For a journal source, it exports the most-recent lines instead (a note in the tab explains this).

The file downloads as site-<id8>-<source>-<timestamp>.log. A single export is capped at 25 MiB / 50k lines.

Resume after a disconnect

For a file source, if the connection drops โ€” laptop sleeps, Wi-Fi blips, the worker restarts โ€” the tail reconnects and picks up exactly where it left off, with no gap (no missed lines) and no duplicates. If the log rotates during a watch, it resyncs to the new file's start.

File sources resume; journal sources don't

Resume is file-only. A journal source (App php-fpm / App node) tails live but can't replay a precise window after a disconnect โ€” it re-reads the most recent lines. That's why those sources are labelled ยท live (no resume) in the picker.

Permissions

Viewing logs needs SITES_LOGS_VIEW (operator and admin). Access is granted only behind that permission and is audited; there's no log access without it.

On this page