> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-8a08bda2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitoring Systemd logs with ClickStack

> Monitoring Systemd and Journald Logs with ClickStack

export const TrackedLink = ({href, eventName, children, ...rest}) => {
  const handleClick = () => {
    try {
      if (typeof window !== "undefined" && window.galaxy && eventName) {
        window.galaxy.track(eventName, {
          interaction: "click"
        });
      }
    } catch (e) {}
  };
  return <a href={href} onClick={handleClick} {...rest}>
      {children}
    </a>;
};

export const Image = ({img, alt, size}) => {
  return <Frame>
      <img src={img} alt={alt} />
    </Frame>;
};

<Info>
  **TL;DR**

  Collect and visualize systemd journal logs in ClickStack using the OpenTelemetry Collector's journald receiver. Includes a demo dataset and pre-built dashboard.
</Info>

<h2 id="existing-systems">
  Integration with existing systems
</h2>

Monitor your existing Linux system's journald logs by running the OpenTelemetry Collector with the journald receiver to collect system logs and send them to ClickStack via OTLP.

If you want to test this integration first without modifying your existing setup, skip to the [demo dataset section](#demo-dataset).

<h5 id="prerequisites">
  Prerequisites
</h5>

* ClickStack instance running
* Linux system with systemd (Ubuntu 16.04+, CentOS 7+, Debian 8+)
* Docker or Docker Compose installed on the monitored system

<Steps>
  <Step>
    <h4 id="get-api-key">
      Get ClickStack API key
    </h4>

    The OpenTelemetry Collector sends data to ClickStack's OTLP endpoint, which requires authentication.

    1. Open HyperDX at your ClickStack URL (e.g., [http://localhost:8080](http://localhost:8080))
    2. Create an account or log in if needed
    3. Navigate to **Team Settings → API Keys**
    4. Copy your **Ingestion API Key**

    <Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/vQMVv9Ng6hRPWQ0d/images/clickstack/api-key.png?fit=max&auto=format&n=vQMVv9Ng6hRPWQ0d&q=85&s=d3451b04e25288d1df17aa2eb35670b7" alt="ClickStack API Key" width="3810" height="1924" data-path="images/clickstack/api-key.png" />

    5. Set it as an environment variable:

    ```bash theme={null}
    export CLICKSTACK_API_KEY=your-api-key-here
    ```
  </Step>

  <Step>
    <h4 id="verify-systemd">
      Verify systemd journal is running
    </h4>

    Ensure your system is using systemd and has journal logs:

    ```bash theme={null}
    # Check systemd version
    systemctl --version

    # View recent journal entries
    journalctl -n 20

    # Check journal disk usage
    journalctl --disk-usage
    ```

    If journal storage is in memory only, enable persistent storage:

    ```bash theme={null}
    sudo mkdir -p /var/log/journal
    sudo systemd-tmpfiles --create --prefix /var/log/journal
    sudo systemctl restart systemd-journald
    ```
  </Step>

  <Step>
    <h4 id="create-otel-config">
      Create OpenTelemetry Collector configuration
    </h4>

    Create a configuration file for the OpenTelemetry Collector:

    ```yaml theme={null}
    cat > otel-config.yaml << 'EOF'
    receivers:
      journald:
        directory: /var/log/journal
        priority: info
        units:
          - sshd
          - nginx
          - docker
          - containerd
          - systemd

    processors:
      batch:
        timeout: 10s
        send_batch_size: 10000
      
      resource:
        attributes:
          - key: service.name
            value: systemd-logs
            action: insert
          - key: host.name
            from_attribute: _HOSTNAME
            action: upsert
      
      attributes:
        actions:
          - key: unit
            from_attribute: _SYSTEMD_UNIT
            action: upsert
          - key: priority
            from_attribute: PRIORITY
            action: upsert

    exporters:
      otlphttp:
        endpoint: ${CLICKSTACK_ENDPOINT}
        headers:
          authorization: ${CLICKSTACK_API_KEY}

    service:
      pipelines:
        logs:
          receivers: [journald]
          processors: [resource, attributes, batch]
          exporters: [otlphttp]
    EOF
    ```
  </Step>

  <Step>
    <h4 id="deploy-docker-compose">
      Deploy with Docker Compose
    </h4>

    <Note>
      The `journald` receiver requires the `journalctl` binary to read journal files. The official `otel/opentelemetry-collector-contrib` image doesn't include `journalctl` by default.

      For containerized deployments, you can either install the collector directly on the host or build a custom image with systemd utilities. See the [troubleshooting section](#journalctl-not-found) for details.
    </Note>

    This example shows deploying the OTel Collector alongside ClickStack:

    ```yaml theme={null}
    services:
      clickstack:
        image: clickhouse/clickstack-all-in-one:latest
        ports:
          - "8080:8080"
          - "4317:4317"
          - "4318:4318"
        networks:
          - monitoring
      
      otel-collector:
        image: otel/opentelemetry-collector-contrib:0.115.1
        depends_on:
          - clickstack
        environment:
          - CLICKSTACK_API_KEY=${CLICKSTACK_API_KEY}
          - CLICKSTACK_ENDPOINT=http://clickstack:4318
        volumes:
          - ./otel-config.yaml:/etc/otelcol/config.yaml:ro
          - /var/log/journal:/var/log/journal:ro
          - /run/log/journal:/run/log/journal:ro
          - /etc/machine-id:/etc/machine-id:ro
        command: ["--config=/etc/otelcol/config.yaml"]
        networks:
          - monitoring

    networks:
      monitoring:
        driver: bridge
    ```

    Start the services:

    ```bash theme={null}
    docker compose up -d
    ```
  </Step>

  <Step>
    <h4 id="verifying-logs">
      Verify logs in HyperDX
    </h4>

    Once configured, log into HyperDX and verify logs are flowing:

    1. Navigate to the Search view
    2. Set source to Logs
    3. Filter by `service.name:systemd-logs`
    4. You should see structured log entries with fields like `unit`, `priority`, `MESSAGE`, `_HOSTNAME`

    <Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/Q67DpMkcKgzQJkGD/images/clickstack/systemd/systemd-search-view.png?fit=max&auto=format&n=Q67DpMkcKgzQJkGD&q=85&s=162cc2cf97f3caf0a2ca7e2d6749f48a" alt="Log search view" width="3838" height="1934" data-path="images/clickstack/systemd/systemd-search-view.png" />

    <Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/Q67DpMkcKgzQJkGD/images/clickstack/systemd/systemd-log-view.png?fit=max&auto=format&n=Q67DpMkcKgzQJkGD&q=85&s=a11f24e2666c78ff6567c6823d280505" alt="Log view" width="3838" height="1934" data-path="images/clickstack/systemd/systemd-log-view.png" />
  </Step>
</Steps>

<h2 id="demo-dataset">
  Demo dataset
</h2>

For users who want to test the systemd logs integration before configuring their production systems, we provide a sample dataset of pre-generated systemd logs with realistic patterns.

<Steps>
  <Step>
    <h4 id="download-sample">
      Download the sample dataset
    </h4>

    Download the sample log file:

    ```bash theme={null}
    curl -O https://datasets-documentation.s3.eu-west-3.amazonaws.com/clickstack-integrations/systemd/systemd-demo.log
    ```
  </Step>

  <Step>
    <h4 id="demo-config">
      Create demo collector configuration
    </h4>

    Create a configuration file for the demo:

    ```bash theme={null}
    cat > systemd-demo.yaml << 'EOF'
    receivers:
      filelog:
        include:
          - /tmp/systemd-demo/systemd-demo.log
        start_at: beginning
        operators:
          - type: regex_parser
            regex: '^(?P<timestamp>\S+) (?P<hostname>\S+) (?P<unit>\S+?)(?:\[(?P<pid>\d+)\])?: (?P<message>.*)$'
            parse_from: body
            parse_to: attributes
          - type: time_parser
            parse_from: attributes.timestamp
            layout: '%Y-%m-%dT%H:%M:%S%z'
          - type: add
            field: attributes.source
            value: "systemd-demo"

    service:
      pipelines:
        logs/systemd-demo:
          receivers: [filelog]
          processors:
            - memory_limiter
            - transform
            - batch
          exporters:
            - clickhouse
    EOF
    ```
  </Step>

  <Step>
    <h4 id="run-demo">
      Run ClickStack with demo data
    </h4>

    Start ClickStack with the demo logs:

    ```bash theme={null}
    docker run -d --name clickstack-demo \
      -p 8080:8080 -p 4317:4317 -p 4318:4318 \
      -e CUSTOM_OTELCOL_CONFIG_FILE=/etc/otelcol-contrib/custom.config.yaml \
      -v "$(pwd)/systemd-demo.yaml:/etc/otelcol-contrib/custom.config.yaml:ro" \
      -v "$(pwd)/systemd-demo.log:/tmp/systemd-demo/systemd-demo.log:ro" \
      clickhouse/clickstack-all-in-one:latest
    ```

    <Note>
      The demo uses the `filelog` receiver with text logs instead of `journald` to avoid requiring `journalctl` in the container.
    </Note>
  </Step>

  <Step>
    <h4 id="verify-demo-logs">
      Verify logs in HyperDX
    </h4>

    Once ClickStack is running:

    1. Open [HyperDX](http://localhost:8080/) and log in to your account
    2. Navigate to the Search view and set the source to `Logs`
    3. Set the time range to **2025-11-14 00:00:00 - 2025-11-17 00:00:00**

    <Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/Q67DpMkcKgzQJkGD/images/clickstack/systemd/systemd-search-view.png?fit=max&auto=format&n=Q67DpMkcKgzQJkGD&q=85&s=162cc2cf97f3caf0a2ca7e2d6749f48a" alt="Log search view" width="3838" height="1934" data-path="images/clickstack/systemd/systemd-search-view.png" />

    <Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/Q67DpMkcKgzQJkGD/images/clickstack/systemd/systemd-log-view.png?fit=max&auto=format&n=Q67DpMkcKgzQJkGD&q=85&s=a11f24e2666c78ff6567c6823d280505" alt="Log view" width="3838" height="1934" data-path="images/clickstack/systemd/systemd-log-view.png" />

    <Info>
      **Timezone display**

      HyperDX displays timestamps in your browser's local timezone. The demo data spans **2025-11-15 00:00:00 - 2025-11-16 00:00:00 (UTC)**. The wide time range ensures you'll see the demo logs regardless of your location.
    </Info>
  </Step>
</Steps>

<h2 id="dashboards">
  Dashboards and visualization
</h2>

To help you get started monitoring systemd logs with ClickStack, we provide essential visualizations for systemd journal data.

<Steps>
  <Step>
    <h4 id="download">
      <TrackedLink href={'/examples/systemd-logs-dashboard.json'} download="systemd-logs-dashboard.json" eventName="docs.systemd_logs_monitoring.dashboard_download">Download</TrackedLink> the dashboard configuration
    </h4>
  </Step>

  <Step>
    <h4 id="import-dashboard">
      Import the pre-built dashboard
    </h4>

    1. Open HyperDX and navigate to the Dashboards section
    2. Click **Import Dashboard** in the upper right corner under the ellipses

    <Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/OwB6o9ddvLojEP8N/images/clickstack/import-dashboard.png?fit=max&auto=format&n=OwB6o9ddvLojEP8N&q=85&s=cdfe26f160c1c080b995c8451311241d" alt="Import dashboard button" width="3024" height="556" data-path="images/clickstack/import-dashboard.png" />

    3. Upload the `systemd-logs-dashboard.json` file and click **Finish Import**

    <Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/Q67DpMkcKgzQJkGD/images/clickstack/systemd/finish-import-systemd.png?fit=max&auto=format&n=Q67DpMkcKgzQJkGD&q=85&s=1eae9ab82fd5afdefa48a83ac0bd75a7" alt="Finish import" width="3350" height="1908" data-path="images/clickstack/systemd/finish-import-systemd.png" />
  </Step>

  <Step>
    <h4 id="created-dashboard">
      View the dashboard
    </h4>

    The dashboard includes visualizations for:

    * Log volume over time
    * Top systemd units by log count
    * SSH authentication events
    * Service failures
    * Error rates

    <Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/Q67DpMkcKgzQJkGD/images/clickstack/systemd/systemd-logs-dashboard.png?fit=max&auto=format&n=Q67DpMkcKgzQJkGD&q=85&s=3e45947e32179b01c118aeba44c81085" alt="Example dashboard" width="3808" height="1908" data-path="images/clickstack/systemd/systemd-logs-dashboard.png" />

    <Note>
      For the demo dataset, set the time range to **2025-11-15 00:00:00 - 2025-11-16 00:00:00 (UTC)** (adjust based on your local timezone).
    </Note>
  </Step>
</Steps>

<h2 id="troubleshooting">
  Troubleshooting
</h2>

<h3 id="no-logs">
  No logs appearing in HyperDX
</h3>

Check if logs are reaching ClickHouse:

```bash theme={null}
docker exec clickstack clickhouse-client --query "
SELECT COUNT(*) as log_count
FROM otel_logs
WHERE ServiceName = 'systemd-logs'
"
```

If no results, check the collector logs:

```bash theme={null}
docker logs otel-collector | grep -i "error\|journald" | tail -20
```

<h3 id="journalctl-not-found">
  journalctl not found error
</h3>

If you see `exec: "journalctl": executable file not found in $PATH`:

The `otel/opentelemetry-collector-contrib` image doesn't include `journalctl`. You can either:

1. **Install the collector on the host**:

```bash theme={null}
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.115.0/otelcol-contrib_0.115.0_linux_amd64.tar.gz
tar -xzf otelcol-contrib_0.115.0_linux_amd64.tar.gz
sudo mv otelcol-contrib /usr/local/bin/
otelcol-contrib --config=otel-config.yaml
```

2. **Use the text export approach** (like the demo) with the `filelog` receiver reading journald exports

<h2 id="next-steps">
  Next steps
</h2>

* Set up [alerts](/clickstack/features/alerts) for critical system events (service failures, authentication failures, OOM kills)
* Create additional [dashboards](/clickstack/features/dashboards/overview) for specific use cases (SSH security monitoring, service health)
* Filter by specific systemd units to reduce noise and focus on services that matter

<h2 id="going-to-production">
  Going to production
</h2>

This guide uses a separate OpenTelemetry Collector to read systemd logs and send them to ClickStack's OTLP endpoint, which is the recommended production pattern.

For production environments with multiple hosts, consider:

* Deploying the collector as a DaemonSet in Kubernetes
* Running the collector as a systemd service on each host
* Using the OpenTelemetry Operator for automated deployment

See [Ingesting with OpenTelemetry](/clickstack/ingesting-data/opentelemetry) for production deployment patterns.
