0

I have a Django app with postgres back-end where I'm configuring gunicorn to work behind nginx as reverse proxy. My machine runs Ubuntu 14.04.

Everything seems to have worked, except I've run into a nasty error that's thrown the moment I try to log into my app:

DatabaseError at /login/

invalid input syntax for type inet: "" LINE 1: ...00101 Firefox/41.0', '2015-12-12 09:39:55.590036+00:00', '')

Exception Location: /home/mhb11/.virtualenvs/redditpk/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py in execute, line 54

Note that this error never comes if I use solely Gunicorn! Can you help me fix this issue? I have a few inklings:

1) The inet data type accepts IPv4 and IPv6 hosts and networks (but not domain names). Maybe I ought to change the domain name I've used in my /etc/nginx/sites-available/myproject? But I tried it; my website fails to load at all (whereby hitherto it only failed after I tried to log in). The code in /etc/nginx/sites-available/myproject is pasted below.

2) A different theory goes something like this:

When I try to log in, my code tries to add a row to some logging table with empty remote IP. It's possible that when I use reverse proxy, the code doesn't know the remote IP, as it's shadowed by the proxy's IP.

Since it's empty, it's possible the code tries to ignore proxy's IP, but it does not find any better. Hence, it should use X-Forwarded-For header.

And if there's no reasonable IP to log, the program should simply log "NULL" as the IP.

To this end, I included proxy_params in /etc/nginx/sites-available/myproject. After that, I ran sudo service nginx restart, and reloaded my website. The error still remains.

I need help from an expert who can assist me in solving it.


/etc/nginx/sites-enabled/myproject:

server {
    listen 80;
    server_name example.cloudapp.net;

    location = /favicon.ico { access_log off; log_not_found off; }

    location /static/ {

        root /home/mhb11/folder/myproject;
    }

    location / {

        include proxy_params;
        proxy_pass http://unix:/home/mhb11/folder/myproject/myproject.sock;

    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /home/mhb11/folder/myproject/templates/;
   }
}

/etc/nginx/proxy_params:

proxy_set_header Host $http_host;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

/etc/nginx/nginx.conf:

user www-data;
worker_processes 4;
pid /run/nginx.pid;

env ON_AZURE=1;
env awsaccesskeyid=something;
env awssecretkey=something;

events {
        worker_connections 1024;
        multi_accept on;
        use epoll;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##
        gzip on;
        gzip_disable "msie6";

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascrip$

        ##
        # nginx-naxsi config
        ##
        # Uncomment it if you installed nginx-naxsi
        ##

        #include /etc/nginx/naxsi_core.rules;

        ##
        # nginx-passenger config
        ##
        # Uncomment it if you installed nginx-passenger
        ##

        #passenger_root /usr;
        #passenger_ruby /usr/bin/ruby;

        ##
        # Virtual Host Configs
        ##

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


#mail {
#       # See sample authentication script at:
#       # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#       # auth_http localhost/auth.php;
#       # pop3_capabilities "TOP" "USER";
#       # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#       server {
#               listen     localhost:110;
#               protocol   pop3;
#               proxy      on;
#       }
#
#       server {
#               listen     localhost:143;
#               protocol   imap;
#               proxy      on;
#       }
#}

Note: feel free to ask for more information in case you need it.

1

Since this is an postgresql error you should probably start by enabling postgresql query log and see what exactly is the erroneous sql query, what is supplied to postgres as 'inet', should be ip/mask(type inet).

Once you've got hold of the broken sql query you can get better understanding which part of the code is issuing it and continue down the line.

You can also check this one which seems to be a common Django/nginx issue

https://stackoverflow.com/questions/1627901/remote-addr-not-getting-sent-to-django-using-nginx-tornado.

Obviously the proxy is not normally passing some of the http headers, this should fix it.

  • I took your advice. It seems that postgresql only stores IP of type INET, and does NOT accept ' ' as a value. Now request.META in django shows me that REMOTE_ADDR is ' ' (i.e. the IP of the client). From nginx.conf, I'm able to pass a value for HTTP_X_REAL_IP and HTTP_REMOTE_ADDR, but not REMOTE_ADDR. How do I set a value for that? Any ideas? That will solve this question. – Hassan Baig Dec 13 '15 at 11:23
  • Ive modified the answer a bit, looks like this is known issue – EvilTorbalan Dec 13 '15 at 11:31
  • Ah my friend, I've actually gone over that one and tried adding proxy_set_header REMOTE_ADDR $remote_addr; to my nginx.conf. request.META still showed REMOTE_ADDR to be ' '. I couldn't tell whether nginx just never correctly passed it, or Django never correctly retrieved it. Any way I can print out what nginx is passing? Theoretically, the reason may be that my nginx reverse proxy is set up with gunicorn (whereas the gentlemen in the SO post you shared is using Tornado with Nginx). – Hassan Baig Dec 13 '15 at 11:38
  • Let me also add that it does work perfectly with solely gunicorn (or waitress, another pure python webserver). So it does seem that the issue is on the end of nginx. – Hassan Baig Dec 13 '15 at 11:41
  • Well, at least you know now where to look, there have been multiple answers in that link, have you seen all of them, they are not the same. – EvilTorbalan Dec 13 '15 at 11:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.