瀏覽代碼

feat: add systemd service support with auto-detecting logger (#2)

- Add systemd service file configured for unprivileged user (claude)
- Enhance logger to auto-detect systemd environment (JOURNAL_STREAM/INVOCATION_ID)
- Disable colors and timestamps when running under systemd for clean journalctl output
- Add comprehensive SYSTEMD.md documentation covering installation and usage
- Update README.md with systemd service information and quick start guide
- Include security hardening options in service file (NoNewPrivileges, ProtectSystem, etc.)

The logger now automatically adapts its output format:
- With systemd: Clean output without colors/timestamps (journald handles these)
- Without systemd: Colored output with timestamps for better console readability

Related to #2
Claude 9 月之前
父節點
當前提交
9dc4484cb9
共有 5 個文件被更改,包括 342 次插入2 次删除
  1. 1 0
      CLAUDE.md
  2. 22 0
      README.md
  3. 280 0
      SYSTEMD.md
  4. 31 0
      agent-manager.service
  5. 8 2
      src/logger.js

+ 1 - 0
CLAUDE.md

@@ -288,4 +288,5 @@ You always have to push the changes into the git reposiroty. Before pushing chan
  - always add label to the issue if no label added
  - always write comment with the current status of the work 
  - when you create commit message, mention the issue if exists
+ - never close the issue 
 

+ 22 - 0
README.md

@@ -56,6 +56,28 @@ The server will start on port 3000 and execute configured commands when webhooks
 npm run dev
 ```
 
+### Running as a Systemd Service
+
+For production deployments, you can run the server as a systemd service. This provides:
+- Automatic start on system boot
+- Automatic restart on failure
+- Centralized logging via journalctl
+- Running as an unprivileged user
+
+See [SYSTEMD.md](./SYSTEMD.md) for detailed installation and configuration instructions.
+
+Quick example:
+```bash
+# Install the service
+sudo cp agent-manager.service /etc/systemd/system/
+sudo systemctl daemon-reload
+sudo systemctl enable agent-manager
+sudo systemctl start agent-manager
+
+# View logs
+journalctl -u agent-manager -f -n100
+```
+
 ### Configuration
 
 The server uses two configuration files:

+ 280 - 0
SYSTEMD.md

@@ -0,0 +1,280 @@
+# Systemd Service Installation
+
+This document explains how to install and run the Agent Manager as a systemd service.
+
+## Prerequisites
+
+- Node.js >= 18.0.0
+- A non-root user to run the service (recommended: `claude`)
+- systemd-based Linux distribution
+
+## Installation Steps
+
+### 1. Prepare the application
+
+Clone the repository to the user's home directory:
+```bash
+cd /home/claude
+git clone <repository-url> agent-manager
+cd agent-manager
+```
+
+### 2. Configure the application
+
+Create your `.env` file from the example:
+```bash
+cp .env.example .env
+```
+
+Edit `.env` to configure your settings:
+```bash
+nano .env
+```
+
+Create your `commands.json` from the example:
+```bash
+cp commands.json.example commands.json
+```
+
+Edit `commands.json` to configure your webhook commands:
+```bash
+nano commands.json
+```
+
+### 3. Install the systemd service
+
+Copy the service file to systemd directory (requires sudo):
+```bash
+sudo cp agent-manager.service /etc/systemd/system/
+```
+
+If your installation path is different from `/home/claude/agent-manager`, edit the service file:
+```bash
+sudo nano /etc/systemd/system/agent-manager.service
+```
+
+Update these fields:
+- `WorkingDirectory`: Path to your installation
+- `User`: The unprivileged user to run as
+- `Group`: The group to run as
+- `ReadWritePaths`: Path to your installation (for writing queue.json)
+
+### 4. Enable and start the service
+
+Reload systemd to recognize the new service:
+```bash
+sudo systemctl daemon-reload
+```
+
+Enable the service to start on boot:
+```bash
+sudo systemctl enable agent-manager
+```
+
+Start the service:
+```bash
+sudo systemctl start agent-manager
+```
+
+## Managing the Service
+
+### Check service status
+```bash
+sudo systemctl status agent-manager
+```
+
+### View logs (last 100 lines, follow mode)
+```bash
+journalctl -u agent-manager -f -n100
+```
+
+### View logs without follow
+```bash
+journalctl -u agent-manager -n100
+```
+
+### View logs since a specific time
+```bash
+journalctl -u agent-manager --since "2025-10-28 10:00:00"
+```
+
+### View logs for today
+```bash
+journalctl -u agent-manager --since today
+```
+
+### Stop the service
+```bash
+sudo systemctl stop agent-manager
+```
+
+### Restart the service
+```bash
+sudo systemctl restart agent-manager
+```
+
+### Disable the service (won't start on boot)
+```bash
+sudo systemctl disable agent-manager
+```
+
+## Updating the Application
+
+When updating the application code:
+
+1. Stop the service:
+```bash
+sudo systemctl stop agent-manager
+```
+
+2. Pull the latest changes:
+```bash
+cd /home/claude/agent-manager
+git pull
+```
+
+3. Start the service:
+```bash
+sudo systemctl start agent-manager
+```
+
+4. Check logs to ensure it started correctly:
+```bash
+journalctl -u agent-manager -f -n50
+```
+
+## Logging
+
+The logger automatically detects when running under systemd and adjusts its output:
+
+- **With systemd**: Colors and timestamps are disabled (journald adds these)
+- **Without systemd**: Colors and timestamps are enabled for better console output
+
+You can view logs using `journalctl`:
+```bash
+# Follow logs in real-time
+journalctl -u agent-manager -f
+
+# Show last 100 lines
+journalctl -u agent-manager -n100
+
+# Show logs from the last hour
+journalctl -u agent-manager --since "1 hour ago"
+
+# Show logs with specific priority (error, warning, info)
+journalctl -u agent-manager -p err
+
+# Export logs to file
+journalctl -u agent-manager > agent-manager.log
+```
+
+## Security Features
+
+The service file includes several security hardening options:
+
+- `NoNewPrivileges=true`: Prevents privilege escalation
+- `PrivateTmp=true`: Uses private /tmp directory
+- `ProtectSystem=strict`: Makes most of the filesystem read-only
+- `ProtectHome=read-only`: Makes home directories read-only (except WorkingDirectory)
+- `ReadWritePaths`: Only allows writing to the application directory
+
+## Troubleshooting
+
+### Service fails to start
+
+Check the service status:
+```bash
+sudo systemctl status agent-manager
+```
+
+View detailed logs:
+```bash
+journalctl -u agent-manager -n100
+```
+
+### Permission issues
+
+Ensure the `claude` user has read/write access to the application directory:
+```bash
+sudo chown -R claude:claude /home/claude/agent-manager
+```
+
+### Port already in use
+
+Check if another process is using port 3000 (or your configured port):
+```bash
+sudo lsof -i :3000
+```
+
+Either stop the conflicting process or change the port in `.env`:
+```env
+PORT=3001
+```
+
+Then restart the service:
+```bash
+sudo systemctl restart agent-manager
+```
+
+### Node.js not found
+
+Ensure Node.js is installed and the path in the service file is correct:
+```bash
+which node
+```
+
+If the path is different, update `ExecStart` in `/etc/systemd/system/agent-manager.service`.
+
+## File Permissions
+
+The application needs write access to create `queue.json` for job persistence. Ensure:
+
+```bash
+# Check ownership
+ls -la /home/claude/agent-manager
+
+# Fix ownership if needed
+sudo chown -R claude:claude /home/claude/agent-manager
+
+# Verify permissions
+ls -la /home/claude/agent-manager/queue.json
+```
+
+## Advanced Configuration
+
+### Custom environment variables
+
+Add environment variables in the service file under the `[Service]` section:
+```ini
+Environment=NODE_ENV=production
+Environment=CUSTOM_VAR=value
+```
+
+Or use an environment file:
+```ini
+EnvironmentFile=/home/claude/agent-manager/.env.systemd
+```
+
+### Automatic restarts
+
+The service is configured to restart on failure with a 10-second delay. Modify these settings in the service file:
+```ini
+Restart=on-failure
+RestartSec=10s
+```
+
+Options for `Restart`:
+- `no`: Never restart
+- `on-failure`: Restart only on failure
+- `on-abnormal`: Restart on abnormal termination
+- `always`: Always restart
+
+### Resource limits
+
+Add resource limits to the service file:
+```ini
+[Service]
+MemoryMax=500M
+CPUQuota=50%
+TasksMax=100
+```

+ 31 - 0
agent-manager.service

@@ -0,0 +1,31 @@
+[Unit]
+Description=Agent Manager - Gogs Webhook Server
+Documentation=https://github.com/fszontagh/agent-manager
+After=network.target
+
+[Service]
+Type=simple
+User=claude
+Group=claude
+WorkingDirectory=/home/claude/agent-manager
+ExecStart=/usr/bin/node src/index.js
+Restart=on-failure
+RestartSec=10s
+
+# Environment
+Environment=NODE_ENV=production
+
+# Security hardening
+NoNewPrivileges=true
+PrivateTmp=true
+ProtectSystem=strict
+ProtectHome=read-only
+ReadWritePaths=/home/claude/agent-manager
+
+# Logging
+StandardOutput=journal
+StandardError=journal
+SyslogIdentifier=agent-manager
+
+[Install]
+WantedBy=multi-user.target

+ 8 - 2
src/logger.js

@@ -4,8 +4,14 @@
 
 export class Logger {
   constructor(options = {}) {
-    this.enableTimestamps = options.enableTimestamps ?? true;
-    this.enableColors = options.enableColors ?? true;
+    // Auto-detect systemd/journald environment
+    // JOURNAL_STREAM and INVOCATION_ID are set by systemd
+    const isSystemd = !!(process.env.JOURNAL_STREAM || process.env.INVOCATION_ID);
+
+    // Disable colors and timestamps when running under systemd
+    // (journald already adds timestamps and doesn't render colors well)
+    this.enableTimestamps = options.enableTimestamps ?? (isSystemd ? false : true);
+    this.enableColors = options.enableColors ?? (isSystemd ? false : true);
   }
 
   _getTimestamp() {