How to Install PHP 7.0 (LEMP Stack) on Debian 8 VPS

Please find the updated working guide for LEMP stack here : https://dev.slickalpha.blog/2019/11/installing-lemp-stack-on-debian-buster.html
This guide should be used by system administrators for reference. If you are new to Linux or want to your server setup with nginx and php 7.0, click 'contact us' on the taskbar.
Before you continue make sure you have a server instance ready to test installation. Try VULTR for cheap and reliable VPS servers.

This guide includes all commands and codes that can be executed on a Linux terminal to install a LEMP stack on Debian 8, along with phpmyadmin, free ssl certificates, ssh key setup, etc,...
Basic Linux Commands
Print Working Directory
pwd
Change Directory (to root)
cd /
List Current Directory
ls -ahl
-a : all the files
-h : human readable
-l : long list
Change Directory (to var)
cd var
Change Directory (to previous)
cd ..
Text Editior (nano)
Prefix a file path or file name with 'nano' and execute command
To save file, press ctrl+y and press enter
Temporarily elevate to root privileges
Prefix a command with 'sudo' and execute command
Prerequisites to install LEMP stack on Debian 8
1. Have deployed Debian 8 image on your new server and have your root password ready
2. Have pointed your domain (example.com) to your server public ip address
3. Have booted your server and is running
4. This guide is for windows users. Install putty for terminal.
Tips & Instructions
1. To copy from here, use ctrl-c, and to paste it on putty, mouse-right-click once on putty
2. Replace all place holders such as 'example.com', 'example_user', 'nothingtosee' and so on with desired strings.
Steps to install LEMP stack on Debian 8
Set preference to ipv4
nano /etc/gai.conf
uncomment "precedence ::ffff:0:0/96 100"
Update & Upgrade Linux
apt-get update
apt-get upgrade
Install sudo (if doesn't exist)
apt-get install sudo
Check if Host File exists
nano /etc/hosts
Set Hostname (replace xhostname)
hostnamectl set-hostname xhostname
Update /etc/hosts (replace example.com with domain)
nano /etc/hosts
127.0.0.1 localhost.localdomain localhost
203.0.113.10 xhostname.example.com xhostname
2600:3c01::a123:b456:c789:d012 xhostname.example.com xhostname
Check Hostname
nano /etc/init.d/hostname.sh
hostname
hostname -f
Set Localtime
dpkg-reconfigure tzdata
Install Nginx
sudo apt-get update
sudo apt-get install nginx
Install MySQL DB Server (& set root pass)
sudo apt-get install mysql-server
Secure MySQL DB Server (set Y except root pass)
sudo mysql_secure_installation
Install PHP with FastCGI
$ sudo -s
echo 'deb http://packages.dotdeb.org jessie all' >> /etc/apt/sources.list
echo 'deb-src http://packages.dotdeb.org jessie all' >> /etc/apt/sources.list
cat /etc/apt/sources.list
sudo apt-get update
sudo apt-get install php7.0-cli php7.0-cgi php7.0-fpm php7.0-mysql php7.0-json php7.0-curl
sudo apt-get update
Fix gpg key errors (if any) (replace 010908312D230C5F with the key shown in error)
gpg --keyserver pgpkeys.mit.edu --recv-key 010908312D230C5F
gpg -a --export 010908312D230C5F | apt-key add -
Securing PHP (Edit php.ini, and uncomment and set fix_pathinfo to 0)
sudo nano /etc/php/7.0/fpm/php.ini
cgi.fix_pathinfo=0
sudo systemctl restart php7.0-fpm
Configure Nginx for PHP
sudo nano /etc/nginx/sites-available/default
Uncomment and edit the highlighted part
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name your_server_ip;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Check for errors & reload nginx
sudo nginx -t
sudo systemctl reload nginx
File System Access
For adding limited access to example_user to sftp (through filezilla or other ftp clients), two things must be done.
1. Grant/Restrict File level permission (read/write/execute)
2. Secure SSH and SFTP Access (through sshd_config)
Add Limited User Account (replace example_user and enter password for user)
adduser example_user
Create a new group (replace example_group)
addgroup --system example_group
Append the sudo file to grant sudo for limited user (optional)
sudo visudo
# User privilege specification
root ALL=(ALL:ALL) ALL
example_user ALL=(ALL:ALL) ALL
Create new site (replace example.com)
sudo mkdir -p /var/www/example.com/site
Mod limited_user to the group with root directory
usermod -g example_group -d /var/www/example.com/site -s /sbin/nologin example_user
Restrict and give limited user r(4)/w(2)/x(1) permission
sudo chown root:root /var/www/example.com/
sudo chmod -R 755 /var/www/example.com/
sudo chmod -R 775 /var/www/example.com/site

Edit sshd_config
sudo nano /etc/ssh/sshd_config
Comment out following line in sshd_config
#Subsystem sftp /usr/libexec/openssh/sftp-server
Add following lines to sshd_config (replace example.com & example_group)
Subsystem sftp internal-sftp
Match Group example_group
ChrootDirectory /var/www/example.com/site
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
Restart ssh to confirm changes
sudo service ssh restart
Create test html page with some sample code for site
nano /var/www/example.com/site/index.html
Create Server Block files for Site (Replace example.com)
sudo apt-get update
sudo nano /etc/nginx/sites-available/example.com
Replace block contents with following and save file. (Replace example.com)
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/site; index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ { include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Enable the site
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled
Edit nginx.conf and uncomment "server_names_hash_bucket_size 64;"
sudo nano /etc/nginx/nginx.conf
Check for errors
sudo nginx -t
Restart Nginx
sudo systemctl restart nginx
Open the domain on your browser to see our test page
Logoff Limited user and login as root
Install Cron for automated updates
sudo apt-get update
sudo apt-get install cron
Restrict all user access. Allow access for example_user (if necessary)
echo ALL /etc/cron.deny
echo example_user /etc/cron.allow
Install UFW for Firewall
sudo apt-get install ufw
Set 'IPV6=yes' if using ipv6
sudo nano /etc/default/ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
Allow tcp 22 or 2222 for ssh access
sudo ufw allow 22/tcp
sudo ufw allow www
sudo ufw allow ftp
To update disable and enable (enable turn it on, make sure ssh is enabled)
sudo ufw disable
sudo ufw enable
sudo ufw status verbose
Add the backports repository to server
echo 'deb http://ftp.debian.org/debian jessie-backports main' | sudo tee /etc/apt/sources.list.d/backports.list
Install Certbot to obtain Letsencrypt ssl
sudo apt-get update
sudo apt-get install certbot -t jessie-backports
Edit Nginx for Webroot usage (for the ssl desired site)
sudo nano /etc/nginx/sites-available/example.com
Add following location block & take note of the root mentioned in the file
location ~ /.well-known {
allow all;
}
sudo nginx -t
sudo systemctl restart nginx
User webroot to request a certificate
sudo certbot certonly -a webroot --webroot-path=/var/www/example.com/site -d example.com -d www.example.com
Enter email & accept terms. Note down the path, similar to '/etc/letsencrypt/live/example.com/'
Check for four files having placed in /etc/letsencrypt/archive with symbolic links in /etc/letsencrypt/live/example.com
· cert.pem: Your domain's certificate
· chain.pem: The Let's Encrypt chain certificate
· fullchain.pem: cert.pem and chain.pem combined
· privkey.pem: Your certificate's private key
sudo ls -l /etc/letsencrypt/live/example.com
To increase security, generate DH bit group
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Create config snippet to point SSL key and cert
sudo nano /etc/nginx/snippets/ssl-example.com.conf
Add the following lines and save the file
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
sudo apt-get update
Create config snippet with strong encryption settings
sudo nano /etc/nginx/snippets/ssl-params.conf
Copy paste the following text. Risky if error occurs!!!
# from https://cipherli.st/
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Preloading HSTS is disabled. Uncomment to includes the
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
Take copy of config
sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.com.bak
Edit the config into two seperate blocks for 80 and ssl-443
sudo nano /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
include snippets/ssl-example.com.conf;
include snippets/ssl-params.conf;
. . .
Adjust UFW for ssl
sudo ufw allow https
Delete http if necessary (http pages now will not load)
sudo ufw delete allow www
Check status of ufw
sudo ufw status verbose
Edit default config to return 404
sudo nano /etc/nginx/sites-available/default
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 404;
location ~ /\.ht {
deny all;
}
}
Check Nginx for errors & restart
sudo nginx -t
sudo systemctl restart nginx
Check ssl-rating for A+
In your browser:
https://www.ssllabs.com/ssltest/analyze.html?d=example.com
Edit crontab to automate renewal and add the following
sudo crontab -e
30 2 * * 1 /usr/bin/certbot renew >> /var/log/le-renew.log
35 2 * * 1 /bin/systemctl reload nginx
Login in to MySQL
mysql -u root -p
Create Database with a new user with permissions
CREATE DATABASE web;
CREATE USER 'webuser' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON web.* TO 'webuser';
quit
Restart PHP to conclude
sudo systemctl restart php7.0-fpm
To install phpmyadmin
Get the latest pure binary file (.tar.gz) from https://www.phpmyadmin.net/downloads/
wget https://files.phpmyadmin.net/phpMyAdmin/4.7.0/phpMyAdmin-4.7.0-all-languages.tar.gz
tar xvf phpMyAdmin-4.7.0-all-languages.tar.gz
Move and rename the directory (replace 'nothingtosee')
mv phpMyAdmin-4.7.0-all-languages /usr/share/
mv -T /usr/share/phpMyAdmin-4.7.0-all-languages /usr/share/nothingtosee
ls -al /usr/share/
Install dependencies & setup config
sudo apt-get install php7.0-mcrypt php-mbstring php7.0-mbstring php-gettext
sudo phpenmod mcrypt
sudo phpenmod mbstring
sudo cp /usr/share/nothingtosee/config.sample.inc.php /usr/share/nothingtosee/config.inc.php
nano /usr/share/nothingtosee/config.inc.php
Set blowfish secret
locate "$cfg['blowfish_secret'] = '';" and enter a string;
Setup encrypted password to open phymyadmin aka 'nothingtosee'
openssl passwd
Copy the resulting encrypted pass. And remember the original pass which will be used for authentication
Create a file to store the username and password for phpmyadmin
sudo nano /etc/nginx/pma_pass
Replace 'sample_user' with username & 'password' with the encrypted one copied from previous step
sample_user:password
Create Symbolic link to phpmyadmin (replace 'nothingtosee' & 'example.com')
sudo ln -s /usr/share/nothingtosee /var/www/example.com/site
Add the phpmyadmin within the working server { } block of the /example.com config (replace 'nothingtosee' & 'example.com')
sudo nano /etc/nginx/sites-available/example.com
location ^~ /nothingtosee/ {
auth_basic "Restricted Content";
auth_basic_user_file /etc/nginx/pma_pass;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
location ~* ^/nothingtosee/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|t$
root /usr/share/;
}
#allow 127.0.0.1;
#deny all;
}
Restart Nginx and open the link on your browser and authenticate
sudo service nginx restart
example.com/nothingtosee
Turn off apache2 and reload nginx (optional)
sudo service apache2 stop && sudo service nginx reload
Adding Public Key Auth for SSH (for each user)
Install and open putty-keygen.exe
Set bits to 4096 and option as SSH-2 RSA and generate
Enter passphrase, save public key, save private key, keep window open
Open putty application, add private key to 'putty connection > ssh > auth', save the session and open session with the desired user (limited/root) and enter password
Create new directory for auth key
mkdir ~/.ssh; touch ~/.ssh/authorized_keys; chmod 700 ~/.ssh
Edit the file and copy public key directly from keygen and paste (ctrl -v)
nano ~/.ssh/authorized_keys
Increase security
chmod 600 ~/.ssh/authorized_keys
Exit and rerun putty, load saved session of desired user.
Make sure private key matches the saved public key for that user.
Enter passphrase to login
Optional Items
To Delete Limited User Account (Optional)
sudo deluser --remove-home username
To Delete any folders (created by mistake)
sudo rm -r -f /path/
Do a update after every action
sudo apt-get update
Restart PHP & Nginx & Update
sudo systemctl restart php7.0-fpm nginx
sudo apt-get update
To change mysql root pass (login to mysql first)
mysql -u root -p
ALTER USER 'root'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'password';
To check Nginx status and error log
sudo systemctl status nginx.service
sudo tail -n 20 /var/log/nginx/error.log
Post a Comment