Skip to main content

Overview

Run the GitHub Webhook Server as a systemd service for automatic startup, restart on failure, and easy management.

Systemd Service Unit File

Here’s the systemd service configuration from the README:
[Unit]
Description=GitHub Webhook Server
After=network.target

[Service]
Type=simple
User=webhook
Group=webhook
WorkingDirectory=/opt/github-webhook-server
Environment=WEBHOOK_SERVER_DATA_DIR=/opt/github-webhook-server/data
ExecStart=/usr/local/bin/uv run entrypoint.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Installation Steps

1. Create Service User

Create a dedicated user for running the webhook server:
# Create webhook user
sudo useradd -r -s /bin/bash -d /opt/github-webhook-server webhook

# Create home directory
sudo mkdir -p /opt/github-webhook-server
sudo chown webhook:webhook /opt/github-webhook-server

2. Install Dependencies

# Install Python 3.12+
sudo dnf install python3.12 python3.12-devel  # Fedora/RHEL
# OR
sudo apt install python3.12 python3.12-dev    # Ubuntu/Debian

# Install uv package manager
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install git and other dependencies
sudo dnf install git podman  # Fedora/RHEL
# OR
sudo apt install git podman  # Ubuntu/Debian

3. Install Webhook Server

# Switch to webhook user
sudo su - webhook

# Clone repository
cd /opt/github-webhook-server
git clone https://github.com/myakove/github-webhook-server.git .

# Install dependencies
uv sync

# Create data directory
mkdir -p data/logs

4. Configure the Server

Create the configuration file:
# Create config.yaml
cat > /opt/github-webhook-server/data/config.yaml << 'EOF'
# yaml-language-server: $schema=https://raw.githubusercontent.com/myk-org/github-webhook-server/refs/heads/main/webhook_server/config/schema.yaml

log-level: INFO
log-file: webhook-server.log

github-app-id: 123456
webhook-ip: https://your-domain.com/webhook_server

github-tokens:
  - ghp_your_github_token

repositories:
  my-repository:
    name: my-org/my-repository
    protected-branches:
      main: []
EOF

# Add GitHub App private key
cp /path/to/webhook-server.private-key.pem /opt/github-webhook-server/data/

# Set permissions
chmod 600 /opt/github-webhook-server/data/config.yaml
chmod 600 /opt/github-webhook-server/data/webhook-server.private-key.pem

5. Create Systemd Service

# Create service file
sudo cat > /etc/systemd/system/github-webhook-server.service << 'EOF'
[Unit]
Description=GitHub Webhook Server
After=network.target

[Service]
Type=simple
User=webhook
Group=webhook
WorkingDirectory=/opt/github-webhook-server
Environment="WEBHOOK_SERVER_DATA_DIR=/opt/github-webhook-server/data"
Environment="WEBHOOK_SERVER_PORT=5000"
Environment="MAX_WORKERS=20"
Environment="VERIFY_GITHUB_IPS=1"
Environment="ENABLE_LOG_SERVER=true"
ExecStart=/home/webhook/.local/bin/uv run entrypoint.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/github-webhook-server/data

[Install]
WantedBy=multi-user.target
EOF

# Reload systemd
sudo systemctl daemon-reload
Adjust the ExecStart path to match where uv is installed. Use which uv to find the correct path.

Environment Variables

You can set environment variables in the service file:
[Service]
Environment="WEBHOOK_SERVER_DATA_DIR=/opt/github-webhook-server/data"
Environment="WEBHOOK_SERVER_PORT=5000"
Environment="MAX_WORKERS=20"
Environment="WEBHOOK_SECRET=your-secret-here"
Environment="VERIFY_GITHUB_IPS=1"
Environment="VERIFY_CLOUDFLARE_IPS=1"
Environment="ENABLE_LOG_SERVER=true"
Environment="ENABLE_MCP_SERVER=false"

Using Environment File

For better secret management, use an environment file:
# Create environment file
sudo cat > /etc/github-webhook-server/environment << 'EOF'
WEBHOOK_SERVER_DATA_DIR=/opt/github-webhook-server/data
WEBHOOK_SERVER_PORT=5000
MAX_WORKERS=20
WEBHOOK_SECRET=your-secret-here
VERIFY_GITHUB_IPS=1
ENABLE_LOG_SERVER=true
EOF

# Set permissions
sudo chmod 600 /etc/github-webhook-server/environment
sudo chown webhook:webhook /etc/github-webhook-server/environment
Update the service file:
[Service]
EnvironmentFile=/etc/github-webhook-server/environment

Service Management

Enable and Start Service

# Enable service to start on boot
sudo systemctl enable github-webhook-server

# Start service
sudo systemctl start github-webhook-server

# Check status
sudo systemctl status github-webhook-server

Stop and Restart

# Stop service
sudo systemctl stop github-webhook-server

# Restart service
sudo systemctl restart github-webhook-server

# Reload configuration
sudo systemctl reload-or-restart github-webhook-server

Disable Service

# Disable service from starting on boot
sudo systemctl disable github-webhook-server

# Stop and disable
sudo systemctl disable --now github-webhook-server

Logs and Monitoring

View Logs with journalctl

# View all logs
sudo journalctl -u github-webhook-server

# Follow logs in real-time
sudo journalctl -u github-webhook-server -f

# View logs since last boot
sudo journalctl -u github-webhook-server -b

# View logs from last hour
sudo journalctl -u github-webhook-server --since "1 hour ago"

# View only errors
sudo journalctl -u github-webhook-server -p err

Application Logs

Application logs are written to the data directory:
# View webhook server logs
tail -f /opt/github-webhook-server/data/logs/webhook-server.log

# View structured webhook logs
tail -f /opt/github-webhook-server/data/logs/webhooks_*.json

# View MCP server logs
tail -f /opt/github-webhook-server/data/logs/mcp_server.log

Health Check

# Check if service is running
curl http://localhost:5000/webhook_server/healthcheck

# Expected response:
# {"status": 200, "message": "Alive"}

Security Hardening

Service Isolation

Add security restrictions to the service file:
[Service]
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/github-webhook-server/data
ReadOnlyPaths=/opt/github-webhook-server

# Network restrictions (if not using container building)
# PrivateNetwork=true  # Uncomment if no network needed

# Capabilities (minimal required)
CapabilityBoundingSet=
AmbientCapabilities=

# System calls filter
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources
If you need container building features, do NOT enable PrivateNetwork or restrict system calls too much.

File Permissions

# Secure configuration files
sudo chmod 600 /opt/github-webhook-server/data/config.yaml
sudo chmod 600 /opt/github-webhook-server/data/webhook-server.private-key.pem
sudo chown webhook:webhook /opt/github-webhook-server/data/*

# Secure environment file
sudo chmod 600 /etc/github-webhook-server/environment
sudo chown webhook:webhook /etc/github-webhook-server/environment

Firewall Configuration

# Allow webhook port (5000)
sudo firewall-cmd --permanent --add-port=5000/tcp
sudo firewall-cmd --reload

# Or use firewalld service
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload

Updates and Maintenance

Update Webhook Server

# Stop service
sudo systemctl stop github-webhook-server

# Switch to webhook user
sudo su - webhook

# Update code
cd /opt/github-webhook-server
git pull

# Update dependencies
uv sync

# Exit webhook user
exit

# Start service
sudo systemctl start github-webhook-server

# Check status
sudo systemctl status github-webhook-server

Log Rotation

Configure log rotation for application logs:
# Create logrotate configuration
sudo cat > /etc/logrotate.d/github-webhook-server << 'EOF'
/opt/github-webhook-server/data/logs/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0640 webhook webhook
    postrotate
        systemctl reload github-webhook-server > /dev/null 2>&1 || true
    endscript
}
EOF

Troubleshooting

Service Won’t Start

# Check service status
sudo systemctl status github-webhook-server

# View detailed error logs
sudo journalctl -u github-webhook-server -n 100 --no-pager

# Check if port is in use
sudo ss -tlnp | grep 5000

# Test manually
sudo su - webhook
cd /opt/github-webhook-server
uv run entrypoint.py

Permission Errors

# Fix data directory permissions
sudo chown -R webhook:webhook /opt/github-webhook-server/data
sudo chmod 755 /opt/github-webhook-server/data
sudo chmod 755 /opt/github-webhook-server/data/logs

# Fix configuration file permissions
sudo chmod 600 /opt/github-webhook-server/data/config.yaml

Service Crashes

# View crash logs
sudo journalctl -u github-webhook-server -p err -n 50

# Check core dumps (if enabled)
sudo coredumpctl list
sudo coredumpctl info <pid>

# Increase restart delay if service is crash-looping
sudo systemctl edit github-webhook-server

# Add:
[Service]
RestartSec=30

Monitoring with systemd

Service Watchdog

Enable systemd watchdog for automatic restart on hang:
[Service]
WatchdogSec=60

Resource Limits

Set resource limits to prevent resource exhaustion:
[Service]
# Memory limit (2GB)
MemoryMax=2G
MemoryHigh=1.5G

# CPU limit (2 cores)
CPUQuota=200%

# File descriptor limit
LimitNOFILE=65536

# Process limit
TasksMax=1024

Next Steps

Configuration

Configure your webhook server

Docker

Docker deployment alternative

Examples

View deployment examples

Security

Security best practices

Build docs developers (and LLMs) love