{
  "id": "CB-UBU-AUDIT-001",
  "standard": "ubuntu",
  "version": "0.1.0",
  "url": "https://baselines.cirsec.org/b/ubuntu/v0.1.0/CB-UBU-AUDIT-001",
  "json": "https://baselines.cirsec.org/b/ubuntu/v0.1.0/CB-UBU-AUDIT-001.json",
  "yaml": "https://baselines.cirsec.org/b/ubuntu/v0.1.0/CB-UBU-AUDIT-001.yml",
  "profiles_effective": [
    "core",
    "server",
    "server-hardened",
    "desktop",
    "desktop-hardened"
  ],
  "license": "Text CC BY 4.0, code Apache-2.0",
  "attribution": "CIRSEC Baselines, https://baselines.cirsec.org",
  "control": {
    "id": "CB-UBU-AUDIT-001",
    "title": "Keep the systemd journal running, persistent, compressed and bounded in size",
    "finding": {
      "title": "System logs may be lost at reboot or fill the disk",
      "description": "Without a persistent and bounded journal, the history of the system disappears at reboot or grows until the file system is full."
    },
    "status": "active",
    "profiles": [
      "core"
    ],
    "risk": {
      "severity": "medium"
    },
    "assessment": "automated",
    "tags": [
      "journald",
      "logging"
    ],
    "description": "`systemd-journald` collects the messages of the kernel, of services and of programs that use\nsyslog. Its settings live in `/etc/systemd/journald.conf` and drop-in files in\n`/etc/systemd/journald.conf.d/`. This control requires:\n\n- the `systemd-journald` service to run;\n- `Storage=persistent`, so the journal is written to `/var/log/journal/` and survives reboots;\n- `Compress=yes` (the default), so large entries are compressed;\n- an explicit size budget: `SystemMaxUse={{ max_use }}` and `SystemKeepFree={{ keep_free }}`.\n  journald removes the oldest archived files to stay within these limits.\n",
    "rationale": "Logs are the first source when investigating an incident. A journal kept only in memory is lost\nat every reboot, which is also what an intruder triggers to erase traces. An explicit size\nbudget makes rotation predictable and keeps the journal from filling the file system.\n",
    "impact": "Journal files use up to {{ max_use }} on the file system holding `/var/log`. The oldest entries\nare removed when the budget is reached; keep a remote copy (CB-UBU-AUDIT-008) when a longer\nhistory is required.\n",
    "notes": "On Ubuntu 20.04 to 26.04 the default is `Storage=auto` and `/var/log/journal/` exists, so the journal\nis already persistent; the control asks for an explicit setting so that removing the directory\ndoes not silently switch to memory-only logging.\n",
    "setting": {
      "location": "/etc/systemd/journald.conf.d/60-cirsec.conf",
      "default_value": "Storage=auto, Compress=yes, size limits computed from the file system size",
      "recommended_value": "Storage=persistent, Compress=yes, SystemMaxUse={{ max_use }}, SystemKeepFree={{ keep_free }}"
    },
    "parameters": [
      {
        "name": "max_use",
        "type": "string",
        "description": "Maximum disk space used by the persistent journal (journald size syntax, for example 1G or 500M).",
        "default": "1G"
      },
      {
        "name": "keep_free",
        "type": "string",
        "description": "Disk space journald leaves free on the file system holding /var/log/journal.",
        "default": "1G"
      }
    ],
    "audit": {
      "manual": "1. Run `systemctl is-active systemd-journald`. It must print `active`.\n2. Run `systemd-analyze cat-config systemd/journald.conf`. The last value of each setting must be\n   `Storage=persistent`, `Compress=yes` (or no `Compress=` line), `SystemMaxUse={{ max_use }}`\n   and `SystemKeepFree={{ keep_free }}`.\n",
      "checks": [
        {
          "id": "active",
          "engine": "shell",
          "description": "State of the systemd-journald service.",
          "spec": {
            "script": "o=$(systemctl is-active systemd-journald 2>/dev/null)\necho \"systemd-journald: ${o:-unknown}\"\n[ \"$o\" = active ]\n"
          }
        },
        {
          "id": "storage",
          "engine": "shell",
          "description": "Effective Storage= of journald.",
          "spec": {
            "script": "v=$(systemd-analyze cat-config systemd/journald.conf 2>/dev/null | sed -n 's/^[[:space:]]*Storage=//p' | tail -n 1)\necho \"Storage=${v:-auto (default)}\"\n[ \"$v\" = persistent ]\n"
          }
        },
        {
          "id": "compress",
          "engine": "shell",
          "description": "Effective Compress= of journald.",
          "spec": {
            "script": "v=$(systemd-analyze cat-config systemd/journald.conf 2>/dev/null | sed -n 's/^[[:space:]]*Compress=//p' | tail -n 1)\necho \"Compress=${v:-yes (default)}\"\ncase ${v:-yes} in yes | true | on | 1) exit 0 ;; esac\nexit 1\n"
          }
        },
        {
          "id": "size",
          "engine": "shell",
          "description": "Effective SystemMaxUse= and SystemKeepFree= of journald.",
          "spec": {
            "script": "c=$(systemd-analyze cat-config systemd/journald.conf 2>/dev/null)\nm=$(printf '%s\\n' \"$c\" | sed -n 's/^[[:space:]]*SystemMaxUse=//p' | tail -n 1)\nk=$(printf '%s\\n' \"$c\" | sed -n 's/^[[:space:]]*SystemKeepFree=//p' | tail -n 1)\necho \"SystemMaxUse=${m:-default} SystemKeepFree=${k:-default}\"\n[ \"$m\" = \"$CB_MAX_USE\" ] && [ \"$k\" = \"$CB_KEEP_FREE\" ]\n"
          }
        }
      ]
    },
    "remediation": {
      "manual": "1. Create `/etc/systemd/journald.conf.d/60-cirsec.conf` with:\n   ```\n   [Journal]\n   Storage=persistent\n   Compress=yes\n   SystemMaxUse={{ max_use }}\n   SystemKeepFree={{ keep_free }}\n   ```\n2. Run `systemctl restart systemd-journald`.\n",
      "effects": {
        "restart": "service",
        "services": [
          "systemd-journald"
        ],
        "disruption": "none",
        "lockout_risk": false
      },
      "rollback": "Delete `/etc/systemd/journald.conf.d/60-cirsec.conf` and run `systemctl restart systemd-journald`.\n",
      "scripts": [
        {
          "id": "dropin",
          "engine": "shell",
          "content": "f=/etc/systemd/journald.conf.d/60-cirsec.conf\nmkdir -p /etc/systemd/journald.conf.d\ncb_backup \"$f\"\nprintf '%s\\n' '# Written by CIRSEC Baselines CB-UBU-AUDIT-001' '[Journal]' 'Storage=persistent' 'Compress=yes' \\\n  \"SystemMaxUse=$CB_MAX_USE\" \"SystemKeepFree=$CB_KEEP_FREE\" >\"$f\"\nchmod 644 \"$f\"\nsystemctl start systemd-journald\n"
        }
      ]
    },
    "references": [
      {
        "title": "journald.conf(5), Ubuntu manual pages",
        "url": "https://manpages.ubuntu.com/manpages/noble/man5/journald.conf.5.html",
        "publisher": "Canonical",
        "kind": "vendor-doc",
        "accessed": "2026-10-19"
      },
      {
        "title": "ANSSI-BP-028 v2.0 - Recommandations de configuration d'un système GNU/Linux (R71)",
        "url": "https://messervices.cyber.gouv.fr/documents-guides/fr_np_linux_configuration-v2.0.pdf",
        "publisher": "ANSSI",
        "kind": "guide",
        "accessed": "2026-10-19"
      }
    ],
    "mappings": [
      {
        "framework": "anssi-linux",
        "framework_version": "2.0",
        "id": "R71",
        "relation": "partial",
        "note": "R71 asks for a logging system; this control covers the local journal."
      },
      {
        "framework": "nist-800-53r5",
        "framework_version": "5.1.1",
        "id": "AU-4",
        "relation": "related"
      },
      {
        "framework": "nist-800-53r5",
        "framework_version": "5.1.1",
        "id": "AU-11",
        "relation": "related"
      }
    ],
    "threats": [
      {
        "framework": "mitre-attack",
        "id": "T1070.002"
      },
      {
        "framework": "cwe",
        "id": "CWE-778"
      }
    ],
    "related_controls": [
      {
        "id": "CB-UBU-AUDIT-002",
        "type": "related"
      },
      {
        "id": "CB-UBU-AUDIT-008",
        "type": "related"
      }
    ],
    "authors": [
      {
        "name": "Alice",
        "github": "Sn0wAlice"
      }
    ],
    "verified": [
      {
        "date": "2026-10-19",
        "by": "Sn0wAlice",
        "versions": [
          "20.04"
        ],
        "environment": "Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic",
        "notes": "Fails on stock image (Storage=auto, no size budget); drop-in fixes it, journald restarted; passes after reboot."
      },
      {
        "date": "2026-10-19",
        "by": "Sn0wAlice",
        "versions": [
          "22.04"
        ],
        "environment": "Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic",
        "notes": "Fails on stock image (Storage=auto, no size budget); drop-in fixes it, journald restarted; passes after reboot."
      },
      {
        "date": "2026-10-19",
        "by": "Sn0wAlice",
        "versions": [
          "24.04"
        ],
        "environment": "Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic",
        "notes": "Fails on stock image (Storage=auto, no size budget); drop-in fixes it, journald restarted; passes after reboot."
      },
      {
        "date": "2026-10-19",
        "by": "Sn0wAlice",
        "versions": [
          "26.04"
        ],
        "environment": "Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic",
        "notes": "Fails on stock image (Storage=auto, no size budget); drop-in fixes it, journald restarted; passes after reboot."
      }
    ],
    "introduced_in": "0.1.0",
    "created": "2026-10-19",
    "updated": "2026-10-19"
  }
}