How to Install SELinux on Ubuntu 26.04, 24.04 and 22.04

Install SELinux on Ubuntu 26.04, 24.04 and 22.04 for mandatory access control. Covers setup, enforcing mode and troubleshooting.

Last updatedAuthorJoshua JamesRead time8 minGuide typeUbuntu

Some compliance baselines and RHEL-aligned workflows expect SELinux labels, booleans, and AVC audit logs instead of Ubuntu’s default AppArmor profiles. You can install SELinux on Ubuntu 26.04, 24.04, and 22.04 from Ubuntu’s repositories, but the switch changes the active Linux Security Module and requires a relabeling reboot.

Ubuntu does not use SELinux by default. It ships AppArmor on Ubuntu as the default mandatory access control layer, while SELinux is an optional package set from Ubuntu’s Universe component for administrators who specifically need the SELinux policy model.

SELinux can block service access, SSH sessions, web content, and local administration when policies or labels are wrong. Start in permissive mode, keep console or provider recovery access available, and test critical services before switching to enforcing mode.

Install SELinux on Ubuntu

Start by confirming AppArmor state, refreshing APT metadata, installing the SELinux policy tools, then activating the SELinux boot parameters for the next restart.

Update Ubuntu Before Installing SELinux

Refresh the package index so APT sees the current SELinux packages and dependencies.

sudo apt update

These commands use sudo for system-wide package and bootloader changes. If your account does not have administrator access yet, add a user to sudoers on Ubuntu before continuing.

The SELinux packages are in Ubuntu’s Universe component. Standard desktop and server installs usually have Universe enabled; minimal or customized systems may need to enable Universe on Ubuntu first if APT cannot find the packages.

Check AppArmor Before Activating SELinux on Ubuntu

Check AppArmor first so you know whether Ubuntu is still using its default MAC layer.

systemctl is-active apparmor
systemctl is-enabled apparmor

On a normal AppArmor-enabled Ubuntu system, the output is:

active
enabled

Disabling AppArmor removes AppArmor profile enforcement until you enable it again. Back up any custom profiles under /etc/apparmor.d/ before switching a production host to SELinux.

Disable AppArmor before SELinux becomes the active security module.

sudo systemctl disable --now apparmor

Confirm that AppArmor is disabled before continuing.

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

Install SELinux Packages with APT

Install the base SELinux utilities, Ubuntu’s default SELinux policy, the audit daemon, and the Python helper package that provides semanage and audit2allow.

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

APT also installs supporting policy tools such as setools and semodule-utils. Check the core command files after installation.

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

semanage lives in /usr/sbin. If a regular shell reports semanage: command not found, run it with sudo semanage or use the full path /usr/sbin/semanage.

Activate SELinux on Ubuntu

Run the activation helper once. It adds the SELinux boot parameter to GRUB, updates the bootloader configuration, and creates /.autorelabel so the next boot labels the filesystem.

sudo selinux-activate

Relevant output includes:

Activating SE Linux
SE Linux is activated.  You may need to reboot now.

Reboot and Verify SELinux on Ubuntu

Reboot after activation. The first SELinux boot can take several minutes because Ubuntu relabels files before services finish starting.

sudo reboot

After the host comes back, check the detailed SELinux status.

sestatus

A successful first boot should include these lines.

SELinux status:                 enabled
Loaded policy name:             default
Current mode:                   permissive
Mode from config file:          permissive

Permissive mode is expected after the initial boot. It logs denials without blocking services, which gives you time to fix labels and booleans before enforcement starts.

Configure SELinux on Ubuntu

SELinux configuration has two layers: the persistent boot mode in /etc/selinux/config and the current runtime mode controlled by setenforce.

Understand SELinux Modes on Ubuntu

  • Enforcing: blocks and logs policy violations. Use it after services run cleanly in permissive mode.
  • Permissive: logs denials without blocking them. This is the safest mode for first boot and policy tuning.
  • Disabled: turns SELinux off. Re-enabling SELinux later requires another activation and relabel cycle.

Edit the SELinux Configuration File on Ubuntu

Open the main SELinux configuration file before changing the persistent mode.

sudo nano /etc/selinux/config

Keep the default policy type unless you intentionally installed and tested a different policy package.

SELINUX=permissive
SELINUXTYPE=default
SETLOCALDEFS=0

Ubuntu’s SELinux policy package uses default as the normal policy name. Do not change SELINUXTYPE to targeted; that Red Hat policy name is not the Ubuntu policy tree.

Set SELINUX=enforcing only after permissive-mode testing is clean. Set SELINUX=disabled only when removing SELinux or backing out of the migration.

Change SELinux Runtime Mode on Ubuntu

Use runtime mode changes for short tests. They take effect immediately but revert to the value in /etc/selinux/config at the next boot.

Switch to permissive mode temporarily:

sudo setenforce 0
getenforce
Permissive

Switch back to enforcing mode after you fix the denial being tested:

sudo setenforce 1
getenforce
Enforcing

Enable SELinux Enforcing Mode on Ubuntu

Use enforcing mode after SSH, web services, databases, scheduled jobs, and application logs show no unexpected denials in permissive mode.

sudo selinux-config-enforcing
Configured enforcing mode in /etc/selinux/config for the next boot.
This can be overridden by "enforcing=0" on the kernel command line.

Reboot, then confirm that enforcing mode is active.

sudo reboot
getenforce
Enforcing

Configure SELinux Policy for Web Servers on Ubuntu

Web services often need extra SELinux policy work when you move document roots, use non-standard ports, or let applications connect to remote services. These examples fit common Apache on Ubuntu, Nginx on Ubuntu, and WordPress on Ubuntu deployments.

Check SELinux HTTP Port Labels on Ubuntu

Check the HTTP ports that the installed SELinux policy already allows before adding a custom listener.

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

Add a custom TCP port, such as 18080, only when your web service actually listens there.

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

If SELinux reports that the port is already defined, the port already has a label. Use sudo semanage port -m -t http_port_t -p tcp 18080 to modify the existing mapping instead of adding a duplicate.

SELinux port labels do not open the local firewall or any cloud security group. If the service must accept network traffic, configure that access separately with UFW firewall on Ubuntu or the firewall tool that owns your host.

Label Custom Web Content on Ubuntu

When web content lives outside the standard paths already covered by the policy, add a file-context rule and relabel the existing files.

sudo semanage fcontext -a -t httpd_sys_content_t "/opt/myapp(/.*)?"
sudo restorecon -Rv /opt/myapp

restorecon prints relabeled files when it changes contexts. If it prints nothing, the files already matched the policy.

Enable SELinux Web Server Booleans on Ubuntu

List the relevant HTTP booleans before changing them so you can see the current and persistent values.

sudo semanage boolean -l | grep -E '^(httpd_can_network_connect|httpd_can_sendmail|httpd_enable_ftp_server)\b'
httpd_can_network_connect      (off  ,  off)  Determine whether httpd scripts and modules can connect to the network using TCP.
httpd_can_sendmail             (off  ,  off)  Determine whether httpd can send mail.
httpd_enable_ftp_server        (off  ,  off)  Determine whether httpd can act as a FTP server by listening on the ftp port.

Enable only the boolean your application needs. For example, allow outbound TCP connections for update checks, APIs, or remote databases:

sudo setsebool -P httpd_can_network_connect 1

Allow web applications to send email only when the site needs mail delivery from the web server context:

sudo setsebool -P httpd_can_sendmail 1

The -P flag saves the boolean change so it survives reboots.

Undo SELinux Web Policy Changes on Ubuntu

Remove local policy changes when a test port, content path, or boolean is no longer needed.

sudo semanage port -d -t http_port_t -p tcp 18080
sudo semanage fcontext -d "/opt/myapp(/.*)?"
sudo setsebool -P httpd_can_network_connect 0

Run the delete commands only for settings you actually added. If a command reports that the record is not defined, that setting was already absent.

Verify SELinux Status on Ubuntu

Use getenforce for a quick mode check and sestatus when you need the loaded policy and boot configuration values.

Check the Current SELinux Mode on Ubuntu

getenforce

The command returns one of these values.

Enforcing
Permissive
Disabled

Check Detailed SELinux Status on Ubuntu

sestatus

Compare Current mode with Mode from config file. A mismatch usually means someone changed the runtime mode with setenforce after boot.

Troubleshoot SELinux on Ubuntu

Most SELinux problems on Ubuntu come from missing labels, services running outside their expected paths, or booleans that still deny legitimate application behavior.

Fix semanage Command Not Found on Ubuntu

The semanage command comes from policycoreutils-python-utils. Install that package if the command is missing.

sudo apt install policycoreutils-python-utils

If the package is installed but the shell still cannot find the command, run sudo semanage or /usr/sbin/semanage because the binary is installed under /usr/sbin.

Restore SELinux File Contexts on Ubuntu

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

sudo restorecon -Rv /var/www/html

The -R flag applies the relabel recursively, while -v prints files whose contexts changed.

Review SELinux Audit Logs on Ubuntu

Start with the audit daemon because SELinux denials are recorded in /var/log/audit/audit.log.

sudo systemctl status auditd --no-pager

Query recent AVC records with ausearch.

sudo ausearch -m AVC,USER_AVC -ts recent

For a quick log scan, combine the grep command in Linux with the tail command in Linux.

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

An AVC record identifies the process, denied action, source context, target context, and target class. Use that detail to decide whether the fix belongs in a file label, a boolean, or a custom policy module.

Create Custom SELinux Policy Modules on Ubuntu

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

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

The first command reads root-owned audit logs and writes a module in the current directory. The second command loads the compiled policy module.

sudo semodule -l | grep mycustommodule
mycustommodule

Review the generated mycustommodule.te file before loading it on production systems. Blindly allowing every denial can make the final policy broader than the service actually needs.

Fix Failed to Load SELinux Policy on Ubuntu

If Ubuntu stops at Failed to load SELinux policy. Freezing., the bootloader is trying to load SELinux but the policy files are missing or broken. Boot from a recovery entry or provider console, then reinstall the default policy package.

sudo apt install --reinstall selinux-policy-default

If the system needs to boot before you finish repairs, add enforcing=0 to the kernel line from the GRUB edit screen so SELinux starts in permissive mode for that boot.

Fix SELinux Not Detected After Reboot on Ubuntu

If getenforce returns Disabled after installation, check the three common causes first.

  • sudo selinux-activate was not run before rebooting.
  • The host has not rebooted since selinux-activate updated GRUB and created /.autorelabel.
  • SELINUX=disabled is still set in /etc/selinux/config.

After correcting the cause, run sudo selinux-activate again when needed and reboot so the kernel loads SELinux at startup.

Disable or Remove SELinux from Ubuntu

Disable SELinux in stages so Ubuntu does not keep SELinux boot parameters after the policy packages are gone. If you only want to disable SELinux and keep the packages installed, skip the package purge after removing the boot parameters and re-enabling AppArmor.

Disable SELinux on Ubuntu

If SELinux is enforcing, move it to permissive mode before removing packages.

sudo setenforce 0

Edit the persistent configuration and set SELinux to disabled.

sudo nano /etc/selinux/config
SELINUX=disabled

Remove SELinux Boot Parameters on Ubuntu

Use the same activation helper with the disable argument so it removes the SELinux kernel parameters from GRUB cleanly.

sudo selinux-activate disable
Deactivating SE Linux
SE Linux is deactivated.  You may need to reboot now.

Purge SELinux Packages from Ubuntu

Purge the SELinux packages only when you want a full removal after disabling SELinux.

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

If auditd was installed only for this SELinux setup, remove it separately. Keep it installed when other compliance or logging workflows already use Linux audit events.

sudo apt remove --purge auditd

Preview dependency cleanup before removing automatically installed packages, especially on shared servers where other tools may use the same libraries.

sudo apt autoremove --purge --dry-run

If the dry run only lists packages you no longer need, run the cleanup without --dry-run.

sudo apt autoremove --purge

Re-enable AppArmor on Ubuntu

Enable AppArmor so Ubuntu returns to its default MAC layer after the next reboot.

sudo systemctl enable apparmor

Reboot once the cleanup finishes.

sudo reboot

After Ubuntu starts again, confirm that AppArmor is active.

systemctl is-active apparmor
active

Check that the main SELinux packages are no longer installed.

dpkg -l selinux-basics selinux-utils policycoreutils policycoreutils-python-utils 2>/dev/null | grep '^ii' || echo 'SELinux packages are not installed'
SELinux packages are not installed

Conclusion

SELinux is installed on Ubuntu with AppArmor disabled, the default policy loaded, and permissive testing available before enforcement. Keep audit reviews part of routine maintenance, then use the related guides to configure unattended upgrades on Ubuntu and install Fail2Ban on Ubuntu for patching and brute-force response.

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
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.

Verify before posting: