How to Install SELinux on Debian 13, 12 and 11

Install SELinux on Debian 13, 12, or 11 with APT. Covers AppArmor handoff, relabeling, permissive checks, policy tuning, and removal.

UpdatedPublished AuthorJoshua JamesRead time8 minGuide typeDebianDiscussion2 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 Debian’s current MAC baseline, then moves into package installation, boot activation, and a first reboot for relabeling.

Debian 13, 12, and 11 enable AppArmor by default, while SELinux remains available from the default Debian repositories as an optional policy stack. Debian-packaged kernels already include the required SELinux support; custom kernels or unusual filesystems should be checked for SELinux and extended-attribute support before you activate the policy.

Check AppArmor Before Installing SELinux on Debian

Check AppArmor first so you know whether Debian’s default profile loader is active on this host.

systemctl is-active apparmor
systemctl is-enabled apparmor

When AppArmor is active and enabled, the commands return:

active
enabled

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.

Install SELinux Packages on Debian

Refresh the package index, then install the base SELinux tools, the default policy, audit logging, 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 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.

APT may list a large dependency set for the SELinux policy tools, especially on minimal systems. Review the transaction before you confirm it so you know which Python, SETools, and policy-development packages will be added.

Check that the expected SELinux commands are available after the package install.

command -v sestatus || sudo sh -c 'command -v sestatus'
command -v semanage || sudo sh -c 'command -v semanage'

A valid path for each command confirms that the tooling is installed. On some minimal Debian installs, /usr/sbin may not be in a regular user’s PATH. If an SELinux administration command returns command not found, rerun it with sudo or the full /usr/sbin path.

Disable AppArmor Before Activating SELinux on Debian

Disable AppArmor after the SELinux packages are installed and before you run the SELinux activation script. This keeps Debian’s default profile enforcement in place during the package-install phase.

sudo systemctl disable apparmor --now

Confirm that AppArmor is no longer active before you activate SELinux.

systemctl is-active apparmor
systemctl is-enabled apparmor
inactive
disabled

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, and some systems reboot a second time after relabeling completes.

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.

Run Debian’s SELinux installation checker after the first reboot to catch common setup issues before you change the system to enforcing mode.

sudo check-selinux-installation

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 existing SELinux label for a port before you add or change it. Debian’s default policy already assigns port 8080 to http_cache_port_t, so a normal semanage port -a command fails on current Debian releases.

sudo semanage port -l | grep -w 8080
http_cache_port_t              tcp      3128, 8080, 8118, 10001-10010

Modify the existing label only when you intentionally want a web server to use 8080 as a normal HTTP port. If your custom port has no existing label, use semanage port -a instead of semanage port -m.

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

Remove the example custom rules if the service no longer uses port 8080 or the /srv/www document root. Deleting the local port override restores Debian’s packaged policy label for 8080, and deleting the file-context rule removes only the local /srv/www mapping.

sudo semanage port -d -p tcp 8080
sudo semanage fcontext -d "/srv/www(/.*)?"
sudo restorecon -Rv /srv/www

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.

Fix SELinux Command Not Found Errors on Debian

If getenforce, setenforce, or semanage returns command not found, first check whether the command is missing from the system or only missing from your user’s PATH. Debian installs these administrative commands under /usr/sbin, and regular user shells on minimal installs may not search that directory.

command -v getenforce || sudo sh -c 'command -v getenforce'
command -v semanage || sudo sh -c 'command -v semanage'

Install or repair the provider packages when those checks return no path. selinux-utils provides getenforce and setenforce, while policycoreutils-python-utils provides semanage.

sudo apt install selinux-utils policycoreutils-python-utils

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.

systemctl is-active auditd
active

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. Use semanage boolean -l when you want policy-store output; getsebool needs SELinux to be active.

sudo semanage boolean -l | grep -E '^httpd_(can_network_connect|can_network_connect_db|can_sendmail|enable_cgi)[[:space:]]'
httpd_can_network_connect      (off  ,  off)  Determine whether httpd scripts and modules can connect to the network using TCP.
httpd_can_network_connect_db   (off  ,  off)  Determine whether scripts and modules can connect to databases over the network.
httpd_can_sendmail             (off  ,  off)  Determine whether httpd can send mail.
httpd_enable_cgi               (off  ,  off)  Determine whether httpd can use support.

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. The current and persistent values should both show on.

sudo semanage boolean -l | grep '^httpd_can_network_connect '

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 selinux-basics selinux-policy-default policycoreutils policycoreutils-python-utils selinux-utils auditd

Preview the dependency cleanup before you remove packages that were pulled in only for SELinux administration.

sudo apt -s autoremove --purge

If the preview lists only SELinux-related packages that you no longer need, run the cleanup without simulation mode.

sudo apt autoremove --purge

Verify SELinux Removal on Debian

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

sudo systemctl enable --now 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.

systemctl is-active apparmor
systemctl is-enabled apparmor
active
enabled

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.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
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 coffeeBuy me a coffee

2 thoughts on “How to Install SELinux on Debian 13, 12 and 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 in published comments:

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

Got a Question or Feedback?

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

Let us know you are human: