How to Configure SSH Remote Log Access in LogSentinelAI

LogSentinelAI reads log files from remote hosts via SSH using the RemoteSSHLogMonitor class, which streams file contents through Paramiko based on environment variables defined in config.py or a system-wide configuration file.

To monitor logs on remote servers without installing agents, the call518/logsentinelai repository provides native SSH support through the RemoteSSHLogMonitor implementation. This feature enables secure, incremental log tailing over SSH connections using either key-based or password authentication. Understanding how to configure SSH remote log access in LogSentinelAI requires familiarity with three core components: the configuration loader in config.py, the SSH wrapper in ssh.py, and the high-level monitor in monitoring.py.

Prerequisites

Before configuring remote access, ensure the Paramiko library is installed in your environment. The RemoteSSHLogMonitor imports Paramiko lazily inside _create_ssh_connection() (lines 46‑55 of src/logsentinelai/core/ssh.py), raising an ImportError with a descriptive message if the dependency is missing.

pip install paramiko

Configuration Methods

LogSentinelAI loads SSH settings through two mechanisms defined in src/logsentinelai/core/config.py:

  1. Environment variables – Place settings in a .env file at the repository root.
  2. System-wide configuration – Create /etc/logsentinelai.config for global installations.

The apply_config() function (called at import time) uses load_dotenv to parse the first existing file, then _load_values() populates the DEFAULT_REMOTE_SSH_CONFIG dictionary (lines 98‑106).

Core Components

The SSH remote log functionality relies on three integrated components:

Component Source File Purpose
RemoteSSHLogMonitor src/logsentinelai/core/ssh.py Wraps Paramiko to query file metadata and read byte ranges via dd commands.
Configuration loader src/logsentinelai/core/config.py Builds DEFAULT_REMOTE_SSH_CONFIG from environment variables.
RealtimeLogMonitor src/logsentinelai/core/monitoring.py Orchestrates polling; instantiates the SSH monitor when access_mode is "ssh".

Step-by-Step Configuration

1. Enable SSH Mode

Set the REMOTE_LOG_MODE variable to activate remote access:

REMOTE_LOG_MODE=ssh

2. Provide SSH Connection Details

Populate the DEFAULT_REMOTE_SSH_CONFIG dictionary with the following variables (see config.py lines 98‑106):

REMOTE_SSH_HOST=your.remote.host
REMOTE_SSH_PORT=22                    # Optional; defaults to 22

REMOTE_SSH_USER=your_user
REMOTE_SSH_KEY_PATH=~/.ssh/id_rsa     # Use for key authentication

REMOTE_SSH_PASSWORD=your_password     # Use only if not using a key

REMOTE_SSH_TIMEOUT=10

3. Specify Remote Log Paths

Define the target files using the standard path variables or pass them explicitly via the API:

LOG_PATH_HTTPD_ACCESS=/var/log/httpd/access_log
LOG_PATH_LINUX_SYSTEM=/var/log/syslog

How SSH Remote Log Access Works

Configuration Flow

  1. apply_config() loads the environment file and calls _load_values() to populate DEFAULT_REMOTE_SSH_CONFIG.
  2. When create_realtime_monitor() is invoked (in monitoring.py lines 27‑30), get_analysis_config() merges defaults with runtime overrides.
  3. If access_mode resolves to "ssh", RealtimeLogMonitor.__init__ calls _initialize_ssh_monitor(), constructing a RemoteSSHLogMonitor instance with the prepared ssh_config and target log_path.

Runtime Operations

The RemoteSSHLogMonitor class provides four key methods for remote file interaction:

  • test_connection() (lines 63‑73): Executes a remote echo command to validate connectivity.
  • get_file_size() (lines 81‑94): Runs stat -c %s to determine current file size in bytes.
  • get_file_inode() (lines 98‑112): Runs stat -c %i to fetch the inode number for rotation detection.
  • read_from_position(position) (lines 15‑55): Uses stat to calculate available bytes, then executes dd skip=position count=bytes_to_read to stream only new data, splitting output into lines.

During operation, RealtimeLogMonitor records the initial file size and inode via _initialize_file_state(). On each polling interval, _read_remote_new_lines() compares current metadata against cached values, detects log rotation or truncation, and calls read_from_position() to fetch only appended bytes.

Code Examples

Environment Configuration File

Create a .env file in the repository root:


# LogSentinelAI SSH Remote Log Access Configuration

REMOTE_LOG_MODE=ssh

# Connection parameters

REMOTE_SSH_HOST=10.0.0.42
REMOTE_SSH_PORT=22
REMOTE_SSH_USER=logreader
REMOTE_SSH_KEY_PATH=~/.ssh/logsentinel_ai_key

# REMOTE_SSH_PASSWORD=secret_password  # Alternative to key auth

REMOTE_SSH_TIMEOUT=15

# Target log files

LOG_PATH_HTTPD_ACCESS=/var/log/httpd/access_log
LOG_PATH_LINUX_SYSTEM=/var/log/syslog

Programmatic Monitor Creation

Instantiate a monitor for remote Apache logs via the Python API:

from logsentinelai.core.monitoring import create_realtime_monitor

# Override configuration at runtime

custom_ssh = {
    "host": "10.0.0.42",
    "user": "logreader",
    "key_path": "/home/user/.ssh/logsentinel_ai_key",
}

monitor = create_realtime_monitor(
    log_type="httpd_access",
    remote_mode="ssh",
    ssh_config=custom_ssh,
    remote_log_path="/var/log/httpd/access_log"
)

# Process log chunks

for chunk in monitor.get_new_log_chunks():
    print(f"New chunk: {len(chunk)} lines")
    # analyze(chunk)

Manual Connection Verification

Test SSH connectivity and file access directly:

from logsentinelai.core.ssh import RemoteSSHLogMonitor
from logsentinelai.core.config import DEFAULT_REMOTE_SSH_CONFIG

ssh_cfg = DEFAULT_REMOTE_SSH_CONFIG.copy()
ssh_cfg.update({
    "host": "10.0.0.42",
    "user": "logreader",
    "key_path": "~/.ssh/logsentinel_ai_key",
})

monitor = RemoteSSHLogMonitor(ssh_cfg, "/var/log/httpd/access_log")
print("Connection test:", monitor.test_connection())
print("File size:", monitor.get_file_size())
print("Inode:", monitor.get_file_inode())
print("Sample lines:", monitor.read_from_position(0)[:5])

Summary

  • Enable SSH mode by setting REMOTE_LOG_MODE=ssh in your environment or /etc/logsentinelai.config.
  • Authentication supports both private keys (REMOTE_SSH_KEY_PATH) and passwords (REMOTE_SSH_PASSWORD).
  • Core implementation resides in src/logsentinelai/core/ssh.py, utilizing Paramiko for secure connections and shell commands (stat, dd) for efficient byte-range reading.
  • Rotation detection relies on inode comparison via get_file_inode() to handle log file truncation or replacement.
  • High-level interface in monitoring.py automatically manages polling intervals and buffer management when access_mode is configured for SSH.

Frequently Asked Questions

What authentication methods does LogSentinelAI support for SSH connections?

LogSentinelAI supports both key-based and password authentication as implemented in RemoteSSHLogMonitor._create_ssh_connection(). Set REMOTE_SSH_KEY_PATH to the private key file for key authentication, or provide REMOTE_SSH_PASSWORD for password-based access. If both are specified, the implementation prioritizes key authentication.

How does LogSentinelAI detect log rotation on remote servers?

The monitor tracks the file inode using get_file_inode() (lines 98‑112 of ssh.py) and compares it against the cached value on each polling cycle. If the inode changes between reads, indicating the file was replaced (common in logrotate scenarios), the monitor resets its position tracker and begins reading from the new file.

Can I monitor multiple remote logs simultaneously?

Yes. Instantiate separate RealtimeLogMonitor instances via create_realtime_monitor() for each remote log file, passing distinct remote_log_path values and ssh_config dictionaries. Each monitor maintains independent SSH connections and file state tracking, allowing concurrent monitoring of multiple hosts or log types.

Is the SSH connection persistent or re-established per read?

The RemoteSSHLogMonitor maintains a persistent Paramiko SSH client connection established during __init__. The connection remains active for the lifetime of the monitor instance, with individual commands executed via exec_command for each metadata query or data read operation. This approach minimizes connection overhead while allowing precise byte-range queries through dd commands.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →