Nginx and Apache are two popular PHP web servers. Running both of them with Nginx in front of apache (Nginx reverse proxy) will improve performance significantly. This tutorial will show you how to configure your Ubuntu server for Yii2 framework environments.
Prerequisites
- Ubuntu Server 16.04 LTS "xenial"
- Root account
Step 1 - Update your OS and install basic program
apt-get update
apt-get upgrade
apt-get install unzip
add-apt-repository -y ppa:ondrej/php
apt-add-repository ppa:ondrej/apache2
add-apt-repository ppa:nginx/stable
Step 2 - Install Apache and PHP
apt-get install apache2 libapache2-mod-fastcgi php7.1-fpm
Step 3 - Install Apache modules
Install mod_aclr2
apt-get install apache2-dev gcc
wget http://files.directadmin.com/services/custombuild/mod_aclr2-1.0.0.tar.gz
tar -xzvf mod_aclr2-1.0.0.tar.gz
apxs -c mod_aclr2.c
apxs -i -a -n aclr mod_aclr2.la
Install mod_rpaf
wget https://github.com/gnif/mod_rpaf/archive/stable.zip
unzip stable.zip
cd mod_rpaf-stable
make
make install
Step 4 - Install PHP modules (for Yii2)
apt-get install -y php-intl php-xml php-mysql php-gd php-zip php-mcrypt php-gmp php-imagick
apt-get install -y php-mbstring
apt-get install -y php-mongodb
apt-get install -y libssh2-1 php-ssh2
Step 5 - Config Apache
Create mod_aclr.conf
configuration file
nano /etc/apache2/mods-available/aclr.conf
Add the following lines
AccelRedirectSet On
AccelRedirectSize 1k
Create rpaf.load
file for loading the module
nano /etc/apache2/mods-available/rpaf.load
Then add the following line
LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.so
Create rpaf.conf
configuration file
nano /etc/apache2/mods-available/rpaf.conf
Add the following code block, replace SERVER_IP with your server public/private IP
<IfModule mod_rpaf.c>
RPAF_Enable On
RPAF_Header X-Real-Ip
RPAF_ProxyIPs SERVER_IP
RPAF_SetHostName On
RPAF_SetHTTPS On
RPAF_SetPort On
</IfModule>
Enable Apache's modules
a2enmod aclr
a2enmod rpaf
a2enmod rewrite
a2enmod headers
a2enmod ssl
a2enmod proxy
a2enmod proxy_fcgi
a2enmod actions
a2enmod proxy_fcgi setenvif
a2enconf php7.1-fpm
Step 6 - Changing Apache ports
nano /etc/apache2/ports.conf
Change Listen 80
to Listen 8080
and Listen 443
to Listen 8081
nano /etc/apache2/sites-available/000-default.conf
Change <VirtualHost *:80>
to <VirtualHost *:8080>
nano /etc/apache2/sites-available/default-ssl.conf
Change <VirtualHost _default_:443>
to <VirtualHost _default_:8081>
Open /etc/apache2/apache2.conf
, add the following code block right under <Directory /var/www/>
code block
<Directory /home/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Finally enable the default ssl site and reload Apache
a2ensite default-ssl
service apache2 reload
Visit http://SERVER_IP:8080 and https://SERVER_IP:8081 to test it.
Step 7 - Install Nginx
apt-get install nginx
Step 8 - Config Nginx
nano /etc/nginx/sites-available/default
Delete all content of the file.
We will redirect all HTTP requets to HTTPS, add the code block below
server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$host$request_uri;
}
Next, add the code block for HTTPS
server {
listen 443 default_server http2;
listen [::]:443 default_server http2;
ssl on;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
location / {
proxy_pass https://{IP}:8081;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Accel-Internal /nginx_static_files;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /nginx_static_files/ {
alias /var/www/html/;
internal;
}
location ~ /(\.ht|\.user\.ini) {
deny all;
}
}
Remove nginx version in the response header field.
nano /etc/nginx/nginx.conf
Uncomment server_tokens off;
Reload everything
service nginx reload
service apache2 reload
service php7.0-fpm reload
Visit http://SERVER_IP and https://SERVER_IP to test it, then you can block ports 8080 and 8081 using firewall.
Restore original visitor IP from Cloudflare: create new file in /etc/nginx/conf.d/cloudflare.conf
with the following lines
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;
# use any of the following two
real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;
Step 9 - Install database
We use MariaDB instead of MySQL
apt-get install software-properties-common
apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/repo/10.2/ubuntu xenial main'
apt update
apt install mariadb-server
Step 10 - Secure web server with Let's Encrypt
Install Certbot
add-apt-repository ppa:certbot/certbot
apt-get update
apt-get install certbot
Add new configuration file
nano /etc/apache2/conf-available/letsencrypt.conf
Add the following line
Alias /.well-known /var/www/html/.well-known
Enable it and reload apache
a2enconf letsencrypt
service apache2 reload
Install certificate for server's hostname, note that replace {HOSTNAME} with your server hostname
certbot certonly --webroot --webroot-path=/var/www/html -d {HOSTNAME}
Update Apache default SSL site
nano /etc/apache2/sites-available/default-ssl.conf
Comment out SSLCertificateFile
and SSLCertificateKeyFile
, then add this below SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/{HOSTNAME}/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/{HOSTNAME}/privkey.pem
SSLCACertificateFile /etc/letsencrypt/live/{HOSTNAME}/chain.pem
Next update Nginx default site
Nano /etc/nginx/sites-available/default
Comment out ssl_certificate
and ssl_certificate_key
, then add this below ssl on;
ssl_certificate /etc/letsencrypt/live/{HOSTNAME}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{HOSTNAME}/privkey.pem;
Generate Strong Diffie-Hellman Group
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Add new configuration snippet
nano /etc/nginx/snippets/ssl-params.conf
Add this content
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
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:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-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_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
Update Nginx conf file
nano /etc/nginx/nginx.conf
Comment out ssl_protocols
and ssl_prefer_server_ciphers
, then add this line right after that
include /etc/nginx/snippets/ssl-params.conf;
Reload services
systemctl reload {nginx,apache2}
Set Up Auto Renewal
crontab -e
Add this line at the end
15 3 * * * /usr/bin/certbot renew --quiet --renew-hook "/bin/systemctl reload {nginx,apache2}"
Step 11: Enable firewall
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
sudo ufw disable
sudo ufw enable
That's it!
(Part 2 coming soon)