03 Oct

SSL/TLS Certificates on Flask Application with Let’s Encrypt and NGINX

Let’s Encrypt is a new certificate authority (CA) offering free and automated SSL/TLS certificates. Certificates issued by Let’s Encrypt are trusted by most browsers in production today, including Internet Explorer on Windows Vista. Simply download and run the Let’s Encrypt client to generate a certificate.

(there are a few more steps than that, of course, though not many)
Step 1: Download LetsEncrypt

Install git if you haven’t done so yet:

# apt-get install git

Use git to get the application and store it somewhere (ie: /opt)

$ sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Step 2: Webroot Plugin

The Webroot plugin works by placing a special file in the /.well-known directory within your document root, which can be opened (through your web server) by the Let’s Encrypt service for validation.
Depending on your configuration, you may need to explicitly allow access to the /.well-known directory.

location /.well-known {
alias /home/user/webapps/appname/.well-known;
}

Restart NGNIX

# sudo service nginx status

 

Step 3: Generate your certificate and Strong Diffie-Hellman Group

The first time you run the command below, you will be asked to provide an e-mail address to be associated to the domain or subdomain, in case you should ever need to recover the key or something.
The next time you run the same command (to renew the certificate) it won’t be asked.

So run the following command to generate the certificate:

$ sudo /opt/letsencrypt/letsencrypt-auto certonly -a webroot –agree-tos –renew-by-default \

–webroot-path=/home/user/webapps/appname \

-d website.com [-d sub.website.com] \

–e-mail=email@website.com

Then Generate Strong Diffie-Hellman Group
This may take a few minutes but when it’s done you will have a strong DH group at /etc/ssl/certs/dhparam.pem.
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Step 4: Configuring Nginx

After running the command that generates the certificates, you should have several files in /etc/letsencrypt/live/website.com/ (replace website.com by your own domain).
We are going to need just two of them for Nginx: fullchain.pem and privkey.pem.
Comment out or delete the lines that configure this server block to listen on port 80.
The beginning of your server block should look like this:

server {

server_name website.com www.website.com;

listen 443 ssl;

ssl_certificate /etc/letsencrypt/live/website.com/fullchain.pem;

ssl_certificate_key /etc/letsencrypt/live/website.com/privkey.pem;

# For Safari and iOS devices

ssl_session_cache shared:SSL:20m;

 

#Diffie-Hellman Group

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_prefer_server_ciphers on;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

ssl_ciphers ‘ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA’;

ssl_session_timeout 1d;

ssl_stapling on;

ssl_stapling_verify on;

add_header Strict-Transport-Security max-age=15768000;

Lastly, outside of the original server block (that is listening on HTTPS, port 443), add this server block to redirect HTTP (port 80) to HTTPS.

server {
listen 80;
server_name website.com www.website.com;
return 301 https://$host$request_uri;
}

Put the changes into effect by restarting Nginx:

$ sudo service nginx restart

The Let’s Encrypt TLS/SSL certificate is now in place.

At this point, you should test that the TLS/SSL certificate works by visiting your domain via HTTPS in a web browser.
You can use the Qualys SSL Labs Report to see how your server configuration scores:

https://www.ssllabs.com/ssltest/analyze.html?d=website.com

Step 5: Automate the Certificate Renewal

Edit the crontab to create a new job that will run the renewal command every week.

$ sudo crontab –e

30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log

35 2 * * 1 /etc/init.d/nginx reload

01 Jun

uWSGI+NGINX on Linux (Centos 6)

Step 1 – Install NGINX

sudo yum install nginx

Step 2 – Add nginx to uobis group:

sudo usermod -a -G uobis nginx
sudo chmod g+x /home && chmod g+x /home/uobis && chmod g+x home/uobis/webapps/
sudo -u nginx stat /home/uobis/webapps/

cat >> kabbu.ini

[uwsgi]
module = wsgi
master = true
processes = 5
socket = kabbu.sock
chmod-socket = 660
vacuum = true

Step 3 – The uWSGI Emperor – multi-app deployment
exec uwsgi --emperor /etc/uwsgi/vassals/ --master --logto /var/log/uwsgi.log
Step 4 – Create a Upstart File

To make sure stuff is automatically run, here’s a configuration file that needs to be placed in /etc/init/uwsgi.conf

description "uWSGI Emperor"

start on runlevel [2345]
stop on runlevel [06]
respawn
exec uwsgi --emperor /etc/uwsgi/vassals/ --master --logto /var/log/uwsgi/emperor.log

Create the directories

mkdir /etc/uwsgi/vassals/

Then either reboot your system or:

sudo initctl start uwsgi
sudo initctl reload-configuration

To check if its started
initctl list

Check the system log file or the emperor.log if uwsgi is not started

30 May

Install Python on Linux (Centos)

Most installed python on Linux systems are outdated. While python 2.6 is quite good for a project, most are advised to use python 2.7 or 3.4, so the need to upgrade it.

However, for Centos 6, you are strongly advised to avoid upgrading or reinstalling the stock version as some important system programs (notable yum), uses it.
Removing the default version will break the dependent system programs, instead you should install your targeted version and make sure your files are linked to it.

Install Python 2.7

Run the following command to update the system applications:
$ sudo yum -y update

In order to get the necessary development tools, run the following:
$ sudo yum groupinstall -y development

# sudo yum install -y zlib-dev openssl-devel sqlite-devel bzip2-devel

Download, compile and install Python:

$ cd /opt
$ sudo wget --no-check-certificate https://www.python.org/ftp/python/2.7.X/Python-2.7.X.tar.xz
$ sudo tar xf Python-2.7.X.tar.xz
$ sudo cd Python-2.7.X
$ sudo ./configure --prefix=/usr/local
$ sudo make && make altinstall

List all python programs

$ ls -ltr /usr/bin/python*
$ ls -ltr /usr/local/bin/python*

Link Python 2.7 to the default python on local environment

$ ln -s /usr/local/bin/python2.7 /usr/local/bin/python

Install easy tools and pip

$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
$ sudo /usr/local/bin/python2.7 ez_setup.py
$ sudo /usr/local/bin/easy_install-2.7 pip

Install virtualenv
$ pip2.7 install virtualenv

 

02 Nov

Git adventures

I wanted to clean up some Bootstrap files from a project directory. After the cleanup. I pushed the changes to the remote repo (BitBucket).
However, I noticed that the files that should be deleted (and was deleted on local repo), was still existing on the remote repo.
After some head scratching, i released that the problem was that I used the file system delete, instead of the git delete.

$ git rm 
$ git add .
$ git commit -m "changes"
$ git push

Everything was fine now and good, until I come back to see that i deleted an important directory due to a misuse of the “*” during the delete.
Well, that what and DSCM was meant for.. Git come to the rescue…. except that it took me 30mins or trying different command ( and help from Stackoverflow) to find the right combo, thus:

cf361cb is the last commit with the missing directory

$ git revert --no-commit cf361cb..HEAD
$ git commit

This is a safe and easy way to rollback to a previous state. Checks for the missing directory

$ ls -ltr
$ cd static/

Cleanup files

$ git rm *.css
$ git rm *.js

Then commit and push

$ git add .
$ git status
$ 1398 git commit -m "UI file cleanup"
$ git push

And Wossah!!
The git throws up a new error, “fatal: You are not currently on a branch”
I checked on the git

$ git status

And trully, you are not a branch!
I was getting loosing the modification twice after using 2 different command, until i hit on the right combo (also good help from stackoverflow)

$ git checkout -b newbranch
$ git checkout master
$ git merge newbranch
$ git branch -d newbranch
$ git status
$ git push

Hurray!!

02 Oct

python+virtualenv on Cygwin

I have been trying to make my default environment for development to be

  1. Install Python.
  2. Download and unzip pip.
  3. Install by going into the expanded directory and running python setup.py in a command prompt.
  4. Set the %PYTHONHOME% system variable to the python base directory, (i.e. C:\Python27\) and adding the python base directory and script directory (i.e. C:\Python27\Scripts) to your %PATH% system variable.
  5. Install Cygwin WITHOUT Python. The previous step tells Cygwin to use the Windows binary.
  6. Install Cygwin-Virtualenvwrapper using pip install https://bitbucket.org/cliffxuan/virtualenvwrapper-for-cygwin-windows-python/get/tip.tar.gz
  7. Install virtualenvwrapper-win using pip install virtualenvwrapper-win
  8. Make a symlink between Cygwin’s virtualenvhome directory and Windows’s using ln -s /cygdrive/c/Users/<USER>/Envs/ ~/.virtualenvs
  9. Add the following to Cygwin’s .bashrc file:
      export VIRTUALENVWRAPPER_PYTHON=”/cygdrive/c/Python27/python.exe”
      export VIRTUALENVWRAPPER_VIRTUALENV=”/cygdrive/c/Python27/Scripts/virtualenv.exe”
      source virtualenvwrapper.sh
  10. Go to C:\User\<username>\Env (or other %VIRTUALENV_HOME% location) and use virtualenv to start a new environment. Doing this allows virtualenvwrapper-win‘s workon command to work.
30 Nov

Deploying Flask on lighttpd

Deploying Flask seems a lonely taks, becuase of dearth of articles or blogs that explain in. This is even worse when deploying on a shared server.
Most people seems to treat a python deployment as a django deployment. Since, there are cheap and available Flask hsting site, i went with Django host, but confirmed that we can host any other framework.

The good thing is that, there too many similarities, and most packages are already installed on the host.

1. Open putty and log into the hosts server (s17.wservices.ch)
2. Check that the following following packages are installed

python and python-devel: the Python interpreter and its development package
lighttpd: The Lighty web server and its development package
install postgresql postgresql-contrib: The PostgreSQL database server and its development package
git: source code version control system (we will use it to download and update the application)
gcc: the C/C++ compiler (needed to compile Python extensions)
sudo: a tool that helps users run commands as other users.

If not, install them.

sudo apt-get python python-devel lighttpd httpd-devel mysql-server mysql-devel git gcc

3. Configure passwordless login (if needed)
4. Create a directory for the application, and install the application from BitBucket
mkdir app
cd app
git clone git://bitbucket.org/peppe/peppe-ng.git

5. Check User permissions
chmod -R 777 *

6. Setup the database
Go to https://panel.djangoeurope.com/databases/
Login with a username and password, and then create a database and dump the content of the dev db
pg_dump peppedb > ppdbdump.sql

Transfer the file to live host
sftp outfile.sql peppe@s17.wservices.ch

Load the Db on the live host
psql peppedb < ppdbdump.sql

7. Setup the webserver
Paste at the end of this file ~/lighttpd/lighttpd.conf

#Peppe.com
$HTTP[“host”] =~ “(^|.)peppe.com.ng$” {
fastcgi.server = (
“/flask.fcgi” => (
“main” => (
“socket” => env.HOME + “/mysite_project/mysite.sock”,
“check-local” => “disable”,
)
),
)
alias.url = (
“/media” => env.HOME + “/mysite_project/media”,
)

url.rewrite-once = (
“^(/media.*)$” => “$1”,
“^/favicon.ico$” => “/media/favicon.ico”,
“^(/.*)$” => “/flask.fcgi$1”,
)
}

Replace mydomain.com with the name of your domain. Be sure to escape all dots of your website’s name (put a backslash before it: .). Replace your_django_project/media with the path of you media directory (relative to your home directory). Replace mysite_project/mysite.sock with the path to your fastcgi socket file

Now you can launch your lighttpd:

~/init/lighttpd start

Whenever you make changes to the configuration, you can reload the configuration or restart lighttpd:

~/init/lighttpd reload

~/init/lighttpd restart

9. Configure the db and start
10. Install application updates