update README

This commit is contained in:
ducoterra
2018-09-16 22:29:26 -04:00
parent 3d2c761aa4
commit 4e96fac5c6
4 changed files with 201 additions and 133 deletions

179
README.md
View File

@@ -1,9 +1,23 @@
# Django Setup for CentOS 7 # Django Setup for CentOS 7
## Quick Install ## Quick Install
```bash
vim vars
```
```bash
# django project settings
export user="centos" <-- change to your user
export projectname="mysite"
export hostname="centos.duco.net" <-- change to your hostname
export letsencrypt=False
```
```bash ```bash
source vars source vars
./install.sh ./install.sh
``` ```
Done!
## A more detailed explanation ## A more detailed explanation
### vars ### vars
```bash ```bash
@@ -39,7 +53,7 @@ The Django Project Settings variables should be changed to match your configurat
2. user = "nginx" 2. user = "nginx"
3. user = "[other user]" 3. user = "[other user]"
My recommendation is to use nginx as the user. The installer takes care of creating a home directory for nginx and setting permissions. Of course there is no problem with specifying another user. You could "adduser django" and set django as the user. The installer will automatically assign permissions as needed. Setting the user to the primary sudo account is risky but the installer won't complain if you do it quietly. My recommendation is to use nginx as the user. The installer takes care of creating a home directory for nginx and setting permissions. Of course there is no problem with specifying another user. The installer will automatically add a user and assign permissions. Setting the user to the primary sudo account is risky but the installer won't complain if you do it quietly.
The projectname variable can be whatever you want. When django starts the project it will use this name. The projectname variable can be whatever you want. When django starts the project it will use this name.
@@ -49,7 +63,7 @@ The hostname will be inserted into "ALLOWED_HOSTS" in your app settings. Multipl
If you are installing this on a system with the minimal CentOS build you'll need install_epel_release to be True. ```epel_release``` installs nginx. Kinda hard to run the site without that. If you are installing this on a system with the minimal CentOS build you'll need install_epel_release to be True. ```epel_release``` installs nginx. Kinda hard to run the site without that.
## install.sh ## install
### Dependencies ### Dependencies
In order for this script to work its magic you'll need a few packages provided by Yum. This part is likely to break due to Yum's inconsistency accross distributions, firewall and proxy configurations, and whether CentOS had its morning coffee. In order for this script to work its magic you'll need a few packages provided by Yum. This part is likely to break due to Yum's inconsistency accross distributions, firewall and proxy configurations, and whether CentOS had its morning coffee.
@@ -73,20 +87,25 @@ if [ $install_epel_release = True ] ; then
fi fi
``` ```
The first part of the script is fairly straight forward. If you aren't root, the installer can't use yum and won't work. It then creates the necessary directories to prevent future complaints and installs the aforementioned epel-release package if you want it. The first part of the script is fairly straight forward. If you aren't root, the installer can't use yum and won't work. After checking if you are the root user it creates the necessary directories to prevent future complaints and installs the aforementioned epel-release package if you want it.
```bash ```bash
# install dependencies # install dependencies
echo -e "\tInstalling gcc" packages=(gcc wget nginx libsqlite3x-devel.x86_64 postgresql-server postgresql-devel postgresql-contrib bzip2-devel zlib-devel libffi-devel openssl-devel policycoreutils-python.x86_64)
yum -y install gcc 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc for package in ${packages[@]};
if [ $? -ne 0 ] ; then do
echo -e "yum failed to install gcc. $yumlogmsg" echo -e "\tInstalling $package"
exit 1 yum -y install $package 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
fi if [ $? -ne 0 ] ; then
echo -e "yum failed to install $package. $yumlogmsg"
exit 1
fi
done
``` ```
The next part of the script installs yum dependencies. Each install will check if it was successful and stop everything it it wasn't. The next part of the script installs yum dependencies. The script verifies that the installation goes smoothly and exits if an error occurs.
### Firewall
```bash ```bash
# set firewall # set firewall
echo -e "firewall-cmd --zone=public --add-port=80/tcp --permanent" > $firelogloc echo -e "firewall-cmd --zone=public --add-port=80/tcp --permanent" > $firelogloc
@@ -117,8 +136,9 @@ fi
The firewall commands are specific to a CentOS 7 minimal install. You may not need them. The installer doesn't really care if they fail because they aren't mission critical. It'll yell at you and that's about it. The firewall commands are specific to a CentOS 7 minimal install. You may not need them. The installer doesn't really care if they fail because they aren't mission critical. It'll yell at you and that's about it.
The semanage command fixes an issue where the websocket would be inaccessible after an install causing 502 errors and loud swearing. The semanage command fixes an issue where the websocket would be inaccessible after an install.
### Python
```bash ```bash
wget $pylink 1> $pylogloc 2>> $pylogloc wget $pylink 1> $pylogloc 2>> $pylogloc
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
@@ -149,30 +169,131 @@ if [ $? -ne 0 ] ; then
fi fi
``` ```
If you've ever installed Python from source this part should look familiar. Right now it grabs the latest version of Python 3.7 and installs it to /usr/src/python37/. It uses alt install to prevent conflict with previous versions of python (I've been told CentOS will break if it can't find python 2, a real problem if you use make install). If you've ever installed Python from source this part should look familiar. The script uses wget to download the version of python provided by ```$pylink```. It uses alt install to prevent conflict with previous versions of python (I've been told CentOS will break if it can't find python 2, a real problem if you use make install).
You could get rid of this section and do it yourself with another version of python. As long as python can be found at /usr/src/python37 and it has django support the installer will continue to chug along happily. You could get rid of this section and do it yourself with another version of python. As long as python can be found at ```$pyinstalldir``` and it has django support the installer will continue to chug along happily.
The script will automatically update pip and install virtualenv.
### Django
```bash ```bash
echo "Starting Django project..." id -u $user > /dev/null
if [ $? = 0 ]; then
adduser $user
fi
if [ ! -d "/home/$user" ] ; then if [ ! -d "/home/$user" ] ; then
mkdir /home/$user mkdir /home/$user
chown -R $user:$user /home/$user chown -R $user:$user /home/$user
fi fi
mkdir /home/$user/$projectname mkdir /home/$user/$projectname
cd /home/$user/ if [ $? -ne 0 ] ; then
/usr/src/python37/bin/python3.7 -m virtualenv $projectname/venv >> $djalog echo -e "Failed to create $projectname directory. $djamsg"
source $projectname/venv/bin/activate >> $djalog exit 1
pip install django gunicorn psycopg2-binary >> $djalog fi
cd $projectname
django-admin startproject $projectname >> $djalog
cd /home/$user/
sed -i "s/ALLOWED_HOSTS = \[\]/ALLOWED_HOSTS = \[\"$hostname\"\]/" $projectname/$projectname/$projectname/settings.py
echo "STATIC_ROOT = os.path.join(BASE_DIR, 'static')" >> $projectname/$projectname/$projectname/settings.py
python $projectname/$projectname/manage.py collectstatic
python $projectname/$projectname/manage.py makemigrations
python $projectname/$projectname/manage.py migrate
deactivate
chown -R $user:$user $projectname
cd /root/
``` ```
Installing Django starts by checking if the user you provided exists. If it doesn't then it adds the user and creates a home directory. It then creates the project directory using the provided project name.
```bash
echo -e "\tCreating venv"
cd /home/$user/
/usr/src/python37/bin/python3.7 -m virtualenv $projectname/venv 1>> $djalogloc 2>> $djalogloc
if [ $? -ne 0 ] ; then
echo -e "Failed to create virtual environment. $djamsg"
exit 1
fi
source $projectname/venv/bin/activate >> $djalogloc
if [ $? -ne 0 ] ; then
echo -e "Failed to source virtual environment. $djamsg"
exit 1
fi
```
The next part of the script creates a virtual environment based on your python install.
```bash
# pip installs
pips=(django gunicorn psycopg2-binary)
for pip in ${pips[@]};
do
echo -e "\tInstalling $pip"
pip install $pip >> $djalogloc
if [ $? -ne 0 ] ; then
echo -e "Failed to install $pip. $djamsg"
exit 1
fi
done
```
The script then installs the necessary pip packages.
```bash
# start django project
echo -e "\tStarting django project"
cd $projectname
django-admin startproject $projectname >> $djalogloc
if [ $? -ne 0 ] ; then
echo -e "Failed to start project $projectname with django-admin. $djamsg"
exit 1
fi
```
Next the script starts the django project. You'll notice that the project structure looks like this:
```
[projectname]/
├── [projectname]/
│ ├── [projectname]/
│ │ ├── __init__.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ └── manage.py
└── venv/
```
When making changes to nginx or gunicorn it's important to keep this structure in mind. There are 3 folders called ```$projectname```.
After this, the script updates allowed hosts, collects static, and makes migrations.
### Gunicorn
```bash
echo -e "
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=$user
Group=nginx
WorkingDirectory=/home/$user/$projectname/$projectname
ExecStart=/home/$user/$projectname/venv/bin/gunicorn --workers 3 --bind unix:/home/$user/$projectname/$projectname.sock $projectname.wsgi:application
[Install]
WantedBy=multi-user.target" > /etc/systemd/system/gunicorn.service
```
The gunicorn and nginx installs are very similar. The gunicorn "install" is just a .service file that gets placed in ```/etc/systemd/system/```. As seen above, the install command just echoes the service file into the right place.
### Nginx
```bash
echo -e "
server {
listen 80;
server_name $hostname;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/$user/$projectname/$projectname;
}
location / {
proxy_set_header Host \$http_host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_pass http://unix:/home/$user/$projectname/$projectname.sock;
}
}" > /etc/nginx/conf.d/$projectname.conf
```
The nginx install copies a configuration file to the nginx configuration directory. The only complication here is:
```bash
if [ ! $user = "nginx" ] ; then
sed -i "s/user nginx/user $user nginx/" /etc/nginx/nginx.conf
fi
```
Which inserts the specified user (if not nginx) into nginx.conf.

View File

@@ -22,91 +22,27 @@ if [ $install_epel_release=True ] ; then
fi fi
# install dependencies # install dependencies
echo -e "\tInstalling gcc" packages=(gcc wget nginx libsqlite3x-devel.x86_64 postgresql-server postgresql-devel postgresql-contrib bzip2-devel zlib-devel libffi-devel openssl-devel policycoreutils-python.x86_64)
yum -y install gcc 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc for package in ${packages[@]};
if [ $? -ne 0 ] ; then do
echo -e "yum failed to install gcc. $yumlogmsg" echo -e "\tInstalling $package"
exit 1 yum -y install $package 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
fi if [ $? -ne 0 ] ; then
echo -e "\tInstalling wget" echo -e "yum failed to install $package. $yumlogmsg"
yum -y install wget 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc exit 1
if [ $? -ne 0 ] ; then fi
echo -e "yum failed to install a wget. $yumlogmsg" done
exit 1
fi
echo -e "\tInstalling nginx"
yum -y install nginx 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install nginx. $yumlogmsg"
exit 1
fi
echo -e "\tInstalling libsqlite3x-devel.x86_64"
yum -y install libsqlite3x-devel.x86_64 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install libsqlite3x-devel.x86_64 . $yumlogmsg"
exit 1
fi
echo -e "\tInstalling postgresql-server"
yum -y install postgresql-server 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install postgresql-server. $yumlogmsg"
exit 1
fi
echo -e "\tInstalling postgresql-devel"
yum -y install postgresql-devel 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install postgresql-devel. $yumlogmsg"
exit 1
fi
echo -e "\tInstalling postgresql-contrib"
yum -y install postgresql-contrib 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install postgresql-contrib. $yumlogmsg"
exit 1
fi
echo -e "\tInstalling bzip2-devel"
yum -y install bzip2-devel 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install bzip2-devel. $yumlogmsg"
exit 1
fi
echo -e "\tInstalling zlib-devel"
yum -y install zlib-devel 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install zlib-devel. $yumlogmsg"
exit 1
fi
echo -e "\tInstalling ibffi-devel"
yum -y install libffi-devel 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install libffi-devel. $yumlogmsg"
exit 1
fi
echo -e "\tInstalling openssl-devel"
yum -y install openssl-devel 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install openssl-devel. $yumlogmsg"
exit 1
fi
echo -e "\tInstalling policycoreutils-python.x86_64"
yum -y install policycoreutils-python.x86_64 1>> $yumlogloc 2>> $yumlogloc 3>> $yumlogloc
if [ $? -ne 0 ] ; then
echo -e "yum failed to install policycoreutils-python.x86_64. $yumlogmsg"
exit 1
fi
# set firewall # set firewall
echo -e "firewall-cmd --zone=public --add-port=80/tcp --permanent" > $firelogloc ports=(80 443)
firewall-cmd --zone=public --add-port=80/tcp --permanent 1>> $firelogloc 2>> $firelogloc for port in ${ports[@]};
if [ $? -ne 0 ] ; then do
echo -e "\tfirewall failed to update port 80 correctly (this may not be an issue). $firelogmsg" echo -e "firewall-cmd --zone=public --add-port=$port/tcp --permanent" > $firelogloc
fi firewall-cmd --zone=public --add-port=$port/tcp --permanent 1>> $firelogloc 2>> $firelogloc
if [ $? -ne 0 ] ; then
echo -e "firewall-cmd --zone=public --add-port=443/tcp --permanent" >> $firelogloc echo -e "\tfirewall failed to update port $port correctly (this may not be an issue). $firelogmsg"
firewall-cmd --zone=public --add-port=443/tcp --permanent 1>> $firelogloc 2>> $firelogloc fi
if [ $? -ne 0 ] ; then done
echo -e "\tfirewall failed to update port 443 correctly, (this may not be an issue). $firelogmsg"
fi
echo -e "firewall-cmd --reload" >> $firelogloc echo -e "firewall-cmd --reload" >> $firelogloc
firewall-cmd --reload 1>> $firelogloc 2>> $firelogloc firewall-cmd --reload 1>> $firelogloc 2>> $firelogloc
@@ -128,6 +64,8 @@ fi
tput setaf 2 tput setaf 2
echo -e "Installing Python" echo -e "Installing Python"
tput setaf 0 tput setaf 0
# fetch Python
wget $pylink 1> $pylogloc 2>> $pylogloc wget $pylink 1> $pylogloc 2>> $pylogloc
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo -e "Failed to fetch python, make sure wget is installed and $pylink is what you're after. $pylogmsg" echo -e "Failed to fetch python, make sure wget is installed and $pylink is what you're after. $pylogmsg"
@@ -143,8 +81,10 @@ if [ $? -ne 0 ] ; then
echo -e "Missing python directory. $pylogmsg" echo -e "Missing python directory. $pylogmsg"
exit 1 exit 1
fi fi
# install Python
echo -e "\tConfigure" echo -e "\tConfigure"
./configure --prefix /usr/src/python37 1>> $pylogloc 2>> $pylogloc ./configure --prefix $pyinstalldir 1>> $pylogloc 2>> $pylogloc
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
echo -e "./configure failed. $pylogmsg" echo -e "./configure failed. $pylogmsg"
exit 1 exit 1
@@ -161,6 +101,8 @@ if [ $? -ne 0 ] ; then
echo -e "make altinstall failed. $pylogmsg" echo -e "make altinstall failed. $pylogmsg"
exit 1 exit 1
fi fi
# upgrade pip and install virtualenv
echo -e "\tUpgrading pip" echo -e "\tUpgrading pip"
/usr/src/python37/bin/python3.7 -m pip install --upgrade pip 1>> $pylogloc 2>> $pylogloc /usr/src/python37/bin/python3.7 -m pip install --upgrade pip 1>> $pylogloc 2>> $pylogloc
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
@@ -186,7 +128,9 @@ fi
tput setaf 2 tput setaf 2
echo -e "Starting Django project" echo -e "Starting Django project"
tput setaf 0 tput setaf 0
echo id -u $user
# check user and create dirs
id -u $user > /dev/null
if [ $? = 0 ]; then if [ $? = 0 ]; then
adduser $user adduser $user
fi fi
@@ -199,6 +143,8 @@ if [ $? -ne 0 ] ; then
echo -e "Failed to create $projectname directory. $djamsg" echo -e "Failed to create $projectname directory. $djamsg"
exit 1 exit 1
fi fi
# virtual environment
echo -e "\tCreating venv" echo -e "\tCreating venv"
cd /home/$user/ cd /home/$user/
/usr/src/python37/bin/python3.7 -m virtualenv $projectname/venv 1>> $djalogloc 2>> $djalogloc /usr/src/python37/bin/python3.7 -m virtualenv $projectname/venv 1>> $djalogloc 2>> $djalogloc
@@ -211,24 +157,20 @@ if [ $? -ne 0 ] ; then
echo -e "Failed to source virtual environment. $djamsg" echo -e "Failed to source virtual environment. $djamsg"
exit 1 exit 1
fi fi
echo -e "\tInstalling django"
pip install django >> $djalogloc # pip installs
if [ $? -ne 0 ] ; then pips=(django gunicorn psycopg2-binary)
echo -e "Failed to install pip dependencies. $djamsg" for pip in ${pips[@]};
exit 1 do
fi echo -e "\tInstalling $pip"
echo -e "\tInstalling gunicorn" pip install $pip >> $djalogloc
pip install gunicorn >> $djalogloc if [ $? -ne 0 ] ; then
if [ $? -ne 0 ] ; then echo -e "Failed to install $pip. $djamsg"
echo -e "Failed to install pip dependencies. $djamsg" exit 1
exit 1 fi
fi done
echo -e "\tInstalling psycopg2-binary"
pip install psycopg2-binary >> $djalogloc # start django project
if [ $? -ne 0 ] ; then
echo -e "Failed to install pip dependencies. $djamsg"
exit 1
fi
echo -e "\tStarting django project" echo -e "\tStarting django project"
cd $projectname cd $projectname
django-admin startproject $projectname >> $djalogloc django-admin startproject $projectname >> $djalogloc
@@ -236,6 +178,8 @@ if [ $? -ne 0 ] ; then
echo -e "Failed to start project $projectname with django-admin. $djamsg" echo -e "Failed to start project $projectname with django-admin. $djamsg"
exit 1 exit 1
fi fi
# update allowed hosts
cd /home/$user/ cd /home/$user/
echo -e "echo -e sed -i 's/ALLOWED_HOSTS = []/ALLOWED_HOSTS = [\"$hostname\"]/' $projectname/$projectname/$projectname/settings.py" >> $djalogloc echo -e "echo -e sed -i 's/ALLOWED_HOSTS = []/ALLOWED_HOSTS = [\"$hostname\"]/' $projectname/$projectname/$projectname/settings.py" >> $djalogloc
sed -i "s/ALLOWED_HOSTS = \[\]/ALLOWED_HOSTS = \[\"$hostname\"\]/" $projectname/$projectname/$projectname/settings.py sed -i "s/ALLOWED_HOSTS = \[\]/ALLOWED_HOSTS = \[\"$hostname\"\]/" $projectname/$projectname/$projectname/settings.py
@@ -249,6 +193,8 @@ if [ $? -ne 0 ] ; then
echo -e "Failed to append STATIC_ROOT. $djamsg" echo -e "Failed to append STATIC_ROOT. $djamsg"
exit 1 exit 1
fi fi
# collect static, migrate
echo -e "\tCollecting static" echo -e "\tCollecting static"
python $projectname/$projectname/manage.py collectstatic >> $djalogloc python $projectname/$projectname/manage.py collectstatic >> $djalogloc
if [ $? -ne 0 ] ; then if [ $? -ne 0 ] ; then
@@ -328,7 +274,7 @@ server {
proxy_set_header X-Forwarded-Proto \$scheme; proxy_set_header X-Forwarded-Proto \$scheme;
proxy_pass http://unix:/home/$user/$projectname/$projectname.sock; proxy_pass http://unix:/home/$user/$projectname/$projectname.sock;
} }
}" > /etc/nginx/conf.d/mysite.conf }" > /etc/nginx/conf.d/$projectname.conf
# set the nginx user # set the nginx user
if [ ! $user = "nginx" ] ; then if [ ! $user = "nginx" ] ; then
sed -i "s/user nginx/user $user nginx/" /etc/nginx/nginx.conf sed -i "s/user nginx/user $user nginx/" /etc/nginx/nginx.conf

1
vars
View File

@@ -22,3 +22,4 @@ export nginxlogloc=$logdir"nginx.log"
# python settings # python settings
export pylink="https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz" export pylink="https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz"
export pyinstalldir="/usr/src/python37"