Deploying SSL for my Django 2.0.1 server with Apache on Ubuntu 16.04 (droplet)

613 views
Skip to first unread message

drone4four

unread,
Jan 20, 2018, 10:00:57 PM1/20/18
to Django users
I’ve played with a little Django (v2.0.1) locally. Now I am trying to implement a test case on my production Apache web server. I’m running an Ubuntu 14.04 DigitalOcean droplet (will upgrade to 18.04 later this year).

I got Django running.


Before I log into my admin panel, I figure it’s best practices to set up HTTPS first. But when I visit that URL, Chrome throws this message:


This site can’t provide a secure connection http://www.angeles4four.info sent an invalid response. ERR_SSL_PROTOCOL_ERROR

And my shell on my server shows this message:

[20/Jan/2018 23:54:39] "GET / HTTP/1.1" 200 16559 [21/Jan/2018 00:01:23] code 400, message Bad request syntax ('\x16\x03\x01\x00Ì\x01\x00\x00È\x03\x03&6U\x10µ\x82\x97\x7f´8\x1e«\x0e¿ÿ§\x89æ\x82\r¢G§\x01ç°P%\x80)ÕÃ\x00\x00\x1c * À+À/À,À0̨̩À\x13À\x14\x00\x9c\x00\x9d\x00/\x005\x00') [21/Jan/2018 00:01:23] You're accessing the development server over HTTPS, but it only supports HTTP.

That’s because SSL isn’t set up. My current SSL Certificate Authority is Let’s Encrypt. SSL is running properly for my public_html content but not for my recent deployment of Django.

I found some resources elsewhere on SO for setting up SSL with Django.

In an SO post titled, “Configure SSL Certificate on Apache for Django Application (mod_wsgi)”, a highly upvoted answer by Alexey Kuleshevich suggests a template for 000-default.conf and default-ssl.conf for Apache vhosts. See here: Configure SSL Certificate on Apache for Django Application (mod_wsgi)

I did my best to change up the suggested values and entries so that they refer to my specific configuration. Here are what these two vhost configuration files of mine look like now.

/etc/apache2/sites-available/angeles4four.info-le-ssl.conf:

<IfModule mod_ssl.c>
<VirtualHost *:443>
#ServerName http://www.example.com
ServerAdmin coffee.dri...@gmail.com
ServerName angeles4four.info
ServerAlias http://www.angeles4four.info
DocumentRoot /var/www/html/angeles4four.info/public_html


ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined


# Django Application
Alias /static /var/www/html/angeles4four.info/public_html/Cel2FahConversion
<Directory /var/www/html/angeles4four.info/public_html/Cel2FahConversion>
Require all granted
</Directory>
<Directory /var/www/html/angeles4four.info/public_html/Cel2FahConversion>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WGIDaemonProcess cel python-path=/var/www/html/angeles4four.info/public_html/Cel2FahConversion/venv/bin/python3
WSGIProcessGroup cel
WSGIScriptAlias / /var/www/html/angeles4four.info/public_html/Cel2FahConversion/Cel2FahConversion/Cel2FahConversion/wsgi.py


SSLCertificateFile /etc/letsencrypt/live/angeles4four.info/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/angeles4four.info/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateChainFile /etc/letsencrypt/live/angeles4four.info/chain.pem
</VirtualHost>
</IfModule>


angeles4four.info.conf:

Quote:
<VirtualHost *:80>


#ServerName http://www.example.com
ServerAdmin coffee.drinker.daniel@gmail.com
ServerName angeles4four.info
ServerAlias http://www.angeles4four.info
DocumentRoot /var/www/html/angeles4four.info/public_html
<Directory "/var/www/html/angeles4four.info/public_html">
Options Indexes FollowSymlinks
AllowOverride All
Require all granted
</Directory>


ErrorLog ${APACHE_LOG_DIR}/
error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined


RewriteEngine on
RewriteCond %{SERVER_NAME} =angeles4four.info [OR]
RewriteCond %{SERVER_NAME} =www.angeles4four.info
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

No dice. I still get the same traceback as I initially shared.

The next SO post I came across suggests modifying settings.py. Here it is: Error "You're accessing the development server over HTTPS, but it only supports HTTP"

The upvoted suggestion here by YoYo is to modify session cookies and secure SSL redirect. YoYo also recommends managing base, local, production settings which doesn’t really apply to me. So I tried adding these three lines to my settings.py:


SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE
= True
SECURE_SSL_REDIRECT
= True


My python3 manage.py runserver shell traceback still says: “You're accessing the development server over HTTPS, but it only supports HTTP.”

Any ideas? What else could I try?

Thanks for your attention.

Antonis Christofides

unread,
Jan 21, 2018, 3:27:41 AM1/21/18
to django...@googlegroups.com

Hello,

I'm not certain I understand what you are describing. Is Apache listening on port 8000? How is it possible that you are using "runserver" when you are running Django through mod_wsgi? Something is wrong there.

Also, don't put your Django app's files in public_html or any other directory that is publicly served by Apache. You don't want visitors from the web reading your source code (or, much worse, your settings file with its secrets). If you haven't done this before you may be confused by static files, in which case this article (of mine) may help.

Regards,

Antonis

Antonis Christofides
http://djangodeployment.com
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/c0592c57-9a5a-4693-b685-80933643eb49%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Phang Mulianto

unread,
Jan 21, 2018, 5:01:19 AM1/21/18
to django-users
Hi

If you use ssl on apache, the ssl terminate only on apache request from client, then the wsgi from apache is no https. 

So ssl handled by your webserver service, whether the webserver you use is apache or nginx.

Try access the static file with https is it working? 



On 21 Jan 2018 4:26 pm, "Antonis Christofides" <ant...@djangodeployment.com> wrote:

Hello,

I'm not certain I understand what you are describing. Is Apache listening on port 8000? How is it possible that you are using "runserver" when you are running Django through mod_wsgi? Something is wrong there.

Also, don't put your Django app's files in public_html or any other directory that is publicly served by Apache. You don't want visitors from the web reading your source code (or, much worse, your settings file with its secrets). If you haven't done this before you may be confused by static files, in which case this article (of mine) may help.

Regards,

Antonis

Antonis Christofides
http://djangodeployment.com

On 2018-01-21 05:00, drone4four wrote:
I’ve played with a little Django (v2.0.1) locally. Now I am trying to implement a test case on my production Apache web server. I’m running an Ubuntu 14.04 DigitalOcean droplet (will upgrade to 18.04 later this year).

I got Django running.


Before I log into my admin panel, I figure it’s best practices to set up HTTPS first. But when I visit that URL, Chrome throws this message:


This site can’t provide a secure connection http://www.angeles4four.info sent an invalid response. ERR_SSL_PROTOCOL_ERROR

And my shell on my server shows this message:

[20/Jan/2018 23:54:39] "GET / HTTP/1.1" 200 16559 [21/Jan/2018 00:01:23] code 400, message Bad request syntax ('\x16\x03\x01\x00Ì\x01\x00\x00È\x03\x03&6U\x10µ\x82\x97\x7f´8\x1e«\x0e¿ÿ§\x89æ\x82\r¢G§\x01ç°P%\x80)ÕÃ\x00\x00\x1c * À+À/À,À0̨̩À\x13À\x14\x00\x9c\x00\x9d\x00/\x005\x00') [21/Jan/2018 00:01:23] You're accessing the development server over HTTPS, but it only supports HTTP.

That’s because SSL isn’t set up. My current SSL Certificate Authority is Let’s Encrypt. SSL is running properly for my public_html content but not for my recent deployment of Django.

I found some resources elsewhere on SO for setting up SSL with Django.

In an SO post titled, “Configure SSL Certificate on Apache for Django Application (mod_wsgi)”, a highly upvoted answer by Alexey Kuleshevich suggests a template for 000-default.conf and default-ssl.conf for Apache vhosts. See here: Configure SSL Certificate on Apache for Django Application (mod_wsgi)

I did my best to change up the suggested values and entries so that they refer to my specific configuration. Here are what these two vhost configuration files of mine look like now.

/etc/apache2/sites-available/angeles4four.info-le-ssl.conf:

<IfModule mod_ssl.c>
<VirtualHost *:443>
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

drone4four

unread,
Jan 26, 2018, 1:21:07 AM1/26/18
to Django users

You’re right, @Antonis, that I don’t want my Django source code exposed. No sysadmin would.  I have since moved my Django project folder to my home user’s directory. However (out of curiosity), if I continued to house Django in my public_html folder (which I am not any more, but say if i did) I would think that my .htaccess config file would prevent unauthorized access to my Django source.  Am I right?


I didn’t realize that Django was suppose to be run using wsgi.  I was just foolishly running the server with ``$ python manage.py runserver 0.0.0.0:8000`` like when I was testing locally when I was coding my app. The keyword here is mod_wsgi.  So I found this guide. I followed along but the issue I now have is that Apache serves my public_html folder (just some light  HTML, CSS and Js).  Serving these contents take priority over Django.  I’m OK with this. I would prefer to keep my public_html folder accessible as it is, but how do I arrange for wsgi to serve Django from a subdirectory, say: www.angeles4four.info/cel2fah or something like that?


@Mulianto:

An example of a static file would be a style sheet, like: ~/cel2fah/static/admin/css/responsive.css

How would trying to access this CSS file help?

I tried:

http://www.angeles4four.info:8000/cel2fah/static/admin/css/responsive.css

https://www.angeles4four.info:8000/cel2fah/static/admin/css/responsive.css

Both show “This site can’t be reached”


Here are the contents of my two apache configuration files.


/etc/apache2/sites-available/angeles4four.info.conf :


<VirtualHost *:80>



        ServerAdmin coffee.dri...@gmail.com

        ServerName angeles4four.info

        ServerAlias www.angeles4four.info

        DocumentRoot /var/www/html/angeles4four.info/public_html


       
<Directory "/var/www/html/angeles4four.info/public_html">


                Options Indexes FollowSymlinks

                AllowOverride All

                Require all granted

       
</Directory>



        ErrorLog ${APACHE_LOG_DIR}/error.log

        CustomLog ${APACHE_LOG_DIR}/access.log combined


        RewriteEngine on

        RewriteCond %{SERVER_NAME} =angeles4four.info [OR]

        RewriteCond %{SERVER_NAME} =www.angeles4four.info

        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]


        Alias /static /home/tranq/cel2fah/static


       
<Directory /home/tranq/cel2fah/static>

                Require all granted

       
</Directory>


       
<Directory /home/user/cel2fah/cel2fah/>


               
<Files wsgi.py>

                Require all granted

               
</Files>

       
</Directory>



        WSGIDaemonProcess cel2fah python-path=/home/tranq/cel2fah python-home=/home/tranq/cel2fah/venv

        WSGIProcessGroup cel2fah

        WSGIScriptAlias / /home/tranq/cel2fah/cel2fah/wsgi.py


</VirtualHost>



And /etc/apache2/sites-available/angeles4four.info.conf :


<IfModule mod_ssl.c>



<VirtualHost *:443>


        ServerAdmin coffee.dri...@gmail.com

        ServerName angeles4four.info

        ServerAlias www.angeles4four.info


        DocumentRoot /var/www/html/angeles4four.info/public_html



        ErrorLog ${APACHE_LOG_DIR}/error.log

        CustomLog ${APACHE_LOG_DIR}/access.log combined


        Alias /static /home/tranq/cel2fah/static


       
<Directory /home/tranq/cel2fah/static>

                Require all granted

       
</Directory>


       
<Directory /home/user/cel2fah/cel2fah/>


               
<Files wsgi.py>

                Require all granted

               
</Files>

       
</Directory>



        # WSGIDaemonProcess cel2fah python-path=/home/tranq/cel2fah python-home=/home/tranq/cel2fah/venv

        # WSGIProcessGroup cel2fah

        # WSGIScriptAlias / /home/tranq/cel2fah/cel2fah/wsgi.py



        SSLCertificateFile /etc/letsencrypt/live/angeles4four.info/cert.pem

        SSLCertificateKeyFile /etc/letsencrypt/live/angeles4four.info/privkey.pem

        Include /etc/letsencrypt/options-ssl-apache.conf

        SSLCertificateChainFile /etc/letsencrypt/live/angeles4four.info/chain.pem

</VirtualHost>


</IfModule>


Thanks to you both for your help so far.

On Saturday, January 20, 2018 at 10:00:57 PM UTC-5, drone4four wrote:
I’ve played with a little Django (v2.0.1) locally. Now I am trying to implement a test case on my production Apache web server. I’m running an Ubuntu 14.04 DigitalOcean droplet (will upgrade to 18.04 later this year).

I got Django running.


Before I log into my admin panel, I figure it’s best practices to set up HTTPS first. But when I visit that URL, Chrome throws this message:


This site can’t provide a secure connection http://www.angeles4four.info sent an invalid response. ERR_SSL_PROTOCOL_ERROR

And my shell on my server shows this message:

[20/Jan/2018 23:54:39] "GET / HTTP/1.1" 200 16559 [21/Jan/2018 00:01:23] code 400, message Bad request syntax ('\x16\x03\x01\x00Ì\x01\x00\x00È\x03\x03&6U\x10µ\x82\x97\x7f´8\x1e«\x0e¿ÿ§\x89æ\x82\r¢G§\x01ç°P%\x80)ÕÃ\x00\x00\x1c * À+À/À,À0̨̩À\x13À\x14\x00\x9c\x00\x9d\x00/\x005\x00') [21/Jan/2018 00:01:23] You're accessing the development server over HTTPS, but it only supports HTTP.

That’s because SSL isn’t set up. My current SSL Certificate Authority is Let’s Encrypt. SSL is running properly for my public_html content but not for my recent deployment of Django.

I found some resources elsewhere on SO for setting up SSL with Django.

In an SO post titled, “Configure SSL Certificate on Apache for Django Application (mod_wsgi)”, a highly upvoted answer by Alexey Kuleshevich suggests a template for 000-default.conf and default-ssl.conf for Apache vhosts. See here: Configure SSL Certificate on Apache for Django Application (mod_wsgi)

I did my best to change up the suggested values and entries so that they refer to my specific configuration. Here are what these two vhost configuration files of mine look like now.

/etc/apache2/sites-available/angeles4four.info-le-ssl.conf:

<IfModule mod_ssl.c>
<VirtualHost *:443>

drone4four

unread,
Jan 27, 2018, 12:20:07 AM1/27/18
to Django users

The username on my droplet is ‘tranq’ but there is a line in both my vhost config files which reads:


<Directory /home/user/cel2fah/cel2fah/>


So I swapped out ‘user’ for ‘tranq’. That line now reads:


<Directory /home/tranq/cel2fah/cel2fah/>


Now some of my static files are accessible.  For example you can see here:


https://www.angeles4four.info/static/admin/css/responsive.css

https://www.angeles4four.info/static/admin/css/login.css


But the following is still saying, “Forbidden”:


https://www.angeles4four.info/static/admin/


This may be pointing to an issue I noticed with how my user and group permissions are set up for Django.  The sqlite.db file was grouped in with ‘tranq’. According to the guide I’ve been using, it should be: ‘www-data’.  I’m not sure how I overlooked this mistake because I very clearly remember doing it properly.  I think I’m conflating this with one of my multiple recent previous attempts following this guide. Anyways, here is what my group permissions look like now from within my project directory:


$ ls -la

total 68

drwxrwxr-x  5 tranq www-data  4096 Jan 25 23:12 .

drwxr-xr-x 18 tranq tranq     4096 Jan 26 21:57 ..

drwxrwxr-x  3 tranq tranq     4096 Jan 25 23:13 cel2fah

-rw-rw-r--  1 tranq www-data 38912 Jan 25 23:11 db.sqlite3

-rwxrwxr-x  1 tranq tranq      539 Jan 25 23:05 manage.py

drwxrwxr-x  3 tranq tranq     4096 Jan 25 23:12 static

drwxrwxr-x  5 tranq tranq     4096 Jan 25 23:04 venv


Notice sqlite.db above? It now says ‘www-data’.  This is how it should be, right?


The parent directory (home user folder) shows these permissions for my project:


...

drwxrwxr-x  5 tranq www-data  4096 Jan 25 23:12 cel2fah


Does this look right to all of you?


The steps I took to arrange the permissions as such were from the bottom of the mod_wsgi guide on DigitalOcean which I referred to initially.

Thanks for your attention.

On Friday, January 26, 2018 at 1:21:07 AM UTC-5, drone4four wrote:

You’re right, @Antonis, that I don’t want my Django source code exposed. No sysadmin would.  I have since moved my Django project folder to my home user’s directory. However (out of curiosity), if I continued to house Django in my public_html folder (which I am not any more, but say if i did) I would think that my .htaccess config file would prevent unauthorized access to my Django source.  Am I right?


I didn’t realize that Django was suppose to be run using wsgi.  I was just foolishly running the server with ``$ python manage.py runserver 0.0.0.0:8000`` like when I was testing locally when I was coding my app. The keyword here is mod_wsgi.  So I found this guide. I followed along but the issue I now have is that Apache serves my public_html folder (just some light  HTML, CSS and Js).  Serving these contents take priority over Django.  I’m OK with this. I would prefer to keep my public_html folder accessible as it is, but how do I arrange for wsgi to serve Django from a subdirectory, say: www.angeles4four.info/cel2fah or something like that?


@Mulianto:

An example of a static file would be a style sheet, like: ~/cel2fah/static/admin/css/responsive.css

How would trying to access this CSS file help?

I tried:

http://www.angeles4four.info:8000/cel2fah/static/admin/css/responsive.css

https://www.angeles4four.info:8000/cel2fah/static/admin/css/responsive.css

Both show “This site can’t be reached”


Here are the contents of my two apache configuration files.


/etc/apache2/sites-available/angeles4four.info.conf :


<VirtualHost *:80>



        ServerAdmin coffee.drinker.daniel@gmail.com
<Directory "/var/www/html/angeles4four.info/public_html">



And /etc/apache2/sites-available/angeles4four.info.conf :




        ServerAdmin coffee.drinker.daniel@gmail.com
<Directory /home/tranq/cel2fah/static>

Antonis Christofides

unread,
Jan 27, 2018, 3:22:27 AM1/27/18
to django...@googlegroups.com


But the following is still saying, “Forbidden”:


https://www.angeles4four.info/static/admin/

This is normal. The reason is not the filesystem permissions, but that Apache is configured to not list files inside that directory (to change that you'd need to use "Options Indexes" somewhere, but you don't want to change that). You can still access any file in that directory, but it will not tell you which files are available. This is the correct thing to do.

...

drwxrwxr-x  5 tranq www-data  4096 Jan 25 23:12 cel2fah


Does this look right to all of you?

It's OK, though it could be better. Apache only needs to read that directory, not write it. Apache is user www-data and group www-data, and this directory is writeable by group www-data, that is, writeable by Apache. So better permissions for that would be drwxr-xr-x (which you can achieve with "chmod 755 cel2fah" or "chmod g-w cel2fah").

Regards,

Antonis

Antonis Christofides
http://djangodeployment.com
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
Reply all
Reply to author
Forward
0 new messages