I assume that you are going to work with:
- Ubuntu
- Django
- Redis
- Iptables
- Fail2ban
- Postgres
- Git-Auto-Deploy
- Nginx & Uwsgi
Server Initial Setup
Create Users:
adduser USER1
adduser USER2
Grant root privileges:
visudo
Put this line:
USER1 ALL=(ALL:ALL) ALL
USER2 ALL=(ALL:ALL) ALL
Disable root login:
nano /etc/ssh/sshd_config
Change the line to:
PermitRootLogin no
Change SSH port:
nano /etc/ssh/sshd_config
Find this line:
Port 22
Change 22 to some custom port and then restart the service:
service ssh restart
Test everything:
ssh [email protected] -p PORTNUMBER
sudo su
Table of Contents
Django and Python Installation & Configuration
Upgrade server:
apt-get update
apt-get upgrade
Install required tools:
apt-get install git htop unzip
Install required python and DB packages:
apt-get install python3 python3-pip python-setuptools python3-setuptools python3-dev build-essential
apt-get install postgresql postgresql-contrib python-psycopg2 libpq-dev
Link pip to pip3:
ln -s /usr/bin/pip3 /usr/bin/pip
pip install --upgrade pip
Add ssh-keys and clone repository
Create key for git-auto-deploy service. Then add it to your gitlab project (not your account).
ssh-keygen -t rsa
cat /etc/git-auto-deploy/.ssh/id_rsa.pub
Clone:
git clone [email protected]:ACCOUNT/REPOSITORY
Install Django and it's packages
Install django and it’s packages:
pip3 install django
pip3 install -r requirements.txt
Configure django after installation by opening this file:
nano /usr/local/lib/python3.5/dist-packages/actstream/urls.py
For some reason remove three “patterns” occurrence in this file.
Update settings in django settings.py:
nano /home/www/PROJECT/PROJECT/settings.py
Specifically these sections:
'USER': 'DBUSER',
'PASSWORD': 'DBPASSWORD',
'HOST': 'HOSTNAME',
'PORT': '5432',
HOST_URL = 'http://YOURWEBSITE/'
Database
Open postgres console:
su - postgres
createuser DBUSER
createdb DBNAME
psql
\password DBPASSWORD
GRANT ALL PRIVILEGES ON DATABASE DBNAME TO DBUSER;
\q
Migration
rm -rf Core/migrations/ APP1/migrations/ APP2/migrations/
python3 manage.py makemigrations app1
python3 manage.py makemigrations app2
python3 manage.py makemigrations
python3 manage.py migrate
Create superuser:
python3 manage.py createsuperuser
python3 manage.py collectstatic
WSGI
sudo pip3 install uwsgi
Test
Run and Test Django:
python3 manage.py runserver 0.0.0.0:80
Run and Test uwsgi:
uwsgi --http :80 --chdir /home/www/PROJECT/ -w PROJECT.wsgi
WSGI Configuration
mkdir /etc/uwsgi/
mkdir /etc/uwsgi/sites
nano /etc/uwsgi/sites/PROJECT.ini
Put this configuration:
[uwsgi]
project = PROJECT
uid = SYSTEMUSER
base = /home/%(uid)
chdir = %(base)/%(project)
module = %(project).wsgi:application
master = true
processes = 5
socket = /run/uwsgi/%(project).sock
chown-socket = %(uid):www-data
chmod-socket = 660
vacuum = true
WSGI on systemd
nano /etc/systemd/system/uwsgi.service
Put this configuration in place:
[Unit]
Description=uWSGI Emperor service
[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown USER:www-data /run/uwsgi'
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all
[Install]
WantedBy=multi-user.target
Web Server
Install web server:
sudo apt-get install nginx
Config virtualhost:
nano /etc/nginx/sites-available/PROJECT
Put this configuration in place:
server {
listen 80;
server_name HOSTNAME;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/www/PROJECT/Core;
}
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/PROJECT.sock;
}
}
Enable your virtualhost:
ln -s /etc/nginx/sites-available/PROJECT /etc/nginx/sites-enabled
Test nginx configuration files:
nginx -t
IPtables
Open necessary ports:
iptables -A INPUT -i ens3 -p tcp --dport 2233 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i ens3 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i ens3 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -I INPUT 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Change default behavior of the specific chains to drop all connections:
iptables -P INPUT DROP
iptables -P FORWARD DROP
To make iptable rules persistent install iptables-persistent:
apt-get install iptables-persistent
invoke-rc.d netfilter-persistent save
You are already done.
Use this command to update iptable rules. Note that if you run iptable-save it saves all fail2ban rules and fail2ban add all these rules on boot and it make your iptable a mess.
iptables-save
List IPtable Rules:
iptables --list
iptables -S
iptables -L --line-numbers
Delete specific rule:
iptables -D FORWARD rule_number
Change default behavior of the specific chains to accept all connections:
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
This drop connections by a separate rule not the default policy:
iptables -I INPUT -j DROP
Fail2ban
Install the service:
apt-get install fail2ban
Follow how to protect ssh with fail2ban on ubuntu 14.04 to protect ssh.
Follow how to protect an nginx server with fail2ban on ubuntu 14.04 to protect nginx.
Redis
Install Redis. After installation of Redis:
pip3 install django-redis
Start uwsgi and nginx services:
sudo systemctl restart nginx
sudo systemctl start uwsgi
service redis_6379 stop
service redis_6379 start
redis-cli
Deploy on Push Service
Install git-auto-deploy program:
add-apt-repository ppa:olipo186/git-auto-deploy
apt-get update
apt-get install git-auto-deploy
Working with service:
/etc/init.d/git-auto-deploy start/stop/status
If it does’nt started see service log:
tail -f /var/log/git-auto-deploy.log
This service listen on 8001 port number by default. If you want to check if it’s started correctly and is listening on this port use telnet:
telnet localhost 8001
If you have telnet on your machine check it from another network.
Change the owner of your project files to it’s created user:
chown -R git-auto-deploy:git-auto-deploy /var/www
Config git-auto-deploy repositories:
nano /etc/git-auto-deploy.conf.json
Add repositories informations:
{
"url": "[email protected]:YOURGITLABACCOUNT/REPO1.git",
"branch": "master",
"remote": "origin",
"path": "/home/www/PROJECT/",
"deploy": "echo deploying"
},
{
"url": "[email protected]:YOURGITLABACCOUNT/REPO2.git",
"branch": "master",
"remote": "origin",
"path": "/home/www/PROJECT/",
"deploy": "echo deploying"
},
Restart the service:
sudo service git-auto-deploy restart
Go to repositories web hook section (1,2) and add hooks information:
URL: http://YOURSERVERIPADDRESS:8001
Enable SSL verification? Disabled
Push events? ✓
Use gitlab built-in test to see if your hook works properly.
Fix permissions for git-auto-deploy service:
chown -R git-auto-deploy:git-auto-deploy /etc/git-auto-deploy
cd path/to/project/dir
chown -R git-auto-deploy:www-data *
chown -R git-auto-deploy:www-data .git/
chown -R git-auto-deploy:www-data .gitignore/
Read how to set up automatic deployment with git with a vps and how to use git hooks to automate development and deployment tasks for more information.
Configure Https
Copy certificates:
cp PROJECT.crt PROJECT.key /etc/ssl/
Open the virtualhost file:
/etc/nginx/sites-available/PROJECT
Find this block:
server {
listen 80;
server_name HOSTNAME;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/www/PROJECT;
}
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/PROJECT.sock;
}
}
Edit it like this:
server {
server_name HOSTNAME;
listen 80;
return 301 https://HOSTNAME$request_uri;
}
server {
listen 443;
server_name HOSTNAME;
ssl on;
ssl_certificate /etc/ssl/PROJECT.crt;
ssl_certificate_key /etc/ssl/PROJECT.key;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/www/PROJECT;
}
location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/ibmn.sock;
proxy_set_header X-Forwarded-Proto https;
}
}
Restart nginx:
service nginx restart
Add following lines to django settings.py:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True