The setting works until you reboot
You configured a kernel parameter to fix a networking issue or improve desktop performance. You ran the command. The setting changed. You rebooted the machine. The setting vanished. You ran the command again. It worked. You rebooted. It broke again.
You are not doing anything wrong. The Linux kernel is designed to be volatile by default. Changes made to the running kernel state are lost when the system powers off. The kernel does not save your configuration to disk. You must explicitly tell the system to write the configuration to a file and load that file at boot.
This article covers how to change parameters immediately, how to make them permanent, and how to debug why a setting refuses to stick.
How the kernel stores parameters
The Linux kernel exposes tunable parameters through the /proc/sys/ virtual filesystem. This is not a real directory on your disk. It is a mirror of the kernel's internal state generated on the fly.
When you read a file in /proc/sys/, the kernel returns the current value of that parameter. When you write to a file, the kernel updates the parameter immediately. The sysctl command is a wrapper that makes reading and writing these files easier. It translates dot-notation names like net.ipv4.ip_forward into the corresponding path /proc/sys/net/ipv4/ip_forward.
Because /proc/sys/ reflects live state, any modification is temporary. A reboot resets the kernel state to the defaults defined by the kernel source and the initial ramdisk. To survive a reboot, you need a persistent configuration file that the system reads during startup.
Fedora uses systemd to manage boot. The systemd-sysctl.service unit reads configuration files from /usr/lib/sysctl.d/ and /etc/sysctl.d/ and applies them in order. This is the mechanism that makes your changes permanent.
Apply a change at runtime
Use runtime changes to test a value before committing it to disk. If a value breaks your network or freezes the system, a reboot restores the default. Never guess at a value for a production server. Test it first.
Here's how to change a parameter immediately without editing any files.
# WHY: -w writes the value to the running kernel.
# WHY: Changes take effect instantly but are lost on reboot.
sudo sysctl -w net.ipv4.ip_forward=1
The command returns the new value to confirm the write succeeded. If you see an error like error: permission denied on key 'net.ipv4.ip_forward', you forgot sudo. Kernel parameters require root privileges to modify.
Runtime changes are useful for quick debugging. They are also the only way to change certain parameters that cannot be modified via configuration files due to security restrictions. Most standard parameters, however, can be set persistently.
Make the change permanent
Persistence requires a configuration file in /etc/sysctl.d/. Fedora's package manager drops default configuration files in /usr/lib/sysctl.d/. You should never edit files in /usr/lib/. Those files belong to packages and will be overwritten on updates. Always create your own files in /etc/sysctl.d/.
Files in /etc/sysctl.d/ override files in /usr/lib/sysctl.d/. The system reads files in lexicographic order. Files with higher numbers are processed last and take precedence. A file named 99-custom.conf will override 10-default.conf.
Here's how to create a persistent configuration file and apply it.
# WHY: tee writes stdin to the file. sudo runs tee as root so it can write to /etc.
# WHY: The heredoc passes the config content to tee.
sudo tee /etc/sysctl.d/99-custom.conf <<'EOF'
# WHY: Comments start with #. sysctl ignores blank lines and comments.
# WHY: Spaces around the equals sign are allowed and improve readability.
# WHY: This enables IP forwarding for virtual machines and VPNs.
net.ipv4.ip_forward = 1
# WHY: This reduces the tendency to swap memory to disk.
# WHY: Lower values mean the kernel prefers keeping data in RAM.
vm.swappiness = 10
EOF
# WHY: --system reads all drop-in files from /usr/lib and /etc in order.
# WHY: This applies changes immediately without a reboot.
sudo sysctl --system
The sysctl --system command is the standard way to reload configuration. It processes all files in the correct order and applies them. You do not need to reboot. If you only want to apply a single file, you can use sysctl -p /etc/sysctl.d/99-custom.conf, but --system is safer because it respects the full precedence chain.
How file precedence works
Conflicts happen when multiple files define the same parameter. The system applies the last value it reads. Understanding the load order prevents hours of debugging.
The systemd-sysctl.service unit loads files in this sequence:
/usr/lib/sysctl.d/*.conf/etc/sysctl.d/*.conf
Within each directory, files are sorted by name. Numeric prefixes determine priority. 10-network.conf loads before 50-security.conf. If both files set net.ipv4.ip_forward, the value in 50-security.conf wins.
This design allows packages to provide defaults while letting administrators override them. A package might set vm.swappiness = 60 in /usr/lib/sysctl.d/10-default.conf. You can override it by creating /etc/sysctl.d/99-custom.conf with vm.swappiness = 10. Your file loads later and takes effect.
If you are unsure which file is setting a value, check the dry run output.
# WHY: --dry-run shows the order files are processed without applying changes.
# WHY: This helps you find which file is overriding your setting.
sudo sysctl --system --dry-run
The output lists every file and the parameters it sets. Look for your parameter in the list. The last occurrence is the active value. If you see your parameter set in a file you didn't create, another package or script is managing it.
Common parameters and what they actually do
Kernel parameters control everything from network routing to memory management. Changing the wrong value can degrade performance or break connectivity. Here are the most common parameters and their real-world effects.
net.ipv4.ip_forward = 1
Enable this when your machine routes traffic between networks. Virtual machines, VPN servers, and Docker bridges require IP forwarding. Without it, packets arrive at the host but never leave. The default is 0 for security. Only enable it if you are running a router or NAT service.
vm.swappiness = 10
Swappiness controls how aggressively the kernel moves pages from RAM to swap. The value ranges from 0 to 100. A value of 10 tells the kernel to avoid swapping unless memory pressure is high. This improves desktop responsiveness on systems with sufficient RAM. A value of 0 does not disable swap. It only prevents swapping when memory is available. Swap is still used for anonymous pages that cannot be reclaimed.
fs.inotify.max_user_watches = 524288
Development tools like Docker, Node.js, and Webpack use inotify to watch files for changes. The default limit is often too low for large projects. You will see errors like Error: EMFILE: too many open files or inotify watch limit reached. Raising this limit fixes the error. The value 524288 is a safe upper bound for most workstations.
net.core.somaxconn = 4096
This sets the maximum number of pending connections in the socket listen backlog. High-traffic web servers and load balancers need a larger backlog to handle connection bursts. The default is usually 128. Increasing it prevents dropped connections during spikes.
kernel.sysrq = 1
Enable the SysRq key for emergency recovery. If the system freezes, you can trigger a safe reboot or sync disks using keyboard shortcuts. This is useful for headless servers where you cannot physically power cycle the machine. Keep it disabled on shared desktops to prevent accidental triggers.
Verify and debug
After applying changes, verify the active values. The runtime state is the source of truth. Configuration files are just instructions.
# WHY: Query a specific parameter to see its current value.
sysctl net.ipv4.ip_forward
# WHY: List all parameters containing a keyword.
sysctl -a | grep swappiness
If the value does not match your configuration file, check for syntax errors. The sysctl parser is strict. A typo in the key name or a missing equals sign causes the line to be skipped. The command usually prints a warning like error: unknown key 'net.ipv4.ip_forwad'. Read the output carefully.
SELinux does not block sysctl configuration. The systemd-sysctl.service runs with the appropriate context to write to /proc/sys. If you see denials in the audit log, they are unrelated to sysctl. Focus on the sysctl output first.
Run journalctl -u systemd-sysctl.service to check for errors during boot. If the service failed, your persistent settings did not apply. The journal will show the specific file and line that caused the failure.
Reboot before you debug complex networking issues. Half the time the symptom is gone after a clean boot.
When to use sysctl versus alternatives
Use sysctl -w when you are testing a value and need immediate feedback. Use /etc/sysctl.d/ drop-in files when the setting must survive reboots and apply at boot time. Use sysctl --system when you want to reload all configurations without restarting the machine. Use tuned when you need a holistic profile that adjusts multiple parameters for a specific workload like virtualization or throughput-performance.