Want more like this?

Stop Disabling SELinux: A Real-World guide

Be safe from software vulnerabilities AND run your webserver

It's 2017, and your New Year's resolution should be to stop disabling SELinux. SELinux does a great job of doing what it says on the tin - making your servers safer. It doesn't matter if a Docker, Samba or even Flash vulnerability hits, as SELinux can contain it.

But SELinux can't do anything if you disable it. In the first post in our SELinux series, we're going to look at just how easy it is to run nginx as a reverse proxy, all while keeping SELinux happy.


For this guide, I'm using a Fedora 25 setup. In writing this guide, I referred heavily to the RHEL/CentOS 7 and 6 documentation. SELinux is a very stable piece of software, so this guide will probably apply unmodified for other RedHat based systems.

As for the http server, we will be looking at using nginx. However the configuration in RedHat based systems is generic across all packaged servers, so you should be lucky if you use apache2.

Proxy Pass

So you have you web application server (eg. django) running on something like http://localhost:8000. Then you setup nginx to proxy pass to the app server:

server {

    location / {

But now you get a 502 bad gateway error when you access it. First we need to follow the SELinux log, which is part of the systemd journal:

journalctl -f

After you request the page again, you should see an error from SELinux (also called audit) in the journal:

Jan 31 10:48:54 server audit[16067]: AVC avc: denied { name_connect } for pid=16067 comm="nginx" dest=8000 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:transproxy_port_t:s0 tclass=tcp_socket permissive=0

This is because of the default SELinux policy, which is secure and restrictive. Since using proxy passes is very common, this is a simple configurable boolean. Just run:

sudo setsebool -P httpd_can_network_connect true

The -P option writes this change to disk, meaning it persists across reboots. So just add this command to your provisioning script and your are good to go. If you use ansible, it is fully integrated:

- name: Allow nginx to proxy pass
  seboolean: name=httpd_can_network_connect state=yes persistent=yes

In future, you can check the list of all booleans but running semanage boolean --list.

Follow our SELinux series

Up next: Now to write your own policy for a custom app
Awesome! Please check your inbox and confirm your email.
We'll email you our latest posts plus special past content. Change your settings any time.

Static files

But in the normal modern setup, nginx does more than just proxy. Commonly nginx is used to serve static files:

server {

    location / {

    location /static/ {
        alias /var/www/static/;

But in your browser, you get a 403 Forbidden error. Again we will follow the systemd journal (journalctl -f) and request the file again. Then you should see an error message from SELinux:

Jan 31 20:28:46 server audit[9197]: AVC avc:  denied  { read } for  pid=9197 comm="nginx" name="test.txt" dev="vda1" ino=137247 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0

This is telling us that SELinux denied a read for a httpd_t (HTTPD type - probably nginx) process to read a var_t file. However, the var_t is used across the whole /var system, and it would be too insecure to give nginx access to all those files.

Enter httpd_sys_content_t. This is type that we can use for just this use case - files that the web server should have read access to.

SElinux file types work in 2 ways. Firstly, they are stored in the file metadata, like any normal permissions. But on creation, SELinux looks up the default for path based on the system rules (see semanage fcontext -i for all the rules on your system). We need to add a new rule for /var/www/:

semanage fcontext --add --type httpd_sys_content_t "/var/www(/.*)?"

That will set the default rule for /var/www and all descendants. Then we have to relabel the type of all the existing files:

     restorecon -Rv /var/www

Now your webserver is good to go.


Keeping a webserver running with SELinux is as simple as 2 things:

  • Setting a config boolean to let it proxy pass
  • Telling SELinux where you are going to put the webroot files

It is seriously something your should do for your server's security.

Next in our SELinux series, we're going to be looking at how we can use SELinux to contain our own apps. By default, services run unconfined. However policy writing is easy and worthwhile for the extra security. Make sure to subscribe so that you get that in your inbox.

Get More Great Content

The intersection of marketing, design and machine learning, delivered straight to your inbox:
Awesome! Please check your inbox and confirm your email.
We'll email you our latest posts plus special past content. Change your settings any time.

Magic Name

Find the name of every subscriber -- without asking

Begin Favicon Project

Taking the Sunday hack too seriously

Exposing properties with Graphene Django

The other missing guide

Arithmetic with JavaScript Arrays

A Astonishing Adventure

Freeing Disk Space with the PackageKit cache

Automatic updates gone wrong

Keeping Python projects secure on GitLab

Pinning projects to the very latest

Testing GraphQL with Graphene Django

The missing guide

Local Politicians Meet InfoSec - a Wordpress Disaster

The article that I didn't want to have to write

PGP for Every Email

Join us in our PGP journey

SELinux Concepts - but for humans

This is your SELinux dictionary!

A new way of writing Gtk+ applications

Introducing Pyract - my weekend hack

Plotinus and the quest for searchable menus

The underdog challenges a 30 year old UI convention

DMARC Secured Your Email Identity, But See How it Ruined Mailing Lists

Why people aren't posting on your mailing list

How they track you: Email Service Provider Edition

A summary of how major email marketers track their emails

Blender for Hackers - 3D modeling is just like using VIM

A very brief introduction to Blender

Edge of the World - What Open-World Games Can Teach Us About Design

Spoiler: It's all about the illusions

When fictional worlds are an accurate representations of IoT security

Ok, a little dramatized. But still truthful.

How I Destroyed my Blog's Performance with CSS Background-Blend-Modes

Just because a browser has a feature doesn't mean you should use it

Help Us Answer: The Email Signup Popup - where is it from?

Who is behind the latest wave of popups?

My WATCH runs GNU/Linux And It Is Amazing

Lennart Poettering would love it!

6 Stunning Email SignUp Form Designs with Free HTML

I've spent way to much time on dribbble researching these!
G'day Mate, join us on IRC for good banter:
#Learnt on Freenode
See you there!