{"id":49170690,"url":"https://github.com/magenx/tuzik","last_synced_at":"2026-04-22T18:32:59.421Z","repository":{"id":347039101,"uuid":"1192615437","full_name":"magenx/tuzik","owner":"magenx","description":"Go daemon for Linux that reads audit events from the audisp-af_unix Unix domain socket and automatically deletes or quarantines (moves) files that match a set of configurable rules as soon as they appear","archived":false,"fork":false,"pushed_at":"2026-04-10T10:27:25.000Z","size":107,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-10T12:17:51.872Z","etag":null,"topics":["auditd","golang","monitoring","security"],"latest_commit_sha":null,"homepage":"https://www.magenx.com","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/magenx.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":"audit.go","citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-26T11:48:53.000Z","updated_at":"2026-04-10T10:27:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/magenx/tuzik","commit_stats":null,"previous_names":["magenx/tuzik"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/magenx/tuzik","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magenx%2Ftuzik","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magenx%2Ftuzik/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magenx%2Ftuzik/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magenx%2Ftuzik/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magenx","download_url":"https://codeload.github.com/magenx/tuzik/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magenx%2Ftuzik/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32149497,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T17:06:48.269Z","status":"ssl_error","status_checked_at":"2026-04-22T17:06:19.037Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auditd","golang","monitoring","security"],"created_at":"2026-04-22T18:32:58.171Z","updated_at":"2026-04-22T18:32:59.410Z","avatar_url":"https://github.com/magenx.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tuzik\n\u003cimg width=\"122\" height=\"122\" alt=\"tuzik\" src=\"https://github.com/user-attachments/assets/c336567f-08f6-4d10-90b0-a4854addacdc\" /\u003e\n\nA little daemon doggy shepherd that watches over your backyard and protects you from intruders. \n  \nGo daemon for Linux that reads audit events from the **audisp-af_unix** Unix domain socket\nand automatically **deletes** or **quarantines** (moves) files that match a set of\nconfigurable rules as soon as they appear.\n\nThis is the same transport used by SIEM systems: `audispd` dispatches fully-formatted\naudit records over the socket so tuzik requires no direct kernel access and no special\ncapabilities beyond read permission on the socket.\n\nWhy I adopted Tuzik  \n\nMost security tools wait for the post-mortem. By then, the damage is done.\nI wanted something different. Something that acts instantly. That’s why I brought Tuzik into my stack.\nTuzik isn’t your average guard dog. He’s built on a philosophy of immutable loyalty and real-time action:\n- Immutable \u0026 Lockdown System – Tuzik is loyal only to his master. No exceptions.\n- Strict Configuration-Based Logic – You tell him who, what, and where. He handles the rest.\n- Kernel Audit Events – The moment something changes, Tuzik listens. He makes event-based decisions to instantly quarantine, delete, or restore files.\n- Zero Tolerance for Tampering – You won’t even execute a modified file. That’s how fast the kernel audit event is processed.\n- No More \"Post-Mortem\" Panic – No waiting 5 hours for a security scan while customer data is already being exfiltrated. Tuzik acts now.\n- Ignore the Noise – He doesn’t care about hashes, heuristics, or training patterns. He simply executes the policy: “Just do it.”\n\n## Requirements\n\n| Dependency | Version |\n|---|---|\n| Go | 1.26 |\n| auditd + audispd | any (Ubuntu/Debian: `apt install auditd`) |\n\nNo CGO or C library dependencies — tuzik is a pure Go binary.\n\n## Build\n\n```bash\nmake build       # produces ./tuzik\nmake install     # installs to /usr/local/sbin and /etc/tuzik/\n```\n\n## auditd / audispd setup\n\n### 1 — Enable the `af_unix` dispatcher plugin\n\nThe `audisp-af_unix` plugin ships with `audispd` (part of the `auditd` package on most\ndistributions).  Enable it by editing its configuration file:\n\n```\n# /etc/audit/plugins.d/af_unix.conf   (path may vary by distro)\nactive = yes\ndirection = out\npath = /sbin/audisp-af_unix\ntype = always\nargs = 0640 /var/run/audispd_events\nformat = string\n```\n\nThe `args` field sets the socket permissions and path.  Reload audispd to apply:\n\n```bash\nservice auditd restart   # or: kill -HUP $(pidof auditd)\n```\n\nAfter restarting you should see `/var/run/audispd_events` appear.\n\n### 2 — Add audit watch rules\n\nCreate watch rules in `/etc/audit/rules.d/tuzik.rules`:\n\n```\n# Watch the upload directory for write / attribute-change events.\n-w /var/www/uploads -p wa -k tuzik\n```\n\nReload the rules:\n\n```bash\naugenrules --load   # or: service auditd reload\n```\n\n## Configuration\n\nCopy `config.yaml` to `/etc/tuzik/config.yaml` and edit it:\n\n```yaml\n# tuzik configuration\n\n# When true, log what would happen but do not modify any files.\ndry_run: false\n\n# Path to the audisp-af_unix Unix domain socket created by the audispd plugin.\n# Default: /var/run/audispd_events\nsocket_path: /var/run/audispd_events\n\n# Audit key used to identify relevant events.\n# Must match the -k value used in your auditd rules.\naudit_key: \"tuzik\"\n\n# Absolute path to the Magento project root directory.\n# Required when maintenance=enable.\nproject_root: /home/magento/public_html\n\n# Enable or disable maintenance mode on file quarantine/delete actions.\n# When enabled, tuzik creates \u003cproject_root\u003e/var/.maintenance.flag which causes\n# Magento to return a 503 maintenance page, preventing customer exposure while\n# the incident is investigated.\n# Supported values: enable | disable\nmaintenance: disable\n\n# Enable or disable EcomScan security audits triggered by maintenance mode.\n# Requires maintenance=enable. When enabled, tuzik runs:\n# ecomscan --skip-dashboard --newonly --state-file \u003cecomscan_state_dir\u003e/ecomscan \u003cproject_root\u003e\n# Supported values: enable | disable\necomscan: disable\n\n# Optional: directory for the ecomscan state file.\n# Default: /var/log/tuzik\n# ecomscan_state_dir: /var/log/tuzik\n\n# Paths to watch for file-creation / write events.\n# tuzik reacts to PATH records in audit events whose key matches audit_key\n# and whose file path falls under one of these paths.\nwatch_paths:\n  - /home/magento/public_html/pub/media/\n  - /home/magento/public_html/pub/static/\n\n# Optional: paths to exclude from monitoring even if they fall under watch_paths.\n# Leave empty to process all paths under watch_paths.\nignore_paths: []\n\n# Optional: only act on files with these exact names (basename match).\n# Leave empty to match all filenames.\nfilenames: []\n\n# Optional: only act on files with these extensions.\n# A leading '.' is added automatically if omitted.\n# Leave empty to match all extensions.\nextensions:\n  - .php\n\n# Tuzik can be set to \"angry mode\", where it recursively monitors the entire project path for any file changes. \n# This mode is only functional in Magento atomic deployments running in production mode, \n# and it requires that correct read-only permissions and ACLs are properly configured. \n# It operates under the condition that PHP only reads files (there are no write operations between deployments).\n\n# Action to perform when a matching file is detected.\n# Supported values: delete | quarantine\naction: quarantine\n\n# Required when action=quarantine: directory where suspicious files are moved.\nquarantine_dir: /var/log/tuzik/quarantine\n\n# When false (default), symlinks found in watched directories are ignored.\n# Set to true to process symlinks as regular files.\nallow_symlinks: false\n```\n\n### CLI flags (override config)\n\n```\n-config           path to YAML config file (default: config.yaml)\n-socket           override socket_path (audisp-af_unix socket)\n-audit-key        override audit_key\n-action           override action (delete|quarantine)\n-quarantine-dir   override quarantine_dir\n-dry-run          enable dry-run mode\n-allow-symlinks   enable symlink processing\n```\n\n## Usage\n\ntuzik connects to the `audisp-af_unix` socket; the process must be able to read that\nsocket (permissions set in `af_unix.conf`).  Typically run as **root**:\n\n```bash\nsudo ./tuzik -config /etc/tuzik/config.yaml\n```\n\nOn startup it:\n1. Connects to the audisp-af_unix Unix domain socket.\n2. Reads `type=X msg=audit(…): …` lines dispatched by audispd; when a complete event\n   group (SYSCALL + PATH + EOE) contains the configured `audit_key` **and** a PATH record\n   whose file matches the configured rules, it executes the configured action.\n3. On `SIGTERM` / `SIGINT`, closes the socket and exits cleanly.\n\n## systemd\n\n### Install and start\n\nAfter running `make install`, the unit file is placed at `/lib/systemd/system/tuzik.service`.\nEnable and start the service:\n\n```bash\nsystemctl daemon-reload\nsystemctl enable --now tuzik\nsystemctl status tuzik\n```\n\nCheck logs with:\n\n```bash\njournalctl -u tuzik -f\n```\n\n### Adjusting `ReadWritePaths`\n\nThe unit file ships with example paths that match the defaults in `config.yaml`:\n\n```ini\nReadWritePaths=/home/magento/public_html/pub/media\nReadWritePaths=/home/magento/public_html/pub/static\nReadWritePaths=/var/tuzik/quarantine\n```\n\nThese must cover every directory listed under `watch_paths` **and** `quarantine_dir` in\n`/etc/tuzik/config.yaml`.  If you change those config values, create a drop-in override\nto add or replace the paths, then reload systemd:\n\n```bash\nsystemctl edit tuzik   # opens a drop-in override file in $EDITOR\n```\n\nTo replace all `ReadWritePaths`, reset the list first then set the new values:\n\n```ini\n[Service]\nReadWritePaths=\nReadWritePaths=/your/watch/path1\nReadWritePaths=/your/watch/path2\nReadWritePaths=/your/quarantine/dir\n```\n\nAfter saving the drop-in:\n\n```bash\nsystemctl daemon-reload\nsystemctl restart tuzik\n```\n\n## Tests\n\n```bash\nmake test\n```\n\nUnit tests cover config loading, line parsing, field parsing, socket reading,\npath matching, and file actions (delete / quarantine / dry-run / symlink handling)\nwithout requiring auditd or root privileges.\n\n## Architecture\n\n| File | Purpose |\n|---|---|\n| `main.go` | Entry point, CLI flags, daemon loop, signal handling |\n| `config.go` | YAML config loading and validation |\n| `audit.go` | `SocketListener` — reads `type=X msg=…` lines from the audisp-af_unix socket |\n| `handler.go` | Audit event parsing, grouping by serial, match evaluation |\n| `action.go` | File delete / quarantine implementation |\n| `tuzik_test.go` | Unit tests |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagenx%2Ftuzik","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagenx%2Ftuzik","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagenx%2Ftuzik/lists"}