Django LoginView does not work on linux

I’m trying to deploy Django on Linux. This works on my local Windows machine but not on the Linux server. At first, the web page appeared when I accessed it, but when I filled in the username and password and pressed login, Django stopped responding. No logs even appeared. Are there any settings I need to add? i’m not used to linux server.

i have already put my ip address on ALLOWED_HOST in settings.py.

here’s my registration/login.html

                            <form method="POST" action="{% url 'csauth:login' %}" class="needs-validation"
                                  novalidate="">
                                {% csrf_token %}
                                <div class="form-group">
                                    <label for="username">Username</label>
                                    <input id="username" type="text" class="form-control" name="username" tabindex="1"
                                           required autofocus>
                                    <div class="invalid-feedback">
                                        Please fill in your username
                                    </div>
                                </div>

                                <div class="form-group">
                                    <label for="password" class="control-label">Password</label>
                                    <input id="password" type="password" class="form-control" name="password"
                                           tabindex="2" required>
                                    <div class="invalid-feedback">
                                        please fill in your password
                                    </div>
                                </div>

                                <div class="form-group">
                                    <button type="submit" class="btn btn-primary btn-lg btn-block" tabindex="4">
                                        Login
                                    </button>
                                </div>
                            </form>

urls.py

urlpatterns = [
    # url(r'^home/', views.home, name='home'),
    # path('', include('django.contrib.auth.urls')),
    url('login/', auth_views.LoginView.as_view(redirect_authenticated_user=True), name='login'),
    url('logout/', auth_views.LogoutView.as_view(), name='logout'),
    url('decode/', views.decode, name='decode'),
]

Welcome @adammmmd !

You’ll need to provide more details here.

Describe your deployment.

  • How are you running your project?
  • What wsgi container are you using? (uwsgi? gunicorn?).
  • What web server are you running this with? (nginx?, apache?)
  • What guides (documentation, blogs, tutorial) are you using as your reference for your deployment?
  • Have you gone through all the steps in the Django deployment checklist?

Check the logs on the server to see what error messages are being generated. Don’t check your application logs alone, but also check your web server logs, your wsgi container logs, and quite possibly syslog as well.

When you say:

Does this mean that after you submitted an id and password, you can’t even bring the login page back up again?

its actually my first time trying to deploy on server :smiling_face_with_tear:

  • its running on virtual machine
  • i’m using gunicorn as wsgi container

app.service

[Unit]
Description=app

[Service]
Restart=on-failure
User=root
WorkingDirectory=/directory/app
ExecStart=/directory/app/virtualenv/bin/gunicorn -b unix:/tmp/app.socket app.wsgi:application --workers=8 --timeout 900

[Install]
WantedBy=multi-user.target
  • i’m using nginx as web server. nginx config is already exist so im just deleted comment

sites-available/app.conf

server {
    listen 8088;
    listen [::]:8088;

    root /var/www/html;

    index index.html index.htm;

    client_max_body_size 100M;

    location /static {
        alias /directory/app/static;
    }

    location / {
                proxy_pass http://unix:/tmp/app.socket;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Connection "";
                proxy_connect_timeout 1200s;
                proxy_read_timeout 1200s;

        }

    location /.well-known {
                alias /var/www/html/.well-known;
        }

    access_log /var/log/nginx/app-access.log;
    error_log /var/log/nginx/app-error.log;
}
  • actually i’m just redeploy the project. project is already exist in vm. im not using any tutorial
  • i tried “manage.py check --deploy” and here is the answer
System check identified some issues:

WARNINGS:
?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems.
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over both SSL and non-SSL connections, you may want to either set this setting True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.
?: (security.W009) Your SECRET_KEY has less than 50 characters, less than 5 unique characters, or it's prefixed with 'django-insecure-' indicating that it was generated automatically by Django. Please generate a long and random SECRET_KEY, otherwise many of Django's security-critical features will be vulnerable to attack.
?: (security.W012) SESSION_COOKIE_SECURE is not set to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.
?: (security.W016) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE, but you have not set CSRF_COOKIE_SECURE to True. Using a secure-only CSRF cookie makes it more difficult for network traffic sniffers to steal the CSRF token.
?: (security.W018) You should not have DEBUG set to True in deployment.

System check identified 6 issues (0 silenced).

and here is the log

syslog

Aug  5 12:02:21 app systemd-timesyncd[668]: Timed out waiting for reply from xx.xxx.xx.xxx:111 (ntp.ubuntu.com).

nginx error.log

2024/08/05 07:33:31 [error] 166096#166096: *944 upstream timed out (110: Connection timed out) while reading response header from upstream, client: xxx.xxx.xx.xxx, server: _, request: "POST /accounts/login/ HTTP/1.1", upstream: "http://xxx.xxx.xx.xxx:8088/accounts/login/", host: "xxx.id", referrer: "https://xxx.id/accounts/login/"
2024/08/05 08:59:37 [error] 166096#166096: *979 upstream timed out (110: Connection timed out) while reading response header from upstream, client: xxx.xxx.xx.xxx, server: _, request: "POST /accounts/login/ HTTP/1.1", upstream: "http://xxx.xxx.xx.xxx:8088/accounts/login/", host: "xxxx.id", referrer: "https://xxx.id/accounts/login/"

i can only access login page. when i input username and password. login page doesn’t respond anything. after some time nginx gives error 504 warning. i use sqlite as database.

Check the permissions on the /tmp/app.socket file. You’re running gunicorn as root (in general, a very bad idea, but not the direct cause of this issue), and so I think it’s unlikely that the nginx account is going to have “write” permissions to that socket.

What should I do about that?
Is there anything else I should pay attention to or check?

About which, the permissions on the socket file?

If so, you’ve got a couple of different options. Some people suggest using a separate service to create the socket. (See step 5 at How To Set Up Django with Postgres, Nginx, and Gunicorn on Debian 10 | DigitalOcean for an example.)

We’ve used the systemd tmpfiles facility to create them in some cases.

We’ve also used the settings within uwsgi directly. (We use uwsgi, not gunicorn. It provides some different options.)

Regarding the logs, I’d be expecting to see something of value in the gunicorn logs or syslog related to gunicorn. I can only suggest that you start looking through everything in /var/log to find information about what’s going wrong.

I’m sorry for not providing the details of what I have tried earlier. I’m not sure if there is something wrong with Django or Nginx because when I try this before with manage.py runserver on the same server, it also gets stuck on the login page, and I can’t submit the form (no changes are made to the SQLite database). I have tried it in several different folders and with different users, but the result is the same. However, when I did the same thing on another development server using manage.py runserver, it worked (changes were written to SQLite).

Here are the logs when I run the server on the development server:

[06/Aug/2024 03:20:27] "GET /accounts/login/?next=/ HTTP/1.1" 200 4805
[06/Aug/2024 03:20:29] "GET /accounts/login/?next=/ HTTP/1.1" 200 4805
[06/Aug/2024 03:20:35] "POST /accounts/login/ HTTP/1.1" 302 0
[06/Aug/2024 03:20:35] "GET / HTTP/1.1" 200 47183
[06/Aug/2024 03:20:36] "POST /backend/api HTTP/1.1" 200 64
[06/Aug/2024 03:20:36] "POST /backend/api HTTP/1.1" 200 64
[06/Aug/2024 03:20:36] "POST /backend/api HTTP/1.1" 200 64

Here are the logs when I run the server on the deployment server:

[06/Aug/2024 03:24:20] "GET /accounts/login/?next=/ HTTP/1.1" 200 4805

Is there something wrong with the Linux server itself?

Highly unlikely. Yes, it’s possible, but that would be the last conclusion I would come to. It’s far more likely there’s some other configuration issue.

But the only suggestion I have for you at the moment is to keep looking through the different log files to find some indication of the underlying issue. If there’s a problem, it’s being logged somewhere.

The relevant logs should be in /var/log/nginx/errors depending on the instance of Linux. Or you could try:

journalctl --since=today | grep AVC
that would confirm if you are getting blocked by Selinux or having other permission issues

Here is error.log:

2024/08/06 13:56:45 [error] 177937#177937: *57 upstream timed out (110: Connection timed out) while reading response header from upstream, client: xxx.xxx.xxx, server: _, request: "POST /accounts/login/ HTTP/1.1", upstream: "http://xxx.xxx.xx.xxx:8088/accounts/login/", host: "xxx.id", referrer: "https://xxx..id/accounts/login/?next=/"

After a while, Nginx responds with 504:

xxx.xxx.xxx.xx - - [06/Aug/2024:13:56:45 +0700] "POST /accounts/login/ HTTP/1.1" 504 578 "https://xxx.id/accounts/login/?next=/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"

And this is app-access.log returning error 499. I still don’t know what’s wrong. This also happens when I use manage.py runserver:

xxx.xxx.xx.xxx - - [06/Aug/2024:13:56:45 +0700] "POST /accounts/login/ HTTP/1.0" 499 0 "https://xxx.id/accounts/login/?next=/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"

I have tried:

sudo journalctl --since=today | grep AVC

but nothing comes up.

Can we have a look at your upstream config for nginx (.conf) – the portion that points to your django/gunicorn proxy? It would also help to see relevant systemd unit files (.service).

The problem is happening between nginx and django/gunicorn. Nginx is waiting for response from your django/unicorn instance and its not coming. Your setup files might reveal more.

If you shouldn’t be using ./manage runserver when running in production.

Weird. I’ve just gone up and read previous posts. I now see you already posted your systemd settings. However, I don’t see the part that starts the socket.

Consider the following setup.

/etc/systemd/system/app.socket

[Unit]
Description=App socket

[Socket]
ListenStream=/run/app.sock
# Our service won't need permissions for the socket, since it
# inherits the file descriptor by socket activation
# only the nginx daemon will need access to the socket
SocketUser=nginx
SocketGroup=app #Assuming you have a unix group named 'app' that runs your django code
# Optionally restrict the socket permissions even more.
# SocketMode=600

[Install]
WantedBy=sockets.target

then you could modify your /etc/systemd/system/app.service file like so:

[Unit]
Description=App daemon
Requires=app.socket
After=network.target

[Service]
Type=notify
# the specific user that our service will run as
User=app
Group=app
# another option for an even more restricted service is
# DynamicUser=yes
# see http://0pointer.net/blog/dynamic-users-with-systemd.html
RuntimeDirectory=app
WorkingDirectory=/directory/app
ExecStart=/directory/app/virtualenv/bin/gunicorn project.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true

[Install]
WantedBy=multi-user.target

You may also need to check permissions on your /directory/app/virtualenv/ path. Selinux often flags those because of non-compliant labels. Fix those by relabelling the paths accordingly. It all depends on where you created your virtualenv

To clarify one point. There is no one error log. Error messages can be written in many different places, including syslog. You need to perform a more comprehensive search through all practical log files in /var/log, including those in subdirectories within that directory. The syslog, in particular, will often show errors being generated that aren’t strictly related to your application, but are otherwise inhibiting its proper operation.