Aegira Documentation

Everything you need to install, configure, and use Aegira.

Install

terminal
# Download
$ wget https://github.com/talatsajafa/Aegira-free-v1-releases/releases/download/v1.0.0/aegira-free-v1.0.0-x86_64.tar.gz
$ tar -xzf aegira-free-v1.0.0-x86_64.tar.gz

# Install (prompts for target)
$ sudo ./install.sh

Requires Linux x86_64. Docker is optional. The installer will guide you through target setup and optional email alerts.

Commands

Command Description
sudo aegira installInstall the Aegira service
sudo aegira statusCheck if Aegira is running
sudo aegira runStart monitoring in foreground
sudo aegira historyView past incidents
sudo aegira show-rulesList active rules (short)
sudo aegira rules listList all active rules (detailed)
sudo aegira rules show <id>View rule details
sudo aegira rules exportExport all rules as JSON
sudo aegira rules disable <id>Disable a rule
sudo aegira rules enable <id>Enable a disabled rule
sudo aegira configure service <name>Set target systemd service
sudo aegira configure container <name>Set target Docker container
sudo aegira configure multi <c1> <c2> ...Set multiple target containers
sudo aegira configure auto <name> [--container]Auto-configure service or container
sudo aegira configure alerts <on|off> [email]Enable/disable email alerts
sudo aegira docker-status <name>Inspect a container's state
aegira --helpShow usage

Custom Rules

Aegira Free allows up to 3 custom rules. Place JSON files in /etc/aegira/rules/custom/.

Adding a Custom Rule

  1. Create a JSON file in /etc/aegira/rules/custom/
    $ sudo nano /etc/aegira/rules/custom/my-rule.json
  2. Paste your rule JSON (see example below). Free allows up to 3 custom rules. Pro is unlimited.
  3. Reload Aegira:
    $ sudo systemctl restart aegira.service
  4. Verify it loaded:
    $ sudo aegira rules list
example.json
{
  "id": "redis_restart",
  "name": "Restart Redis on connection error",
  "severity": "high",
  "error_patterns": [
    "redis connection failed",
    "redis connection refused"
  ],
  "context_patterns": ["redis"],
  "trigger": { "type": "log" },
  "remediation": {
    "type": "service_restart",
    "service": "redis"
  },
  "verification": {
    "type": "service_active",
    "service": "redis"
  },
  "action": "auto_recover",
  "priority": 50
}

Rule Fields Reference

Field Required Description
idYesUnique rule ID (lowercase, no spaces)
nameYesHuman-readable name
severityNolow / medium / high / critical
error_patternsYesLog substrings that trigger the rule
context_patternsNoAdditional context substrings (higher match score)
triggerNoObject — see Trigger section below. Defaults to { "type": "log" }
remediationYesservice_restart, container_restart, command, container_exec, command_sequence, alert_only
verificationYesservice_active, container_running, container_healthy, http_status, container_http_status, command_success, none
actionNoauto_recover / alert_only / dry_run / approval_required
priorityNoHigher = matched first (default 0)

Trigger Types

The trigger field is an object with a type key. Supported types:

Type Example
log{ "type": "log" }
docker_exit{ "type": "docker_exit", "container": "my-app", "exit_codes": [137] }
docker_health{ "type": "docker_health", "container": "my-app", "status": "unhealthy" }
docker_oom{ "type": "docker_oom", "container": "my-app" }
http_health{ "type": "http_health", "url": "http://...", "container": "my-app", "expected_status": 200 }
container_probe{ "type": "container_probe", "container": "my-db", "executable": "pg_isready" }

💡 Trigger Format

trigger is always an object, never a string. Use { "type": "log" } — not "log".

Rule Examples

Restart a systemd service on log error:

{
  "id": "nginx_restart",
  "name": "Restart Nginx on connection error",
  "error_patterns": ["nginx", "connection refused", "failed"],
  "trigger": { "type": "log" },
  "remediation": { "type": "service_restart", "service": "nginx" },
  "verification": { "type": "service_active", "service": "nginx" },
  "action": "auto_recover",
  "priority": 50
}

Restart a Docker container on exit 137:

{
  "id": "app_container_restart",
  "name": "Restart app container on exit 137",
  "error_patterns": ["exit code 137"],
  "trigger": { "type": "docker_exit", "container": "my-app", "exit_codes": [137] },
  "remediation": { "type": "container_restart", "container": "my-app" },
  "verification": { "type": "container_running", "container": "my-app" },
  "action": "auto_recover",
  "priority": 50
}

Heal a service inside a container without restarting it:

{
  "id": "nginx_reload",
  "name": "Reload nginx config inside container",
  "error_patterns": ["nginx config error"],
  "trigger": { "type": "log" },
  "remediation": { "type": "container_exec", "container": "nginx", "args": ["nginx", "-s", "reload"] },
  "verification": { "type": "container_http_status", "container": "nginx", "url": "http://127.0.0.1:8080/health", "expected_status": 200 },
  "action": "auto_recover",
  "priority": 50
}

HTTP health check + container exec (fix service inside a running container):

{
  "id": "nginx_http_health",
  "name": "Nginx HTTP health check + container exec",
  "error_patterns": ["HTTP health check failed"],
  "trigger": {
    "type": "http_health",
    "url": "http://localhost:8080/",
    "container": "my-app",
    "expected_status": 200,
    "interval_secs": 5
  },
  "remediation": {
    "type": "container_exec",
    "container": "my-app",
    "args": ["nginx"]
  },
  "verification": {
    "type": "container_http_status",
    "container": "my-app",
    "url": "http://localhost:8080/",
    "expected_status": 200
  },
  "action": "auto_recover",
  "priority": 50
}

Alert only — no automatic remediation:

{
  "id": "disk_full_alert",
  "name": "Alert on disk full",
  "error_patterns": ["no space left on device"],
  "trigger": { "type": "log" },
  "remediation": { "type": "alert_only" },
  "verification": { "type": "none" },
  "action": "alert_only",
  "priority": 50
}

⚠️ Important

Rules execute as root. Destructive commands are blocked best-effort, not foolproof. Write your rules carefully.

Testing Sequence & Timing

After creating a rule, follow this sequence to ensure Aegira detects and recovers correctly. Skipping steps (especially the waits) is the most common reason rules don't fire.

💡 Quick Summary

Rule → Restart → Wait → Configure → Restart → Clear Log → Crash → Wait → Check

Step-by-Step Sequence

  1. Create your rule
    $ sudo nano /etc/aegira/rules/custom/my-rule.json

    Paste your JSON and save.

  2. Reload Aegira
    $ sudo systemctl restart aegira

    Aegira reloads rules dynamically when the file changes, but a restart guarantees the new rule is loaded.

  3. Verify the rule loaded
    $ sudo aegira rules list

    Look for your rule in the Custom section. If it's not there, check the journal for rejection reasons.

  4. Wait 10–15 seconds
    $ sleep 15

    Aegira's monitoring threads need time to start. This ensures journald, Docker events, and HTTP health monitors are running before you test.

  5. Configure your target (if the rule uses TARGET_SERVICE or TARGET_CONTAINER)
    $ sudo aegira configure service nginx
    # or
    $ sudo aegira configure container my-app
  6. Restart Aegira again (to load the new target)
    $ sudo systemctl restart aegira
    $ sleep 15

    Target configuration is loaded at startup. Without a restart, the rule won't know which service or container to target.

  7. Clear the incident log
    $ sudo truncate -s 0 /var/log/aegira/incident.log

    This ensures only the new incident is visible in the log. Old entries make it hard to verify whether the new rule fired.

  8. Trigger the crash
    # systemd service
    $ sudo systemctl stop nginx
    
    # Docker container
    $ docker kill my-app
  9. Wait 10–15 seconds
    $ sleep 15

    Aegira needs time to detect the crash, match the rule, run the recovery, and verify the result.

  10. Check the recovery log
    $ sudo cat /var/log/aegira/incident.log

    You should see [WATCHER], [RECOVER], and [RESOLVED] entries.

  11. Verify recovery
    # systemd service
    $ sudo systemctl is-active nginx
    
    # Docker container
    $ docker inspect -f '{{.State.Status}}' my-app

Timing Cheat Sheet

Action Wait Time Why
After rule reload 10–15s Monitoring threads need to start
After target configure 10–15s Config loaded at startup
After crash 10–15s Detect + match + recover + verify
HTTP health poll 5s default Configurable via interval_secs
Cooldown (after recovery) 30s–600s Prevents infinite restart loops

⚠️ Common Mistakes

  • Testing too fast — if you crash a service within 2 seconds of starting Aegira, the initial snapshot may not have completed yet.
  • Forgetting the second restart — after configuring a target, Aegira must restart to load it.
  • Not clearing the log — old incidents make it hard to tell if the new rule fired.
  • Wrong trigger format — trigger is an object, not a string: { "type": "log" }.

Email Alerts (Optional)

Aegira can send Gmail alerts via Composio when incidents occur. You need a free Composio account.

During install, choose to enable alerts and provide:

  • Composio API key (from app.composio.dev)
  • Composio user ID
  • Recipient email

Or configure later:

$ sudo aegira configure alerts on you@example.com

Troubleshooting

Aegira service not running +
$ sudo systemctl status aegira.service
$ sudo journalctl -u aegira -n 100
Rule not matching +

Check the Aegira journal for rejection reasons:

$ sudo journalctl -u aegira -n 50 | grep -i "rules\|skip\|invalid"

Common causes:

  • Missing error_patterns
  • Invalid JSON syntax
  • Wrong trigger format (must be object, not string)
  • Target not configured
Alerts not arriving +

Verify your Composio API key and user ID in /etc/aegira/composio.env. Then check the incident log: sudo grep -i alert /var/log/aegira/incident.log

Docker rules not firing +

Docker rules use TARGET_CONTAINER. You must configure a target: sudo aegira configure container <name>

Journald not detecting services +

Aegira monitors journald (systemd logs). If a service isn't detected, verify it logs to journald: journalctl -u <service> -n 20. If no output, the service may not be a systemd unit.