DEV Community

Cover image for Flask + SELinux: Fixing the Mysterious 502 Error on Alma Linux
Mpia
Mpia

Posted on

Flask + SELinux: Fixing the Mysterious 502 Error on Alma Linux

You deploy your Flask app on Alma Linux, everything looks perfect, you hit your URL and... BAM! 502 Bad Gateway.

You check configs, permissions, logs. Nothing works. Then you try sudo setenforce 0 and... it works! ๐ŸŽ‰

But now you're stuck running with SELinux disabled, and you know that's not the solution.

Sound familiar? Let me show you how to fix this properly.

The Real Problem

SELinux isn't your enemy - it's just doing its job. By default, it blocks:

  • nginx connecting to your Gunicorn Unix socket
  • systemd launching Gunicorn from /home
  • Your app sending emails via SMTP

Basically, everything a modern web app needs to do. ๐Ÿ˜ค

Quick Diagnosis

# See what SELinux is blocking
sudo ausearch -m avc -ts recent

# Check your service logs
sudo journalctl -u your-service -n 50 --no-pager
Enter fullscreen mode Exit fullscreen mode

If you see Permission denied with code 203/EXEC, that's SELinux blocking you.

The Solution (Step by Step)

1. Move to /var/www (seriously, do it)

SELinux hates /home for web apps. Move to the standard location:

sudo systemctl stop your-service
sudo mkdir -p /var/www
sudo mv /home/user/my-app /var/www/my-app
sudo chown -R user:user /var/www/my-app
sudo restorecon -Rv /var/www/my-app  # SELinux magic!
Enter fullscreen mode Exit fullscreen mode

2. Update systemd service

Edit /etc/systemd/system/your-service.service:

[Unit]
Description=Gunicorn for Flask app
After=network.target

[Service]
User=your-user
Group=your-group
WorkingDirectory=/var/www/my-app

ExecStartPre=/usr/bin/mkdir -p /var/run/my-app
ExecStartPre=/usr/bin/chown your-user:nginx /var/run/my-app
ExecStartPre=/usr/bin/chmod 755 /var/run/my-app

Environment="PATH=/var/www/my-app/venv/bin"

ExecStart=/var/www/my-app/venv/bin/gunicorn \
    --workers 4 \
    --bind unix:/var/run/my-app/my-app.sock \
    --umask 007 \
    wsgi:app

Restart=always

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode
sudo systemctl daemon-reload
Enter fullscreen mode Exit fullscreen mode

3. Configure SELinux contexts

# Tell SELinux the socket is legitimate
sudo semanage fcontext -a -t httpd_var_run_t "/var/run/my-app(/.*)?"
sudo restorecon -Rv /var/run/my-app

# Allow nginx to connect
sudo setsebool -P httpd_can_network_connect 1
Enter fullscreen mode Exit fullscreen mode

4. Create a custom SELinux policy (THE game changer!)

This is the crucial step:

# Temporary permissive mode
sudo setenforce 0

# Start your app to generate violations
sudo systemctl restart your-service
sleep 5
curl http://localhost

# Generate custom policy from violations
sudo ausearch -m avc -ts recent | audit2allow -M my_policy

# Install the policy
sudo semodule -i my_policy.pp

# Back to enforcing mode
sudo setenforce 1

# Restart and verify
sudo systemctl restart your-service
Enter fullscreen mode Exit fullscreen mode

What just happened? audit2allow analyzed all SELinux denials and created a policy that allows them. SELinux just learned what your app needs!

5. Configure nginx

upstream app_server {
    server unix:/var/run/my-app/my-app.sock fail_timeout=0;
}

server {
    listen 80;
    server_name my-domain.com;

    location / {
        proxy_pass http://app_server;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
Enter fullscreen mode Exit fullscreen mode
sudo nginx -t
sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

Common Issues & Quick Fixes

Emails not sending?

sudo setsebool -P httpd_can_sendmail 1
Enter fullscreen mode Exit fullscreen mode

External database connection blocked?

sudo setsebool -P httpd_can_network_connect_db 1
Enter fullscreen mode Exit fullscreen mode

API calls failing?

sudo setsebool -P httpd_can_network_connect 1
Enter fullscreen mode Exit fullscreen mode

Verify It Works

# Check SELinux mode (should show "Enforcing")
getenforce

# Service status
sudo systemctl status your-service

# No more violations?
sudo ausearch -m avc -ts recent

# Test your site
curl -I http://your-domain.com
Enter fullscreen mode Exit fullscreen mode

If everything's green, congratulations! ๐ŸŽ‰ You've tamed SELinux!

Golden Rules

  1. NEVER disable SELinux in production - create policies instead
  2. Always use /var/www for web apps
  3. Save your .te files - you'll need them later
  4. Use restorecon after moving files - saves hours of debugging

Want the Full Guide?

This is just the quick version! For a complete, detailed walkthrough with troubleshooting tips, deployment automation scripts, and more real-world scenarios, check out the full article on my blog:

๐Ÿ‘‰ Read the complete guide on codewithmpia.com

You'll learn:

  • How to debug SELinux violations like a pro
  • Setting up automated deployment scripts
  • Handling edge cases and specific scenarios
  • Best practices for production deployments

Have you struggled with SELinux? Share your experience in the comments below!

And if this helped you fix that annoying 502 error, don't forget to share it with others who might be stuck in the same situation. ๐Ÿ˜‰

May the SELinux be with you! ๐Ÿงโœจ


๐Ÿ‘‹ About Me

Hi! I'm Mpia M., a computer science student passionate about web development. I created codewithmpia.com to share coding tutorials and make programming knowledge accessible to everyone.

Want more content like this?

  • ๐ŸŒ Visit my blog: https://codewithmpia.com
  • ๐Ÿ“ง Subscribe to my newsletter for Python, Django, Flask, Svelte tips
  • ๐Ÿ’ฌ Let's connect and share our dev experiences!

Topics I cover: Python, Django, Flask, SvelteKit, Vue.js, and DevOps.

Top comments (0)