Ubuntu Yii2 web server with Nginx+Apache
Introduction
Nginx and Apache are two popular PHP web servers. Running both with Nginx in front of Apache (Nginx reverse proxy) will improve performance significantly. This tutorial will show configuring your Ubuntu server for Yii2 framework environments.
Prerequisites
- Ubuntu Server 16.04 LTS "xenial"
- Root account
Step-by-step Guide
-
Update your OS and install the 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
-
Install Apache and PHP
apt-get install apache2 libapache2-mod-fastcgi php7.1-fpm
-
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
-
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
-
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's 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
-
Changing Apache ports
nano /etc/apache2/ports.conf
Change
Listen 80
toListen 8080
andListen 443
toListen 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
-
Install Nginx
apt-get install nginx
-
Config Nginx
nano /etc/nginx/sites-available/default
Delete all content of the file. We will redirect all HTTP requests 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 a firewall.
Restore original visitor IP from Cloudflare: create a 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;
-
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
-
Secure web server with Let's Encrypt
Install Certbot:
add-apt-repository ppa:certbot/certbot apt-get update apt-get install certbot
Add a 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
andSSLCertificateKeyFile
, 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
andssl_certificate_key
, then add this belowssl 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
andssl_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}"
-
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
Conclusion
Your PHP Yii2 server is now configured with an Nginx reverse proxy.