Nginx serve static files for flask app 404

fedoraflasknginxpythonstatic-content

I've tried numerous solutions of other posts, but nothing seems to work for me, I always get a 404 error, when trying to let nginx serve static files of my flask application. Somewhere in between all those attempts on getting it to run, I also had a 403, but I can't reconstruct it. This is my current setup:

The app is in: ~/development/Python/flask_nginx_gunicorn/, which is supposed to be a test project for getting everything running, understanding nginx and so on. It has the following structure:

project structure

So there is nothing more than a file called app.py, which configures a few routes and an index.html in the static folder.

I configured my nginx as follows:

/etc/nginx/nginx.conf with the following content:

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

At the end there is an include for the sites-enabled sub directory. In that directory I have a file called flask_project. In that file I have the following configuration for my project:

server {

    root /home/xiaolong/development/Python/flask_nginx_gunicorn/;

    server_name localhost;

    # LISTENING ON WHICH PORTS?
    listen localhost:7777;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /static/ {
        autoindex on;
        root /home/xiaolong/development/Python/flask_nginx_gunicorn/;
    }
}

I started nginx using the command systemctl start nginx. When it is running, and I do a ps -aux | grep nginx, I get the following output:

root     17748  1.2  2.5 1607328 102772 pts/1  Sl   20:45   0:07 /usr/local/sublime_text_3/sublime_text /etc/nginx/nginx.conf
root     18762  0.0  0.0 122720  2880 ?        Ss   20:53   0:00 nginx: master process /usr/sbin/nginx
nginx    18763  0.0  0.1 124808  7916 ?        S    20:53   0:00 nginx: worker process
nginx    18764  0.0  0.1 124808  7916 ?        S    20:53   0:00 nginx: worker process
nginx    18765  0.0  0.1 124808  7916 ?        S    20:53   0:00 nginx: worker process
nginx    18766  0.0  0.1 124808  7916 ?        S    20:53   0:00 nginx: worker process
root     18988  0.0  0.0 111032  1792 pts/0    S+   20:54   0:00 tail -f 10 /var/log/nginx/error.log
root     19001  0.0  0.0 115820  2396 pts/1    S+   20:55   0:00 grep --color=auto nginx

So I know it is running. I used to get an error in the log, telling me nginx couldn't bind to a specific port, which was caused by SELinux only allowing certain ports for it to bind to. I fixed that using the command semanage port --add --type http_port_t --proto tcp 7777.

After each change I always ran systemctl restart nginx, to restart the nginx server, so that it can reload its configuration.

I use gunicorn app:app -b localhost:8080 to run my flask app.

When I open the URL http://localhost:8080/static/ in the browser, I get a 404 and the log I read using tail -f 10 /var/log/nginx/error.log states no new errors. The flask app is running though, which I can verify by going to: http://localhost:8080/ and http://localhost:8080/data, which both work fine. However, once there is static content from the static directory, I get the 404.

My guesses are the following:

  1. Somehow nginx is not being talked to and it doesn't know about the request for the static folder content.
  2. Somehow the paths are still not correct.
  3. There is some other issue that prevents it from getting the file for the browser and making it not log that.

I've tried to get it running for two days now, but none of the configurations I found worked for me. I also tried the following two commands, which were suggested in other places:

  1. Change Security Context of a Directory recursively:

    chcon -Rt httpd_sys_content_t /home/xiaolong/development/Python/flask_nginx_gunicorn/

  2. Allow the http daemon to connect using the network (???)

    setsebool -P httpd_can_network_connect 1

What's wrong with my configuration?

Additional Info

In my /etc/nginx/ directory I have the following structure:

  • one nginx.conf file
  • sub directory sites-available containing only the config for my flask app
  • sub directory sites-enabled containing a link to my config file for the flask app in sites-available

I am running a Fedora 22 here.

Best Answer

This is over a year old at this point so I'm sure you've worked this out, but in case anyone else sees this:

Nginx is listening on localhost:7777, but your URL is taking you to port 8080 where your gunicorn server lives. This is why you can get to your Flask app (served by gunicorn) but not your static content (served by ngninx). This is also why you're not getting anything in your nginx logs. If you go to http://localhost:7777/, nginx should pass your request through to your Flask app, and http://localhost:7777/static/ should take you to the static content.