Run usg fix as your first move and you find out what CIS hardening breaks in production, so audit first and remediate only once you know. The examples use Ubuntu Security Guide, or usg, version 24.04.8, installed with Ubuntu 24.04 benchmark data.
Allow 20 to 30 minutes for an audit and review. You need a shell, the usg package, and sudo access. The audit writes reports but does not remediate the host. The fix command is different: it changes the running system and requires a reboot, so it is deliberately not used as the first test.
Checkpoint: Keep this guide at the audit and review stage until you have a maintenance window, a recovery plan, and an inventory of applications that could be affected by hardening.
Check the binary and package version. These are ordinary read-only commands:
$ command -v usg
/usr/sbin/usg
$ dpkg-query -W -f='${Package} ${Version}\n' usg
usg 24.04.8
On this installation, usg refuses to run its commands unless it is started with super-user privileges. Use sudo usg ... for the operational examples below. The privilege is needed by the tool and its OpenSCAP checks, not because listing or auditing should modify your policy.
Checkpoint: Verify the command can display its usage through the same privilege boundary:
$ sudo usg --help
usg [command] [command options] [command arguments]
The exact usage text can vary slightly with the installed build. If sudo reports that usg is not found, check the path from command -v and your sudo policy before continuing.
Ask usg for the supported profiles:
$ sudo usg list
The command lists supported profiles only. Add --all when you need to see deprecated profile versions too:
$ sudo usg list --all
Do not copy a profile name from a different Ubuntu release or from an old report. On the installed benchmark data, the profile families include:
cis_level1_servercis_level2_servercis_level1_workstationcis_level2_workstationcis_level1_server_ec2stigChoose the profile that matches the machine's role. Level 2 generally has greater usability impact than Level 1, and a workstation profile is not a server profile with a different label.
Checkpoint: Save the exact profile name in a shell variable, then inspect its details:
PROFILE='cis_level1_server'
sudo usg info "$PROFILE"
Replace cis_level1_server with the result that fits your host. If the profile is not accepted, return to sudo usg list rather than guessing a spelling.
Audit the selected profile before generating or applying fixes:
$ sudo usg audit cis_level1_server
audit checks whether the profile's rules are met. It writes a user-friendly HTML report and an extensive XML result file at these default locations:
/var/lib/usg/usg-report-DATE.html for the HTML report./var/lib/usg/usg-results-DATE.xml for detailed results.List the newest reports after the command finishes:
sudo find /var/lib/usg -maxdepth 1 -type f \( -name 'usg-report-*.html' -o -name 'usg-results-*.xml' \) -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort
Read the HTML report in a browser and keep the XML result with your change record. A failed rule is evidence about the host at audit time, not an instruction to apply every remediation blindly. Investigate services, application dependencies, and the reason for the failure first.
Checkpoint: You should have a profile name, an audit result, and a report path before making a tailoring file or running any remediation.
A tailoring file is XML that selects the rules to include and can set rule variables. Generate one from the profile into a review directory:
sudo install -d -m 0750 /root/usg-review
sudo usg generate-tailoring cis_level1_server /root/usg-review/cis_level1_server-tailoring.xml
sudo ls -l /root/usg-review/cis_level1_server-tailoring.xml
This is a generated file, not a live policy change. Open it and make only documented changes: a rule can be excluded with an xccdf:select element whose selected value is false, and a rule variable can be customised with xccdf:set-value. Use the usg-rules and usg-variables manual pages to identify valid rule and variable names; do not invent identifiers from a report heading.
For example, the manpage describes disabling a specific rule with:
<xccdf:select idref="sshd_set_loglevel_info_or_verbose" selected="false"/>
Only make an exception when you can explain its owner, reason, scope, and review date. A tailoring file is tied to a major profile version; it is not automatically compatible with another major version, even when the benchmark name looks similar.
To abandon an unapproved generated file, remove that file from the review directory. This does not undo an audit and does not change the host:
sudo rm -- /root/usg-review/cis_level1_server-tailoring.xml
Warning: The removal is irreversible unless you have another copy. Keep an approved tailoring file in version-controlled change records instead of editing the only copy in place.
Generate a Bash script from the profile or tailoring file. Generation still does not apply the commands:
sudo usg generate-fix \
--output /root/usg-review/cis_level1_server-fix.sh \
--tailoring-file /root/usg-review/cis_level1_server-tailoring.xml
sudo sed -n '1,220p' /root/usg-review/cis_level1_server-fix.sh
The --output option belongs to generate-fix. If you pass --tailoring-file, the profile argument is ignored, so do not provide a conflicting profile name and assume it wins. Check the script for changes to authentication, SSH access, filesystems, services, logging, and application assumptions. Test in a disposable or recently provisioned system where possible.
There is also a narrower remediation mode:
$ sudo usg fix --only-failed cis_level1_server
This still changes the host and still requires a reboot. The option limits remediation to rules that fail the initial audit; it does not make the operation safe, reversible, or suitable for a production host without review.
Do not run fix as a way to discover what it does. It audits and remediates in one operation, changes the running system, and may stop applications from functioning. Take a backup or snapshot, record the current access path, arrange console access, and schedule the required reboot.
When the change window is approved, use the reviewed profile or tailoring file:
sudo usg fix --tailoring-file /root/usg-review/cis_level1_server-tailoring.xml
sudo reboot
The reboot is a separate, explicit command. The manpage says it is required for the fixes to be fully applied. There is no general usg undo command; recovery comes from your snapshot, backup, documented manual reversions, or the platform's console access. After the host returns, run the same audit again and compare the new report with the pre-change result.
sudo usg audit --tailoring-file /root/usg-review/cis_level1_server-tailoring.xml
sudo find /var/lib/usg -maxdepth 1 -type f -name 'usg-report-*.html' -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort
usg version and used the required privilege boundary.sudo usg list, not from an unverified example.