How To Install Linux, Nginx, MariaDB, PHP 7.2 (LEMP) Stack on Debian 9













This guide includes all commands and codes that can be executed on a Linux terminal (console) to install a Nginx server (LEMP stack) on Debian 9 (Stretch), along with PhpMyAdmin and free ssl certificates.


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 changes on nano, press ctrl+x and type 'y' (without quotes) and press enter. To discard changes type 'n' instead of 'y'.

Temporarily elevate to root privileges


Prefix a command with 'sudo' and execute command

Prerequisites to install LEMP stack on Debian 9

1. Have deployed a Debian 9 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 up and running

4. This guide uses putty for terminal.

Tips & Instructions

1. To copy code 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.

3. From Debian 9 onwards, you can use 'apt' instead of 'apt-get'.


Steps to install LEMP stack on Debian 9 (Stretch)

Set preference to ipv4 (optional)

nano /etc/gai.conf


uncomment "precedence ::ffff:0:0/96 100" by removing preceding pound

Update & Upgrade Linux

apt update && apt upgrade


When prompted, type y and press enter.

Install sudo (if doesn't exist, and optional)

apt install sudo


Set Hostname (replace xhostname)

hostnamectl set-hostname xhostname



Update /etc/hosts (replace example.com and replace x.x.x.x [ipv4] and y:y::y:y:y:y [ipv6] with ip found on your vps dashboard).

nano /etc/hosts

x.x.x.x xhostname.example.com xhostname
y:y:y:y:y:y:y xhostname.example.com xhostname

Check Hostname

hostname

hostname -f

Set Localtime

dpkg-reconfigure tzdata

Install Nginx

apt update && apt upgrade

apt install nginx


Edit nginx.conf and uncomment "server_names_hash_bucket_size 64;"

nano /etc/nginx/nginx.conf


Adding package sources (For PHP 7.x only)

Note : PHP Packages are obtained from packages.sury.org


apt install apt-transport-https lsb-release ca-certificates

wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg

echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php.list

apt update && apt upgrade

Installing PHP 7.2 with FastCGI

Note : PHP 7.2 does not come with Mcrypt, use 'text replacer' at the bottom of this post to change 7.2 to 7.0 for Mcrypt. Optionally you can also try the latest PHP 7.3 instead. Below are few general extensions, add more php packages as required. 

apt install php7.2-cli php7.2-cgi php7.2-fpm php7.2-mysql php7.2-json php7.2-curl php7.2-mbstring php7.2-zip

apt update

Securing PHP : Edit php.ini, and uncomment and set fix_pathinfo to 0

nano /etc/php/7.2/fpm/php.ini

Set 0 and uncomment (remove preceding semicolon) cgi.fix_pathinfo=0


Set 1 for session.referer_check


Set 1 for session.cookie_httponly

Set 128 for session.sid_length

Set 6 for session.sid_bits_per_character

Set 1 for session.use_strict_mode

Set 1 for session.cookie_secure

For more session security settings visit the links below

http://php.net/manual/en/session.security.ini.php

https://medium.com/the-white-hat-elephpant/a-look-into-sessions-and-security-b6939a8f6e92

Set as default and restart fpm to conclude
 


update-alternatives --set php /usr/bin/php7.2

systemctl restart php7.2-fpm

Install Maria DB Server

Note: Maria DB is same as MySql, just the name. 

apt -y install mariadb-server mariadb-client

Secure Maria DB Server (set Y for all and set root pass)

mysql_secure_installation


Check status of MariaDB


systemctl status mariadb

Create server block for first site (Replace example.com)

apt update


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.2-fpm.sock;
     } 
     location ~ /\.ht { 
       deny all; 
     }

     location ~ /.well-known/acme-challenge/ {
       allow all;
     }
}

Create directories for first site (replace example.com)

mkdir -p /var/www/example.com/site



Enable the site

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled



Check for errors & restart nginx

nginx -t


systemctl restart nginx

Create a php page to test (optional) (replace example.com)

nano /var/www/example.com/site/index.php



<?php   
     echo "Welcome to Slickalpha";
?>

Restart Nginx

systemctl restart nginx


Repeat the three step procedure to create multiple sites.

  1. Create server block for site
  2. Create directories for site
  3. Enable the server block
Install certbot client to obtain ssl from letsencrypt.com

apt install certbot

Getting a certificate using webroot and certbot. (Enter an email for updates)

To test a certificate using staging environment before using production environment (optional)

certbot certonly --staging --webroot --agree-tos -w /var/www/example.com/site -d example.com 

To get a production level certificate using webroot (Limited to 5 attempts/hr)

certbot certonly --webroot --agree-tos -w /var/www/example.com/site -d example.com 

To get certificates for sub domains (optional)

certbot certonly --webroot --agree-tos -w /var/www/example.com/site -d example.com -d www.example.com -w /var/www/sub.example.com/site -d sub.example.com





Use --rsa-key-size 3072 parameter to change key size

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


ls -l /etc/letsencrypt/live/example.com

Replace default server block to return 404

rm /etc/nginx/sites-available/default

nano /etc/nginx/sites-available/default


server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 404;
    location ~ /\.ht {

        deny all;
    }
}


Restart Nginx

systemctl restart nginx


To increase security, generate DH bit group


openssl dhparam -out /etc/ssl/certs/dhparam.pem 3072

https://en.wikipedia.org/wiki/Key_size#Asymmetric_algorithm_key_lengths -> "RSA claims that 1024-bit [asymmetric] keys are likely to become crackable some time between 2006 and 2010 and that 2048-bit keys are sufficient until 2030. An RSA key length of 3072 bits should be used if security is required beyond 2030. NIST key management guidelines further suggest that 15360-bit [asymmetric] RSA keys are equivalent in strength to 256-bit symmetric keys."

Create config snippet to point SSL key and cert (replace example.com)

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;


Create config snippet with encryption params

nano /etc/nginx/snippets/ssl-params.conf


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 backup of config (replace example.com)

cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.com.bak

Edit server blocks for ssl-port 443

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 {

    listen 443 ssl;

    listen [::]:443 ssl;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    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.2-fpm.sock;
    } 
    location ~ /\.ht { 
       deny all; 
    }

}

Check Nginx for errors & restart

nginx -t


systemctl restart nginx


Check ssl-rating for A+

In your browser:


https://www.ssllabs.com/ssltest/analyze.html?d=example.com


Adding a limited access SFTP user to access site files

Create a new group (replace example_group)

addgroup --system example_group

Add Limited User Account (replace example_user and enter password for user)

adduser example_user


Mod limited_user to the group with root directory (replace example.com)

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) permissions

chown -R root:root /var/www/example.com


chown -R example_user:example_group /var/www/example.com/site

chmod -R 755 /var/www


chmod -R 775 /var/www/example.com/site


Edit sshd_config

nano /etc/ssh/sshd_config


Comment out following line in sshd_config (add a preceding pound)

#Subsystem sftp /usr/lib/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
X11Forwarding no
AllowTcpForwarding no

ForceCommand internal-sftp


Note: ChrootDirectory is the one that is writable only by root (usually, one less than user directory)

Restart ssh to confirm changes

service ssh restart


apt update


systemctl restart nginx

Try authenticating using Filezilla to confirm access



Install Cron for automated updates

apt install cron

Restrict all user access. Allow access for example_user (if necessary)

echo ALL /etc/cron.deny

echo example_user /etc/cron.allow

Add following two lines to crontab for letsencrypt ssl auto renewal 

crontab -e

30 1 * * * /usr/bin/certbot renew >> /var/log/le-renew.log

35 1 * * * /bin/
systemctl restart nginx

Install Iptables for network security

apt --reinstall install iptables

Flush existing (iptables for ipv4 and ip6tables for ipv6)


iptables -F

ip6tables -F

Note: After adding the following rules do not use the above command to flush instead use the following command. 

iptables-save | awk '/^[*]/ { print $1 } /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; } /COMMIT/ { print $0; }' | iptables-restore

ip6tables-save | awk '/^[*]/ { print $1 } /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; } /COMMIT/ { print $0; }' | ip6tables-restore

To show status

iptables -S

ip6tables -S

or 

iptables --list

or 

iptables -L -n

Create iptables script as shell script (replace x.x.x.x with your ipv4 address)


Note : the following rules do not guarantee anything, but provides basic protection from attacks.


Ports : remove port numbers or lines associated, to disable those ports
22 - SSH
80 - HTTP
443 - HTTPS
25, 465 - SMTP
587 - SMTPS
110 - POP3
995 - POP3S
143 - IMAP
993 - IMAPS


nano iptables.sh

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT

iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

iptables -4 -A INPUT -s 127.0.0.0/8 ! -i lo -j DROP
ip6tables -6 -A INPUT -s ::1/128 ! -i lo -j DROP

iptables -4 -A INPUT -m addrtype --dst-type BROADCAST -j DROP
iptables -4 -A INPUT -m addrtype --dst-type MULTICAST -j DROP
iptables -4 -A INPUT -m addrtype --dst-type ANYCAST -j DROP
iptables -4 -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP

iptables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -N SSHBRUTE
iptables -A SSHBRUTE -m recent --name SSH --set
iptables -A SSHBRUTE -m recent --name SSH --update --seconds 300 --hitcount 10 -m limit --limit 1/second --limit-burst 100 -j LOG --log-prefix "iptables[SSH-brute]: "
iptables -A SSHBRUTE -m recent --name SSH --update --seconds 300 --hitcount 10 -j DROP
iptables -A SSHBRUTE -j ACCEPT
ip6tables -N SSHBRUTE
ip6tables -A SSHBRUTE -m recent --name SSH --set
ip6tables -A SSHBRUTE -m recent --name SSH --update --seconds 300 --hitcount 10 -m limit --limit 1/second --limit-burst 100 -j LOG --log-prefix "iptables[SSH-brute]: "
ip6tables -A SSHBRUTE -m recent --name SSH --update --seconds 300 --hitcount 10 -j DROP
ip6tables -A SSHBRUTE -j ACCEPT

iptables -N ICMPFLOOD
iptables -A ICMPFLOOD -m recent --set --name ICMP --rsource
iptables -A ICMPFLOOD -m recent --update --seconds 1 --hitcount 6 --name ICMP --rsource --rttl -m limit --limit 1/sec --limit-burst 1 -j LOG --log-prefix "iptables[ICMP-flood]: "
iptables -A ICMPFLOOD -m recent --update --seconds 1 --hitcount 6 --name ICMP --rsource --rttl -j DROP
iptables -A ICMPFLOOD -j ACCEPT
ip6tables -N ICMPFLOOD
ip6tables -A ICMPFLOOD -m recent --set --name ICMP --rsource
ip6tables -A ICMPFLOOD -m recent --update --seconds 1 --hitcount 6 --name ICMP --rsource --rttl -m limit --limit 1/sec --limit-burst 1 -j LOG --log-prefix "iptables[ICMP-flood]: "
ip6tables -A ICMPFLOOD -m recent --update --seconds 1 --hitcount 6 --name ICMP --rsource --rttl -j DROP
ip6tables -A ICMPFLOOD -j ACCEPT

iptables -A INPUT -p tcp --dport 22 --syn -m conntrack --ctstate NEW -j SSHBRUTE
iptables -A INPUT -p tcp --dport 22 --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 80,443 --syn -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
ip6tables -A INPUT -p tcp -m multiport --dports 80,443 --syn -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -m multiport --sports 22,80,443 --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -p tcp -m multiport --sports 80,443 --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT

iptables -A INPUT -p tcp -m tcp -m multiport --dports 110,143,465,587,993,995 --syn -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp -m multiport --sport 110,143,465,587,993,995 --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp -m multiport --dports 110,143,465,587,993,995 --syn -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -p tcp -m tcp -m multiport --sport 110,143,465,587,993,995 --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 25 --syn -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 25 --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
ip6tables -A INPUT -p tcp --dport 25 --syn -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -p tcp --sport 25 --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT

iptables -A INPUT -p udp --dport 1900 -j DROP
ip6tables -A INPUT -p udp --dport 1900 -j DROP
iptables -A INPUT -p udp --sport 53 -j DROP
ip6tables -A INPUT -p udp --sport 53 -j DROP

iptables -A INPUT -m limit --limit 1/second --limit-burst 100 -j LOG --log-prefix "iptables[DOS]: "
ip6tables -A INPUT -m limit --limit 1/second --limit-burst 100 -j LOG --log-prefix "iptables[DOS]: "

iptables -4 -A INPUT -p icmp --icmp-type 0  -m conntrack --ctstate NEW -j ACCEPT
iptables -4 -A INPUT -p icmp --icmp-type 3  -m conntrack --ctstate NEW -j ACCEPT
iptables -4 -A INPUT -p icmp --icmp-type 11 -m conntrack --ctstate NEW -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 1   -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 2   -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 3   -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 4   -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 133 -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 134 -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 135 -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 136 -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 137 -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 141 -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 142 -j ACCEPT
ip6tables -6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 130 -j ACCEPT
ip6tables -6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 131 -j ACCEPT
ip6tables -6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 132 -j ACCEPT
ip6tables -6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 143 -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 148 -j ACCEPT
ip6tables -6 -A INPUT -p ipv6-icmp --icmpv6-type 149 -j ACCEPT
ip6tables -6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 151 -j ACCEPT
ip6tables -6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 152 -j ACCEPT
ip6tables -6 -A INPUT -s fe80::/10 -p ipv6-icmp --icmpv6-type 153 -j ACCEPT

ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 128 -j ICMPFLOOD

iptables -A INPUT -p tcp -s x.x.x.x --sport 1024:65535 -d x.x.x.x --dport 3306 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -s x.x.x.x --sport 3306 -d x.x.x.x --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 5 --connlimit-mask 32 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --syn --dport 443 -m connlimit --connlimit-above 15 --connlimit-mask 32 -j REJECT --reject-with tcp-reset
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m limit --limit 150/second --limit-burst 160 -j ACCEPT
ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m limit --limit 150/second --limit-burst 160 -j ACCEPT


Execute script to add rules to iptables

sh -x iptables.sh

Save the rules and restore it after every boot


iptables-save > /etc/iptables.rules

iptables-restore < /etc/iptables.rules

To restore it automatically after reboot, add to cron jobs

nano /etc/crontab

@reboot  root  iptables-restore < /etc/iptables.rules


Creating MariaDB database for Limited user

Login in to MariaDB (with root pass)


mariadb -u root -p

Create a database for limited user (replace db_name, db_user, db_pass)


CREATE DATABASE db_name;

CREATE USER 'db_user'@'127.0.0.1' IDENTIFIED BY 'db_pass';

GRANT ALL PRIVILEGES ON db_name.* TO 'db_user'@'127.0.0.1';

Check mysql.user table for limited user and flush. 

SELECT User, Host, plugin FROM mysql.user;


FLUSH PRIVILEGES;

\q

Restart MariaDB to conclude

service mariadb restart

systemctl restart php7.2-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.7/phpMyAdmin-4.7.7-all-languages.tar.gz


tar xvf phpMyAdmin-4.7.7-all-languages.tar.gz


Move and rename the directory (replace 'nothingtosee')

mv phpMyAdmin-4.7.7-all-languages /usr/share/

mv -T /usr/share/phpMyAdmin-4.7.7-all-languages /usr/share/nothingtosee

ls -al /usr/share/



rm phpMyAdmin-4.7.7-all-languages.tar.gz

Create Symbolic link to phpmyadmin (replace 'nothingtosee' & 'example.com')

ln -s /usr/share/nothingtosee /var/www/example.com/site


To setup phpmyadmin config.inc file, rename the sample file (replace 'nothingtosee')

mv /usr/share/nothingtosee/config.sample.inc.php /usr/share/nothingtosee/config.inc.php

Set blowfish_secret and change host to '127.0.0.1' in config file and save (replace 'bf_secret' with 32 chars)

nano /usr/share/nothingtosee/config.inc.php

$cfg['blowfish_secret'] = 'bf_secret';

$cfg['Servers'][$i]['host'] = '127.0.0.1';


Create password to the secure phpmyadmin page (using openssl)

openssl passwd

Enter a password and copy the resulting encrypted pass. And remember the entered pass for authentication


Create a file to store the username and password for phpmyadmin

nano /etc/nginx/pma_pass


Replace 'example_user' with a username & 'encrypted_password' with the encrypted one copied from previous step


example_user:encrypted_password


Add the phpmyadmin within the working server block of the /example.com config (replace 'nothingtosee' & 'example.com')

nano /etc/nginx/sites-available/example.com

    location ~ ^/nothingtosee/(.+\.php)$ {
        auth_basic "Restricted Content";
        auth_basic_user_file /etc/nginx/pma_pass;
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        #allow 127.0.0.1;
        #deny all;
    }

    location ~ ^/nothingtosee/ {
        auth_basic "Restricted Content";
        auth_basic_user_file /etc/nginx/pma_pass;

    }

Restart Nginx to conclude

service nginx restart


Visit http://example.com/nothingtosee/ to see phpmyadmin page with authentication. 


If there are session based errors, provide full access to sessions folder

sudo chmod 777 /var/lib/php/sessions

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 commands)

Turn off apache2 and reload nginx

service apache2 stop && service nginx reload


To Delete Limited User Account


deluser --remove-home username

To Delete any folders (created by mistake)


rm -r -f /path/


Do a update after every action



apt update

Restart PHP & Nginx & Update


systemctl restart php7.2-fpm nginx


apt-get update


To add default permission to files created using acl


apt install acl

setfacl -R -m d:u::rwx,d:g::rwx,d:o::rwx /var/www/example.com/site/777/

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


systemctl status nginx.service


or tail -n 20 /var/log/nginx/error.log


or nano /var/log/nginx/error.log


Configuration for gZip compression


nano /etc/nginx/nginx.conf

        gzip on;
        gzip_http_version 1.1;
        gzip_vary on;
        gzip_comp_level 6;
        gzip_proxied any;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
        gzip_buffers 16 8k;

        gzip_disable "MSIE [1-6]\.(?!.*SV1)";

Configure browser caching (replace example.com)

nano /etc/nginx/sites-available/example.com

Add the following in server block

    location ~*  \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 365d;

    }

To install Memcached

apt -y install memcached netcat

Check and update configuration and enable memcached

nano /etc/memcached.conf

systemctl restart memcached

systemctl enable memcached

Check if working

echo "stats settings" | nc localhost 11211

Install php extension for memcached

apt install -y php7.2-memcached

Add memcached to php.ini & restart

nano /etc/php/7.2/fpm/php.ini

extension=memcached


systemctl restart php7.2-fpm



Text Replacer Tool (This -> That)
Copyright Slickalpha.com | All Rights Reserved. Powered by Blogger.