Skip to content

event triggered caddy plugin allows execute external script or program when caddy event happened

Notifications You must be signed in to change notification settings

RedForestLonvor/caddy-event-trigger

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Caddy Events Trigger (events.handlers.exec)

中文 | English

This is an event handler plugin designed for Caddy v2 that allows executing external commands when Caddy events occur. This is a true event-triggered plugin, not a monitoring-based one.

Features

  • Event-Triggered: Directly interfaces with Caddy v2's event system, triggering scripts in the synchronous execution path of event occurrence
  • Supports Multiple Caddy Events: Including TLS certificate events, HTTP routing events, etc.
  • Placeholder Replacement: Supports placeholders like {event.name}, {event.data.identifier}, etc.
  • Environment Variable Passing: Can pass event data as environment variables to scripts
  • Timeout Control: Can set command execution timeout
  • Working Directory: Can specify the working directory for command execution
  • Shell Support: Supports executing commands through shell
  • Error Handling: Can choose to abort events when commands fail

Installation

Building with xcaddy

# Install xcaddy
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

# Build Caddy with the plugin
xcaddy build --with github.com/RedForestLonvor/caddy-event-trigger=.

Configuration

Configuration Options Reference

Option Type Required Default Description
command []string Yes* - Command array to execute (each element is one argument)
shell string No - Execute command through specified shell
shell_args []string No - Extra arguments passed to the shell before -c
timeout duration No Unlimited Command execution timeout (e.g.: 30s, 5m, 1h)
work_dir string No Current directory Working directory for command execution
env map[string]string No - Additional environment variables (supports placeholders)
abort_on_error bool No false Whether to abort event when command fails

*Note: At least one of command and shell must be set

JSON Configuration

{
  "apps": {
    "events": {
      "subscriptions": [
        {
          "events": ["cert_obtained"],
          "handlers": [
            {
              "handler": "exec",
              "command": ["./my_script.sh"],
              "env": {
                "CERT_ID": "{event.data.identifier}",
                "CERT_PATH": "{event.data.certificate_path}",
                "KEY_PATH": "{event.data.private_key_path}"
              },
              "timeout": "30s",
              "work_dir": "/tmp",
              "abort_on_error": false
            }
          ]
        }
      ]
    }
  }
}

Caddyfile Configuration

{
  events {
    on cert_obtained exec ./my_script.sh
    on cert_obtained exec {
      shell /bin/sh
      shell_args -euxo pipefail
      command ./my_script.sh --cert {event.data.certificate_path}
      timeout 30s
      work_dir /tmp
      env PUSH_URL https://example.com/api
      abort_on_error false
    }
  }
}

Supported Events

Verified Supported Event Types

TLS Certificate Events

  • cert_obtained: Certificate obtained successfully (requires TLS automation configuration)
  • cert_failed: Certificate obtaining failed (requires TLS automation configuration)
  • tls_get_certificate: TLS handshake certificate retrieval

HTTP Routing Events

  • started: Caddy server started
  • *: Wildcard event (matches all events)

Note

  • Event types may vary depending on Caddy version and loaded modules
  • Some events like cert_obtaining were not verified in local testing
  • You can discover available events by monitoring Caddy logs or using the wildcard * event

Event Data Fields

  • identifier: Certificate identifier (domain name)
  • certificate_path: Certificate file path
  • private_key_path: Private key file path
  • metadata_path: Metadata file path
  • renewal: Whether it's a renewal
  • remaining: Remaining validity period

Usage Examples

1. Basic Event Trigger Example

Listen to Server Start Event

{
  "apps": {
    "events": {
      "subscriptions": [
        {
          "events": ["started"],
          "handlers": [
            {
              "handler": "exec",
              "command": ["echo", "Server started at: {event.time}"]
            }
          ]
        }
      ]
    },
    "http": {
      "servers": {
        "test": {
          "listen": [":8080"],
          "routes": [
            {
              "handle": [
                {
                  "handler": "static_response",
                  "body": "Hello from Caddy Events!"
                }
              ]
            }
          ]
        }
      }
    }
  }
}

2. Environment Variable Passing Example

{
  "apps": {
    "events": {
      "subscriptions": [
        {
          "events": ["cert_obtained"],
          "handlers": [
            {
              "handler": "exec",
              "command": ["./deploy_cert.sh"],
              "env": {
                "EVENT_TYPE": "{event.name}",
                "DOMAIN": "{event.data.identifier}",
                "CERT_FILE": "{event.data.certificate_path}",
                "KEY_FILE": "{event.data.private_key_path}",
                "TIMESTAMP": "{event.time}"
              }
            }
          ]
        }
      ]
    }
  }
}

3. Shell Mode with Complex Commands

{
  "apps": {
    "events": {
      "subscriptions": [
        {
          "events": ["started"],
          "handlers": [
            {
              "handler": "exec",
              "shell": "/bin/sh",
              "shell_args": ["-euxo", "pipefail"],
              "command": ["set -e; echo 'Server started'; date | tee /var/log/caddy-start.log"]
            }
          ]
        }
      ]
    }
  }
}

4. Real-world: SSL Certificate Auto-deployment

{
  "apps": {
    "events": {
      "subscriptions": [
        {
          "events": ["cert_obtained"],
          "handlers": [
            {
              "handler": "exec",
              "command": ["./deploy_to_cdn.sh"],
              "env": {
                "DOMAIN": "{event.data.identifier}",
                "CERT_FILE": "{event.data.certificate_path}",
                "KEY_FILE": "{event.data.private_key_path}"
              },
              "timeout": "30s",
              "abort_on_error": true
            }
          ]
        }
      ]
    }
  }
}

Testing

Quick Verification

# Create a simple test configuration
cat > test_simple.json << 'EOF'
{
  "apps": {
    "events": {
      "subscriptions": [
        {
          "events": ["started"],
          "handlers": [
            {
              "handler": "exec",
              "command": ["echo", "✅ Plugin working! Event: {event.name}"]
            }
          ]
        }
      ]
    },
    "http": {
      "servers": {
        "test": {
          "listen": [":8080"],
          "routes": [
            {
              "handle": [
                {
                  "handler": "static_response",
                  "body": "Test page"
                }
              ]
            }
          ]
        }
      }
    }
  }
}
EOF

# Test the plugin
./caddy run --config test_simple.json

Run Complete Test Suite

# Run all tests
bash tests/run_all.sh

# Run individual tests
bash tests/test_env_vars.sh       # Environment variables
bash tests/test_shell_mode.sh     # Shell mode
bash tests/test_timeout.sh        # Timeout control
bash tests/test_abort_on_error.sh # Error handling

Verify Plugin Loading

# Check if the plugin is loaded
./caddy list-modules | grep events
# Should show: events and events.handlers.exec

Development

Local Development

# Clone repository
git clone https://github.com/RedForestLonvor/caddy-event-trigger.git
cd caddy-event-trigger

# Install dependencies
go mod tidy

# Build Caddy with plugin
xcaddy build --with github.com/RedForestLonvor/caddy-event-trigger=.

License

MIT License

Contributing

Issues and Pull Requests are welcome!

FAQ

Q: Why isn't my script executing?

A: Check the following:

  1. Confirm event name is correct
  2. Check if script path is correct (recommend using absolute path)
  3. Check Caddy logs for error messages
  4. Confirm script has execute permissions

Q: Environment variables not being passed to script?

A: Check the following:

  1. Confirm env configuration is correct
  2. Check placeholder syntax is correct (e.g.: {event.name})
  3. Confirm script can receive environment variables

Q: How to debug event triggering?

A: Suggestions:

  1. Use echo command to test basic functionality
  2. Check Caddy log output
  3. Add debug information in scripts
  4. Use wildcard event * to capture all events

Related Links

About

event triggered caddy plugin allows execute external script or program when caddy event happened

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages