How to add a local Suricata rule

Private detections let Suricata alert on traffic that public rulesets do not describe, such as internal test paths, organization-specific indicators, or short-lived investigation markers. Keeping those signatures in a separate local file makes custom rules easier to review without editing the managed ruleset that suricata-update rebuilds.

Packaged Ubuntu configurations commonly load the compiled /var/lib/suricata/rules/suricata.rules file and can also load an extra absolute rule file. A local file under /etc/suricata/rules keeps the private rule visible in configuration review while leaving /var/lib/suricata/rules for generated rule output.

Use a private sid value that does not collide with managed rules, test the configuration before touching the running service, and trigger the signature against lab traffic before relying on it. A lab HTTP test rule can match a request for /local-rule-test and write a visible alert with sid 1000001.

Steps to add a local Suricata rule:

  1. Create the local rules directory.
    $ sudo install -d -m 0755 /etc/suricata/rules
  2. Add the local signature to its own rule file.
    $ sudo vi /etc/suricata/rules/local.rules
    /etc/suricata/rules/local.rules
    alert http any any -> any any (msg:"SG local HTTP rule test"; http.uri; content:"/local-rule-test"; sid:1000001; rev:1;)

    Use a local sid range reserved for your environment. Reusing a managed rule sid can make suppression, thresholding, and alert triage point at the wrong signature.

  3. Include the local file in the active rule list.
    $ sudo vi /etc/suricata/suricata.yaml
    /etc/suricata/suricata.yaml
    default-rule-path: /var/lib/suricata/rules
    
    rule-files:
      - suricata.rules
      - /etc/suricata/rules/local.rules

    An absolute path keeps local.rules outside the managed default-rule-path while still loading it with the compiled rule file.

  4. Refresh the managed ruleset used by the same configuration.
    $ sudo suricata-update
    25/6/2026 -- 07:51:42 - <Info> -- Using Suricata configuration /etc/suricata/suricata.yaml
    25/6/2026 -- 07:51:42 - <Info> -- No sources configured, will use Emerging Threats Open
    ##### snipped #####
    25/6/2026 -- 07:51:45 - <Info> -- Writing rules to /var/lib/suricata/rules/suricata.rules: total: 66793; enabled: 50866; added: 0; removed 0; modified: 0
    25/6/2026 -- 07:51:45 - <Info> -- No changes detected, exiting.

    suricata-update writes the managed /var/lib/suricata/rules/suricata.rules file that remains listed beside the local rule file.
    Related: How to update Suricata rules

  5. Test the full Suricata configuration with both rule files.
    $ sudo suricata -T -c /etc/suricata/suricata.yaml -v
    Notice: suricata: This is Suricata version 8.0.3 RELEASE running in SYSTEM mode
    ##### snipped #####
    Info: detect: 2 rule files processed. 50867 rules successfully loaded, 0 rules failed, 0 rules skipped
    Notice: suricata: Configuration provided was successfully loaded. Exiting.

    The loaded rule file count should increase to include the local file, and the failed rule count should remain 0.
    Related: How to test Suricata configuration

  6. Replay lab traffic that should match the new local rule.
    $ sudo suricata -r /tmp/local-rule-test.pcap -c /etc/suricata/suricata.yaml -l /tmp/suricata-local-rule
    i: suricata: This is Suricata version 8.0.3 RELEASE running in USER mode
    i: threads: Threads created -> RX: 1 W: 8 FM: 1 FR: 1   Engine started.
    i: suricata: Signal Received.  Stopping engine.
    i: pcap: read 1 file, 4 packets, 292 bytes

    Use a lab pcap that contains the traffic your rule is meant to catch. For the sample rule, the capture must contain an HTTP request for /local-rule-test.

  7. Confirm that the replay wrote the local alert.
    $ sudo cat /tmp/suricata-local-rule/fast.log
    06/25/2024-08:00:00.000000  [**] [1:1000001:1] SG local HTTP rule test [**] [Classification: (null)] [Priority: 3] {TCP} 192.0.2.10:49152 -> 198.51.100.20:80

    The bracketed alert ID should show the local sid and revision from /etc/suricata/rules/local.rules. Use /tmp/suricata-local-rule/eve.json when the alert pipeline reads EVE JSON instead of fast.log.
    Related: How to view Suricata alert logs

  8. Restart the running Suricata service after the local rule passes the replay test.
    $ sudo systemctl restart suricata

    Restarting loads the updated rule-files list into the service that monitors live traffic.
    Related: How to manage the Suricata service

  9. Remove the temporary replay log directory.
    $ sudo rm -rf /tmp/suricata-local-rule