The Scenario
It's 2 AM. A config file is corrupted, deployment is failing, and you just need to overwrite it. You're root. You run:
rm: cannot remove 'config.conf': Operation not permitted
You try sudo rm -f. Same error. You try chmod 777. Also fails. You check ownership โ root owns it. Nothing makes sense.
Almost always, this is the immutable flag set by chattr. It lives below POSIX permissions โ a separate layer that root can't bypass without explicitly lifting it first.
Why This Happens
Think of Linux permissions as two layers. The familiar rwxrwxrwx bits are the outer layer โ the one everyone knows. Underneath sits an extended attribute system, and one of those attributes is +i. When a file has it set:
- No one can modify, delete, rename, or create hard links to the file
- Not even root
- Not even with
-f
How does a file end up immutable? Usually one of these:
- A sysadmin locked it intentionally โ common for
/etc/resolv.confor/etc/hosts - A provisioning tool (Ansible, Chef, Puppet) set it as part of hardening
- An installer or package script added it
- Someone protecting a config from accidental overwrites
- Rare: a rootkit protecting itself โ worth keeping in the back of your mind
Diagnose: Check the Immutable Flag
Run lsattr against the file:
lsattr config.conf
Immutable files show an i in the attribute string:
----i---------e-- config.conf
That i is your culprit. For a whole directory, scan recursively:
lsattr -R /etc/nginx/
No lsattr on the system? Install it:
# Debian/Ubuntu
apt install e2fsprogs
# RHEL/CentOS
yum install e2fsprogs
Quick Fix: Remove the Immutable Flag
One command, then you're unblocked:
# Remove immutable flag from a single file
sudo chattr -i config.conf
# Now delete it
rm config.conf
Want to edit instead of delete? Same first step:
sudo chattr -i config.conf
nano config.conf
Dealing with a whole directory tree:
sudo chattr -iR /path/to/directory/
Verify the Fix
# Confirm the flag is gone
lsattr config.conf
# Should show no 'i' in the attributes:
# ---------------e-- config.conf
# Now the delete should work
rm config.conf
echo $? # Should print 0
Other Causes (If chattr Isn't the Issue)
Still getting the error but lsattr shows no immutable flag? A few other suspects:
SELinux
On RHEL/CentOS/Fedora, SELinux enforces its own access rules on top of everything else โ and root is not exempt:
# Check if SELinux is the blocker
audit2why -a | grep denied
# Check SELinux context on the file
ls -Z config.conf
# Temporarily permissive mode (for testing only)
sudo setenforce 0
rm config.conf
sudo setenforce 1
Mount Options (Read-Only Filesystem)
# Check mount flags
mount | grep "$(df config.conf | tail -1 | awk '{print $1}')"
# Look for 'ro' in the options
AppArmor (Ubuntu)
# Check AppArmor denials
dmesg | grep -i apparmor | tail -20
aa-status
NFS or Remote Filesystem
Files on NFS behave differently. The root_squash option maps root to an unprivileged user on the server side โ so even though you're root locally, you're effectively nobody on the remote. Check /etc/exports on the NFS server. You'll need no_root_squash to restore root access.
Permanent Fix: Decide If the Flag Should Stay
Before you remove the flag and move on, take 30 seconds to ask why it was there. Immutable flags on production systems usually got set for a specific reason โ a previous incident, a compliance requirement, or an automation tool that will just set it again on the next run.
Find out who set it:
# Search for chattr calls in Ansible playbooks
grep -r "chattr" /etc/ansible/
# Check shell history (if available)
grep chattr ~/.bash_history
Watch out for managed configs in particular. If /etc/resolv.conf was made immutable to stop NetworkManager or dhclient from clobbering your DNS settings, removing the flag will let them overwrite it on next reboot. The real fix is to stop those services from touching the file:
# Tell NetworkManager to stop overwriting resolv.conf
echo -e "[main]\ndns=none" | sudo tee /etc/NetworkManager/conf.d/nodns.conf
sudo systemctl restart NetworkManager
Quick Reference
# View attributes
lsattr filename
lsattr -R /directory/
# Set immutable
sudo chattr +i filename
# Remove immutable
sudo chattr -i filename
# Other useful flags:
# +a append-only (can write but not delete/overwrite)
# +u undeletable (data preserved for recovery)
sudo chattr -a filename # remove append-only
Tips
When you're deep in permission debugging and lose track of what a file's bits actually mean, the Unix Permissions Calculator on ToolCraft is a quick way to decode chmod values โ handy for confirming what permissions a file should have before you restore it after lifting the immutable flag.

