pythondjangoubuntunginxdigital-ocean

Unable to redirect non-www to www in django Nginx project on Digital Ocean


Hello I would be grateful if someone could please help with the following Nginx configuration:

/etc/nginx/sites-available/example

server {
    server_name *.example.com;

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

    location /static/ {
        alias /home/admin/pyapps/example/example/static/;
    }

    location /static/admin/ {
        alias /home/admin/pyapps/example/example/static/admin/;
    }

    location /media/ {
        root /home/admin/pyapps/example;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }


    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}


server {
    if ($host = admin.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = backoffice.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = www.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name example.com *.example.com;
    return 404; # managed by Certbot
}

I would like to create a redirection for example.com to https://www.example.com.

Note that I am using django-hosts.

My configuration for django-hosts below:

settings.py

ROOT_URLCONF = 'example.urls'
ROOT_HOSTCONF = 'example.hosts'
DEFAULT_HOST = 'www'
# DEFAULT_REDIRECT_URL = "http://www.example.com:8000"
DEFAULT_REDIRECT_URL = "http://www.example.com"
PARENT_HOST = 'example.com'
# HOST_PORT = '8000'

MIDDLEWARE = [
    'django_hosts.middleware.HostsRequestMiddleware',
    ....
    'django_hosts.middleware.HostsResponseMiddleware',
]

hosts.py

from django.conf import settings
from django_hosts import patterns, host
from example.hostsconf import urls as redirect_urls
from . import admin_urls

host_patterns = patterns('',
    host(r'www', settings.ROOT_URLCONF, name='www'),
    host(r'admin', admin_urls, name='admin'),
    host(r'backoffice', 'backoffice.urls', name="backoffice"),
    host(r'(?!www).*', redirect_urls, name='wildcard'),
)

hostsconf/urls.py

from django.urls import path
from .views import wildcard_redirect

urlpatterns = [
    path(r'^?P<path>.*)', wildcard_redirect),
]

hostsconf/views.py

from django.conf import settings
from django.http import HttpResponseRedirect

DEFAULT_REDIRECT_URL = getattr(settings, "DEFAULT_REDIRECT_URL", "http://www.example.com")

def wildcard_redirect(request, path=None):
    new_url = DEFAULT_REDIRECT_URL
    if path is not None:
        new_url = DEFAULT_REDIRECT_URL + '/' + path
    return HttpResponseRedirect(new_url)

I have tried pretty much everything, but I think it might have to do with the django-hosts config.

When I go to https://example.com, it shows me the 'Welcome to nginx' screen instead of redirecting to https://www.example.com.

enter image description here

When I go to www.example.com or to admin.example.com or to backoffice.example.com, the website loads fine.

Someone please assist me. I would like to redirect https://example.com to https://www.example.com

Let me know if you need any other configuration from me.


Solution

  • in your second block

    server {
        if ($host = admin.example.com) {
            return 301 https://$host$request_uri;
        } # managed by Certbot
    
    
        if ($host = backoffice.example.com) {
            return 301 https://$host$request_uri;
        } # managed by Certbot
    
    
        if ($host = example.com) {
            return 301 https://www.$host$request_uri;
        } # managed by Certbot
    
        listen 80;
        server_name example.com *.example.com;
        return 404; # managed by Certbot
    }
    ```
    

    change www.example.com in your condition
    return https://www.$host$request_uri;


    Edit made by OP

    It turns out the above is correct, however I had an additional change to make.

    There is a default nginx config file under /etc/nginx/sites-available and it is called default.

    In this file, the server block at the bottom must be removed.

        #server {
        #    if ($host = example.com) {
        #        return 301 https://$host$request_uri;
        #    } # managed by Certbot
        
        
        #       listen 80 ;
        #       listen [::]:80 ;
        #    server_name example.com;
        #    return 404; # managed by Certbot
        
        
        #}
    

    What was happening is that this block was running first when requesting example.com and it was redirecting to https://example.com.

    Or maybe I could have edited the server block in the default file. But I did not try it. I prefer to have all the configuration in one place.