A Kernel Boot Line From the Internet: What We Kept After Reviewing It Line by Line

The last post covered sysctl, which you change at runtime. This one is a different animal: boot parameters written into GRUB and handed to the kernel at startup (the kernel command line). They differ from sysctl in one fundamental way — a bad sysctl you can roll back, but a bad boot parameter can leave the machine unable to boot at all, with no error visible over SSH. You’re going to the IPMI/serial console to rescue it.

This string isn’t ours. It’s a “tuned kernel boot line” that circulates online, and people paste the whole thing into GRUB_CMDLINE_LINUX and reboot. We’re keeping it here in full, but let’s be clear: this is not a recommended config, it’s a reference we audited line by line. A fair chunk of it we flatly refuse to enable on production boxes, and we’ll say why below. Reading it grouped by purpose is far more useful than treating it as one long incantation.

An iron rule first: before you touch boot parameters, make sure you have out-of-band management (IPMI/iDRAC/serial) that can reach GRUB. If you don’t have out-of-band and the box is in a remote facility, don’t touch these.

Logging, audit, and boot display

ParameterEffect
loglevel=3Kernel console print level set to 3, less console spam.
rd.udev.log_priority=3udev log level in initramfs set to 3.
rd.systemd.show_status=autoShow systemd status automatically at boot.
log_buf_len=2MKernel log ring buffer set to 2M, keeps more history for debugging.
audit=1Enable the kernel audit subsystem.

This group is basically harmless and we keep it. The one caveat: audit=1 has a noticeable cost on boxes with heavy syscall rates, so drop it if you have no compliance requirement.

cgroups and containers

ParameterEffect
systemd.unified_cgroup_hierarchy=falseDisable the cgroup v2 unified hierarchy, fall back to v1.
systemd.legacy_systemd_cgroup_controller=falseDisable the legacy systemd cgroup controller.
cgroup_enable=memoryEnable the memory cgroup.
cgroup_memory=nokmemDisable kmem accounting (a historical memory-leak workaround).
swapaccount=1Enable swap accounting, needed to limit swap per container.

These decide which cgroup version the container runtime gets. Be careful forcing a fall back to cgroup v1: modern container runtimes (containerd, recent podman) increasingly default to v2, and falling back to v1 can make newer tooling misbehave. Our rule is to follow the runtime version actually in use rather than reflexively reverting to v1.

Storage and I/O

ParameterEffect
scsi_mod.use_blk_mq=1Enable block-layer multi-queue (blk-mq), meaningful for NVMe/multi-queue SSDs.

On our NVMe/ZFS boxes blk-mq is the default and what we want, so this can stay; on recent kernels it’s effectively the default behavior already.

Memory management and huge pages

ParameterEffect and risk
transparent_hugepage=neverDisable Transparent Huge Pages (THP). On latency-sensitive memory workloads like databases and the ZFS ARC, turning THP off is usually right — it avoids the latency spikes from THP compaction. One of the few we recommend outright.
cma=128MReserve 128M of contiguous memory for CMA. Only specific devices (certain DMA) need it; without that hardware it’s just wasted memory.
init_on_free=0, init_on_alloc=0Disable zeroing memory on alloc/free. Trades a little performance for giving up a layer of info-leak hardening — a direct security-versus-performance tradeoff.
vsyscall=noneDisable the old vsyscall interface, tightens the attack surface, safe on modern systems.

Note the source writes domain init_on_free=0, init_on_alloc=0, with a stray domain and a comma. That’s paste noise: the real kernel parameters are just init_on_free=0 and init_on_alloc=0, with no comma between them. Copying it verbatim makes the kernel treat domain as an unrecognized parameter.

CPU power and frequency (chasing low latency)

ParameterEffect and risk
intel_pstate=disableDisable the intel_pstate scaling driver.
processor.max_cstate=0 / intel_idle.max_cstate=0Forbid the CPU from entering deep C-states.
idle=haltUse halt when idle rather than a deeper power-saving state.
cpufreq.off=1Disable frequency scaling.
pcie_aspm=offDisable PCIe power saving.
thermal.off=1Disable thermal control.

This whole group is the classic “trade power for latency”: pin the CPU at high frequency and don’t let it sleep, in exchange for steady low-latency response. It makes sense for real-time forwarding or low-latency trading workloads. The cost is direct: power draw and heat rise sharply, and your power bill and facility cooling have to keep up. And thermal.off=1 deserves special caution — turning off thermal control means the kernel no longer throttles to protect against overheating, so a genuine cooling problem can cook the hardware. We don’t enable that one on production boxes. An ordinary application box has no need for this group at all.

Interrupts, locking, and RCU

ParameterEffect and risk
threadirqsMove hard-IRQ handling into kernel threads, easier to schedule and isolate.
nosoftlockupDisable soft-lockup detection.
nmi_watchdog=0Disable the NMI watchdog, saves a little per-core overhead.
rcu_nocbs=0-64Offload RCU callbacks for CPUs 0–64 elsewhere, used with CPU isolation for low latency.
rcupdate.rcu_expedited=1Expedite RCU grace periods, lowers latency at a slight CPU cost.
rcutree.kthread_prio=2Raise the priority of the RCU kernel threads.
skew_tick=1Stagger per-core timer interrupts to reduce jitter from simultaneous wakeups.
no_timer_checkSkip the timer IRQ routing check, saves a little boot time.
noreplace-smpDisable SMP-related code replacement optimization.

This group is for a low-latency box you’ve specifically tuned for CPU isolation. In particular, rcu_nocbs=0-64 only matters when you’ve actually used isolcpus/nohz_full to isolate those cores; otherwise it does nothing. nosoftlockup + nmi_watchdog=0 again turns off the detection we treated as a safety net in the last post — you save the overhead and lose the means to notice a hang. Be clear about that tradeoff.

Virtualization and IOMMU

ParameterEffect
intel_iommu=on / amd_iommu=onEnable the IOMMU, a prerequisite for PCI passthrough.
iommu.strict=0Non-strict mode, defers TLB flushes for performance at the cost of slightly weaker isolation for passthrough devices.
kvm-intel.nested=1Enable nested virtualization.
kvm-intel.vmentry_l1d_flush=neverDisable the L1D flush on VM entry — one of the L1TF mitigations, see the security section below.
pci=reallocAllow reallocating PCI resources, fixes insufficient BAR space on some devices.

For GPU/NIC passthrough intel_iommu=on is mandatory. iommu.strict=0 and the various flush=never flags all trade isolation for performance — think hard in a multi-tenant environment.

NIC naming

ParameterEffect
net.ifnames=0Disable systemd’s predictable NIC naming, back to traditional names like eth0.
biosdevname=0Likewise disable BIOS-style naming.

These two are purely an ops-style choice. The upside is short names that are easy to script; the downside is that on multi-NIC boxes traditional naming order isn’t stable, so names can swap after you reseat a card, which makes automation easier to trip over. We only use this on boxes where the NICs are fixed and bound by MAC.

Graphics

ParameterEffect and risk
nomodesetDisable Kernel Mode Setting (KMS).
vt.cur_default=50Set the virtual-terminal cursor.

nomodeset deserves to be called out: it disables mode setting in the kernel graphics driver. It may not matter for a pure server, but on a machine that needs the graphics driver to work (the GPU node in the previous post, for instance), nomodeset will keep the driver from coming up. Whether a parameter like this is “good” depends entirely on the machine’s role; you can’t copy it blindly.

Security mitigations — the highest-risk group

mitigations=off noibrs nopti l1tf=off nospec_store_bypass_disable noibpb spectre_v2_user=off spectre_v2=off
ParameterEffect
mitigations=offTurn off all CPU vulnerability mitigations at once (this one line equals everything below).
noptiDisable KPTI (the Meltdown mitigation).
noibrs / noibpb / spectre_v2=off / spectre_v2_user=offDisable the Spectre v2 mitigations.
l1tf=offDisable the L1TF (L1 Terminal Fault) mitigation.
nospec_store_bypass_disableDisable the SSB mitigation.

This is the part of the whole string we most need to warn about. Turning these mitigations off does win back the performance the Meltdown/Spectre patches cost, and on some compute-heavy workloads the gain is real. But the price is exposing the machine to known side-channel vulnerabilities. On a multi-tenant box, one running other people’s code, or any machine with not-fully-trusted workloads, never enable it — it’s tearing down the CPU’s security isolation on purpose. Only consider it on a physically isolated, single-tenant box where you’ve confirmed the workload is fully trusted and you’ve actually measured the bottleneck here, and record it as an explicit risk decision rather than pasting it into GRUB offhand.

Everything else

ParameterEffect and risk
selinux=0Disable SELinux. Less hassle, but also removes a layer of mandatory access control.
mce=offDisable Machine Check Exceptions. Dangerous: MCE is how the hardware reports memory/CPU errors, so disabling it means going blind to hardware faults in progress. We don’t enable it.
noresumeDisable resume from hibernation; servers don’t hibernate anyway, so harmless.
workqueue.power_efficient=0Disable power-efficient workqueues, favors performance.
cryptomgr.notestsSkip the crypto self-tests at boot, saves a little boot time.
nosyncDisable related busy-wait behavior.
nf_conntrack.acct=0Disable conntrack flow accounting, saves a little per-connection overhead — somewhat meaningful on the hundreds-of-thousands-of-connections box from the last post.
crashkernel=384M-2G:64M,2G-:128MReserve crash-kernel memory for kdump, scaled by physical RAM. Keep it if you want crash dumps.

Full reference (kept verbatim)

Below is the complete single line from the source. Once more: this is not a config to copy. It’s a thing to evaluate. Decide the mitigations=off group, mce=off, thermal.off=1, and nomodeset explicitly based on the machine’s role, and clean up the domain ... , paste noise.

loglevel=3 selinux=0 audit=1 rd.systemd.show_status=auto rd.udev.log_priority=3 systemd.unified_cgroup_hierarchy=false systemd.legacy_systemd_cgroup_controller=false scsi_mod.use_blk_mq=1 crashkernel=384M-2G:64M,2G-:128M workqueue.power_efficient=0 domain init_on_free=0, init_on_alloc=0 cma=128M vsyscall=none nosoftlockup mce=off threadirqs noresume nmi_watchdog=0 vt.cur_default=50 transparent_hugepage=never cgroup_enable=memory cgroup_memory=nokmem swapaccount=1 nf_conntrack.acct=0 log_buf_len=2M intel_pstate=disable processor.max_cstate=0 intel_idle.max_cstate=0 thermal.off=1 pci=realloc pcie_aspm=off cpufreq.off=1 idle=halt net.ifnames=0 biosdevname=0 mitigations=off noibrs nopti l1tf=off nomodeset nospec_store_bypass_disable noibpb spectre_v2_user=off spectre_v2=off kvm-intel.vmentry_l1d_flush=never no_timer_check noreplace-smp kvm-intel.nested=1 nosync iommu.strict=0 intel_iommu=on amd_iommu=on cryptomgr.notests rcu_nocbs=0-64 rcupdate.rcu_expedited=1 rcutree.kthread_prio=2 skew_tick=1

The right way to do this: pick the handful of flags that match your machine’s role, add one group at a time, run grub2-mkconfig, reboot, confirm from the out-of-band console that it comes up, then verify that what you turned off didn’t break anything. There is no “one universal boot line” to copy — every machine’s role is different, and so is which flag helps and which one kills it.

Published At (Updated At) Tagged with