Skip to content

Scheduled jobs examples

Sources live under examples/jobs/.

Minimal demo (policy + http_call + builtin override)

Requires admin.enabled, SQLite DSN, and optional admin.jobs for command policy. Includes one http_call item and a purge_waf_events built-in override.

yaml
version: v1
port: 8080

# Minimal scheduled-jobs demo: requires admin + SQLite for job_run history.
admin:
  enabled: true
  port: 9080
  database:
    driver: sqlite
    dsn: file:./admin.db?cache=shared&_fk=1
  jobs:
    allow_command: true
    command_allowlist:
      - /bin/sh
    command_workdir: /tmp
    command_max_output_bytes: 65536

jobs:
  builtins:
    purge_waf_events:
      enabled: true
      schedule: "0 3 * * *"
      params:
        retain_days: 14
  items:
    - id: nightly-health
      name: Nightly health probe
      kind: http_call
      schedule: "0 1 * * *"
      enabled: true
      timeout_sec: 30
      on_failure: log
      params:
        method: GET
        url: https://httpbin.org/status/200
        expect_status: [200]

    - id: echo-script
      name: Echo script job
      kind: script
      schedule: "0 2 * * *"
      enabled: false
      params:
        engine: shell
        shell: sh
        script: |
          #!/bin/sh
          echo jobs-demo

rules:
  - host: jobs-demo.example.com
    backend:
      type: service
      service:
        name: httpbin.org
        port: 443
        protocol: https
bash
ingress run -c examples/jobs/ingress.yaml
# Admin jobs UI: http://127.0.0.1:9080/jobs

HTTP call only

Custom http_call jobs with expect_status, headers, and POST body. No admin.jobs.allow_command required.

yaml
version: v1
port: 8080

admin:
  enabled: true
  port: 9080
  database:
    driver: sqlite
    dsn: file:./admin.db?cache=shared&_fk=1

# Custom http_call jobs do not require admin.jobs.allow_command.
jobs:
  items:
    - id: export-webhook
      name: Trigger nightly export
      kind: http_call
      schedule: "30 2 * * *"
      enabled: true
      timeout_sec: 120
      on_failure: log
      params:
        method: POST
        url: https://httpbin.org/post
        headers:
          Authorization: Bearer replace-me
          Content-Type: application/json
        body: '{"action":"export","window":"daily"}'
        expect_status: [200, 202]
    - id: status-page
      name: Status page ping
      kind: http_call
      schedule: "*/15 * * * *"
      enabled: true
      params:
        url: https://httpbin.org/status/200

rules:
  - host: export.example.com
    backend:
      type: service
      service:
        name: httpbin.org
        port: 443
        protocol: https

Script engines (shell / JavaScript / Go)

Runnable sample: examples/jobs/script-engines.yaml — see Scheduled jobs guide.

yaml
version: v1
port: 8080

# Shell / JavaScript(goja) / Go(yaegi) script engines for custom jobs.
# Embedded javascript and go engines do not use command_allowlist (shell only).
admin:
  enabled: true
  port: 9080
  database:
    driver: sqlite
    dsn: file:./admin.db?cache=shared&_fk=1
  jobs:
    allow_command: true
    command_allowlist:
      - /bin/sh
    command_max_output_bytes: 65536

jobs:
  items:
    - id: shell-echo
      name: Shell echo
      kind: script
      schedule: "0 * * * *"
      enabled: false
      params:
        engine: shell
        shell: sh
        script: |
          #!/bin/sh
          echo "job started"

    - id: js-http-probe
      name: JavaScript HTTP probe
      kind: script
      schedule: "*/30 * * * *"
      enabled: false
      timeout_sec: 60
      params:
        engine: javascript
        script: |
          console.log("job started", new Date().toISOString())
          const res = await fetch("https://httpbin.org/status/200")
          console.log("status", res.status, "ok", res.ok)

    - id: go-stdlib-report
      name: Go stdlib report
      kind: script
      schedule: "0 6 * * *"
      enabled: false
      params:
        engine: go
        script: |
          import (
            "fmt"
            "strings"
            "time"
          )

          fmt.Println(strings.ToUpper("job started"), time.Now().Format(time.RFC3339))

rules:
  - host: jobs-scripts.example.com
    backend:
      type: service
      service:
        name: httpbin.org
        port: 443
        protocol: https
bash
ingress validate -c examples/jobs/script-engines.yaml
ingress run -c examples/jobs/script-engines.yaml
# Admin UI → 定时任务 → Run now on shell-echo / js-http-probe / go-stdlib-report

Built-in ops overrides

Tune all four built-in jobs (purge_waf_events, purge_audit_logs, check_tls_expiry, sync_geoip). Optional admin.geoip supports the GeoIP sync job.

yaml
version: v1
port: 8080

admin:
  enabled: true
  port: 9080
  database:
    driver: sqlite
    dsn: file:./admin.db?cache=shared&_fk=1
  # Optional GeoIP block for sync_geoip builtin (see admin.geoip in admin-console example).
  geoip:
    ingress_label: Demo edge
    ingress_lat: 31.2304
    ingress_lng: 121.4737

# Built-in ops jobs are always registered in code; jobs.builtins only overrides schedule / enabled / params.
jobs:
  builtins:
    purge_waf_events:
      enabled: true
      schedule: "0 3 * * *"
      params:
        retain_days: 7
    purge_audit_logs:
      enabled: true
      schedule: "0 4 * * 0"
      params:
        retain_days: 60
    check_tls_expiry:
      enabled: true
      schedule: "0 8 * * *"
    sync_geoip:
      enabled: true
      schedule: "0 2 * * *"
    # Disable a builtin by setting enabled: false (omit entry to use code defaults).

rules:
  - host: ops.example.com
    backend:
      type: service
      service:
        name: httpbin.org
        port: 443
        protocol: https

Validate

bash
ingress validate -c examples/jobs/ingress.yaml
ingress validate -c examples/jobs/http-call-only.yaml
ingress validate -c examples/jobs/builtin-ops.yaml
ingress validate -c examples/jobs/script-engines.yaml

See Scheduled jobs guide for cron syntax, command security, API paths, and job_run history.

Released under the MIT License.