How to Install SELinux on Debian (13, 12, 11)

Last updated Friday, March 13, 2026 1:08 pm 10 min read 2 comments

Debian ships with AppArmor enabled by default, but some hardening and compliance workflows still expect SELinux and its tighter policy controls around services, files, and network ports. To install SELinux on Debian, you do more than add packages: you switch the active MAC workflow, relabel the filesystem, and test services before moving into enforcing mode.

The same package set works on Debian 13, 12, and 11 on server and desktop installs alike. After activation, you can tune the operating mode, label custom web content, inspect denials, and roll back to AppArmor cleanly if the host is not ready for permanent SELinux enforcement.

Install SELinux on Debian

Switching from AppArmor to SELinux changes how Debian enforces mandatory access controls, so the install flow starts with AppArmor, then moves into package installation, boot activation, and a first reboot for relabeling.

Disable AppArmor Before Installing SELinux on Debian

Check AppArmor first so you know whether the service is still active on this host.

sudo systemctl status apparmor

When AppArmor is active, the status output includes lines like these.

apparmor.service - Load AppArmor profiles
     Loaded: loaded (/lib/systemd/system/apparmor.service; enabled; preset: enabled)
     Active: active (exited) since ...

Disabling AppArmor removes its profile enforcement until you enable it again. If this Debian system relies on custom AppArmor profiles today, back them up before you switch to SELinux.

Disable AppArmor before you activate SELinux on Debian.

sudo systemctl disable apparmor --now

Confirm that AppArmor is no longer active before you move on.

sudo systemctl status apparmor --no-pager
apparmor.service - Load AppArmor profiles
     Loaded: loaded (/lib/systemd/system/apparmor.service; disabled; preset: enabled)
     Active: inactive (dead)

Install SELinux Packages on Debian

Refresh the package index, then install the base SELinux tools, the default policy, and the Python helpers used by semanage and audit2allow.

sudo apt update

If your account does not already have sudo access, add a user to sudoers on Debian before you continue.

sudo apt install -y policycoreutils selinux-utils selinux-basics selinux-policy-default auditd policycoreutils-python-utils

The package set is the same on Debian 13, 12, and 11. policycoreutils-python-utils provides semanage and audit2allow, while auditd records AVC denials for later troubleshooting.

Check that the expected SELinux command files are present after the package install.

dpkg -L policycoreutils policycoreutils-python-utils | grep -E '/sestatus$|/semanage$'
/usr/bin/sestatus
/usr/sbin/semanage

On some minimal Debian installs, /usr/sbin may not be in a regular user’s PATH. If semanage returns command not found, rerun it with sudo semanage or the full /usr/sbin/semanage path.

Activate SELinux on Debian

Run the activation script once so Debian adds the SELinux boot parameters and prepares the relabel on the next restart.

sudo selinux-activate

Successful output resembles:

Activating SE Linux
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.x.x-amd64
Found initrd image: /boot/initrd.img-6.x.x-amd64
done
SE Linux is activated.  You may need to reboot now.

Restart after the script finishes. The first SELinux boot can take several minutes because Debian relabels the filesystem before it hands control back to the system.

sudo reboot

Verify SELinux Status on Debian

After the host comes back, confirm that SELinux is enabled and still in permissive mode.

sudo sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
Loaded policy name:             default
Current mode:                   permissive
Mode from config file:          permissive

Permissive mode is expected on the first boot. That gives you a safe place to collect denials before you move into enforcement.

Configure SELinux on Debian

SELinux has three operating modes, and the right one depends on how far you are through testing.

  • Enforcing: blocks and logs policy violations. Use this after the host and its services are labeled correctly.
  • Permissive: logs denials without blocking them. This is the safest place to start after the first reboot.
  • Disabled: turns SELinux off entirely. Re-enabling it later requires another relabel cycle.

Edit the SELinux Configuration File on Debian

Open the main SELinux configuration file before you choose the permanent mode.

sudo nano /etc/selinux/config

Set SELINUX to the mode you want Debian to use after the next reboot.

Use enforcing mode once your services run cleanly under permissive mode.

SELINUX=enforcing

Keep permissive mode if you still need to watch denials without blocking traffic.

SELINUX=permissive

Use disabled only when you are removing SELinux or intentionally backing out of the migration.

SELINUX=disabled

Apply SELinux Mode Changes on Debian

Restart Debian after you save the configuration so the new mode is loaded at boot.

sudo reboot

Verify SELinux Mode After Reboot on Debian

Check the active mode after the host comes back.

sudo getenforce

When enforcing mode is active, the command returns:

Enforcing

When permissive mode is active, the command returns:

Permissive

Configure SELinux Policy Settings on Debian

Most Debian systems only need two policy lines beyond the main mode setting in /etc/selinux/config.

  • SETLOCALDEFS=0 keeps Debian on the policy-provided file contexts unless you deliberately add local overrides with semanage.
  • SELINUXTYPE=default loads Debian’s standard policy package. Use mls only when your environment truly requires multi-level security labels.
SETLOCALDEFS=0
SELINUXTYPE=default

Debian uses default as the standard SELinux policy name. Do not change that line to targeted; that Red Hat naming does not exist in Debian’s policy packages.

Configure SELinux for Web Servers on Debian

Custom document roots and non-standard ports are common SELinux adjustments after you install Apache on Debian or install Nginx on Debian.

Check the HTTP ports that SELinux already allows before you add a new one.

sudo semanage port -l | grep http_port_t
http_port_t                    tcp      80, 443, 488, 8008, 8009, 8443, 8448

Add port 8080 to the HTTP port type if your service listens there.

sudo semanage port -a -t http_port_t -p tcp 8080

If the command returns Port tcp/8080 already defined, Debian already has a label on that port. Modify the existing label instead of adding a second one: sudo semanage port -m -t http_port_t -p tcp 8080.

Check the list again so you can confirm that 8080 now appears under http_port_t.

sudo semanage port -l | grep http_port_t
http_port_t                    tcp      80, 443, 488, 8008, 8009, 8080, 8443, 8448

Use a file-context rule when the web content lives outside Debian’s default document root.

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"

Restore the context on existing files after you add the rule.

sudo restorecon -Rv /srv/www
Relabeled /srv/www from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

Troubleshoot SELinux on Debian

Most SELinux problems on Debian come down to missing labels, denied network access, or services that were moved outside their default paths. If the host also needs perimeter controls, install UFW on Debian and install Fail2Ban on Debian so the firewall and intrusion-response side stays in step with the policy work.

Restore Default SELinux File Contexts on Debian

Reset labels first when a service breaks after you move files or copy content into a path that SELinux already knows how to manage.

sudo restorecon -Rv /var/www/html

When files need relabeling, the output resembles:

Relabeled /var/www/html from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

If no files need changes, restorecon finishes without printing anything.

Test SELinux with Permissive Mode on Debian

Switch to permissive mode temporarily when you need to confirm that SELinux is the source of a denial.

sudo setenforce 0

Verify the mode change before you retest the application.

sudo getenforce
Permissive

If the application works in permissive mode, inspect the audit logs and then switch back to enforcing once you have fixed the policy issue.

sudo setenforce 1

Check the mode again after you re-enable enforcement.

sudo getenforce
Enforcing

Review SELinux Audit Logs on Debian

Start with auditd because Debian writes SELinux denials into /var/log/audit/audit.log.

sudo systemctl status auditd --no-pager
auditd.service - Security Auditing Service
     Loaded: loaded (/lib/systemd/system/auditd.service; enabled; preset: enabled)
     Active: active (running) since ...

Query the recent AVC records once the service is running.

sudo ausearch -m AVC,USER_AVC -ts recent

Use a narrower log search when you want a quick look at the most recent denials. For more pattern-matching options, use grep command in Linux as a reference while you work through larger audit logs.

sudo grep 'denied' /var/log/audit/audit.log | tail -20

An AVC denial entry looks like this.

type=AVC msg=audit(1234567890.123:456): avc:  denied  { read } for  pid=1234 comm="httpd" name="index.html" dev="sda1" ino=123456 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:var_t:s0 tclass=file permissive=0

The process name, requested action, and source and target contexts usually tell you whether the fix belongs in a file label, a boolean, or a custom policy module.

Create Custom SELinux Policy Modules on Debian

Generate a local module only after you understand the denial and decide that the access should be allowed permanently.

sudo grep 'denied' /var/log/audit/audit.log | audit2allow -M mycustommodule
sudo semodule -i mycustommodule.pp

Only the grep part needs sudo because the audit log is root-readable. audit2allow writes the module files into your current working directory, and semodule loads the finished policy with root privileges.

Verify that Debian loaded the module after you install it.

sudo semodule -l | grep mycustommodule
mycustommodule

Review the generated .te file before you load it on production systems so you are not granting broader access than the service actually needs.

Manage SELinux Booleans on Debian

Booleans are the quickest way to toggle common policy behaviors without writing a custom module.

sudo getsebool -a | grep httpd
httpd_can_network_connect --> off
httpd_can_network_connect_db --> off
httpd_can_sendmail --> off
httpd_enable_cgi --> on

Enable the boolean you need with the -P flag so the change survives reboots.

sudo setsebool -P httpd_can_network_connect 1

Check the result after you change it.

sudo getsebool httpd_can_network_connect
httpd_can_network_connect --> on

Remove SELinux from Debian

Back the system out of SELinux in three stages: disable enforcement, remove the SELinux boot parameters, and purge the packages before you bring AppArmor back.

Disable SELinux on Debian Before Removal

Move SELinux into permissive mode first so you are not removing packages while policy enforcement is still active.

sudo setenforce 0

Edit the main configuration file and change the permanent mode to disabled.

sudo nano /etc/selinux/config
SELINUX=disabled

Remove SELinux Kernel Parameters on Debian

Use Debian’s deactivation helper instead of editing GRUB by hand.

sudo selinux-activate disable

Successful output resembles:

Deactivating SE Linux
Generating grub configuration file ...
done
SE Linux is deactivated.  You may need to reboot now.

selinux-activate disable removes the SELinux boot parameters from GRUB. That is more reliable than editing /etc/default/grub by hand and hoping nothing gets left behind.

Remove SELinux Packages on Debian

Purge the SELinux packages after the configuration and boot parameters are in place.

sudo apt remove --purge -y selinux-basics selinux-policy-default policycoreutils policycoreutils-python-utils selinux-utils auditd

Clean up any dependencies that were pulled in only for SELinux administration.

sudo apt autoremove --purge -y

Verify SELinux Removal on Debian

Re-enable AppArmor before the reboot if you want Debian’s default MAC layer back immediately.

sudo systemctl enable apparmor

Restart once the cleanup is finished.

sudo reboot

After Debian comes back, refresh APT metadata and confirm that the SELinux packages are no longer installed.

sudo apt update
apt-cache policy selinux-basics selinux-utils policycoreutils
selinux-basics:
  Installed: (none)
  Candidate: 0.x.x
selinux-utils:
  Installed: (none)
  Candidate: 3.x.x
policycoreutils:
  Installed: (none)
  Candidate: 3.x.x

The candidate version numbers vary by Debian release. The important removal check is that each package shows Installed: (none).

If you re-enabled AppArmor, confirm that the service is active again after the reboot.

sudo systemctl status apparmor --no-pager
apparmor.service - Load AppArmor profiles
     Loaded: loaded (/lib/systemd/system/apparmor.service; enabled; preset: enabled)
     Active: active (exited) since ...

SELinux on Debian FAQ

Does Debian use SELinux by default?

No. Debian uses AppArmor by default, and SELinux is an optional hardening framework that you install and activate separately. If you switch to SELinux, disable AppArmor first so you are not managing two different policy workflows on the same host.

Can you install SELinux on Debian 13, 12, and 11 with the same commands?

Yes. Debian 13, 12, and 11 use the same package names and the same activation flow. Package versions differ by release, but the install, reboot, verification, and rollback commands stay the same.

Why is the semanage command missing on Debian?

The semanage command comes from policycoreutils-python-utils. If it is missing, install or reinstall that package with sudo apt install policycoreutils-python-utils. On minimal Debian installs, you may also need to run the command with sudo because it lives in /usr/sbin.

Can you disable SELinux later and switch back to AppArmor on Debian?

Yes. Set SELINUX=disabled in /etc/selinux/config, run sudo selinux-activate disable, purge the SELinux packages, and reboot. If you want Debian’s default MAC layer back immediately, re-enable AppArmor before that final reboot with sudo systemctl enable apparmor.

Conclusion

SELinux is installed on Debian and ready for permissive testing or a move to enforcing mode once your labels and booleans match the services you run. To keep the host hardened after the initial policy work, configure unattended upgrades on Debian for routine patches and install Fail2Ban on Debian if the server also needs automated response to brute-force traffic.

Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffee Buy me a coffee

2 thoughts on “How to Install SELinux on Debian (13, 12, 11)”

    • Thanks for the suggestion, hmidani. You were right that auditd is essential for troubleshooting. The article didn’t include it when you commented in April. The guide has been updated to include auditd along with policycoreutils-python-utils.

      The updated command is:

      sudo apt install policycoreutils selinux-utils selinux-basics selinux-policy-default auditd policycoreutils-python-utils

      Thanks for helping improve the guide.

      Reply
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Leave a Comment

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: