Installing Apache, PHP 7.3 and MariaDB (LAMP) on Debian 10
LAMP stack guide for installing PHP 7.4 alongside PhpMyAdmin
and Let's Encypt SSL certificates.
i. Prerequisites
1. Have deployed a Debian 10 image on your new server and have your root
password ready. If not perform a full upgrade from Debian 9 or 8.
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 linux terminal to enter commands (or putty for windows).
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 linux terminal to enter commands (or putty for windows).
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 ..`
Elevate to root privileges for whole session
`sudo -i`
To install sudo
`apt install sudo`
- 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'.
- To temporarily elevate to root privileges
- Prefix a command with 'sudo' and execute command
- Replace all placeholders such as 'example.com', 'example_user', 'nothingtosee' and so on with desired strings using string replacer tool
ii. String Replacer Tool
I. Upgrading Debian
If not using Debian 10 or if not sure, check the version by entering following commands
`lsb_release -a`
`uname -mrs`
Update and upgrade existing package
`apt update && apt upgrade && apt full-upgrade && apt --purge autoremove`
Backup and change version to 'buster' on sources file
(replace stretch with jessie for Debian 8)
`cp -v /etc/apt/sources.list /etc/apt/sources.list.bak`
`cp -rv /etc/apt/sources.list.d/ /etc/apt/sources.list.d.bak/`
`sed -i 's/stretch/buster/g' /etc/apt/sources.list`
`sed -i 's/stretch/buster/g' /etc/apt/sources.list.d/*`
Check if the packages are changed to buster
`cat /etc/apt/sources.list`
For locales related warnings you can explicitly set the locales by
running the commands. This may happen when using a Linux terminal ssh.
`export LANGUAGE=en_US.UTF-8`
`export LC_ALL=en_US.UTF-8`
`export LANG=en_US.UTF-8`
`export LC_CTYPE=en_US.UTF-8`
`export LC_ALL=en_US.UTF-8`
`export LANG=en_US.UTF-8`
`export LC_CTYPE=en_US.UTF-8`
Or use dpkg to configure locales
`locale-gen en_US en_US.UTF-8`
`dpkg-reconfigure locales`
`dpkg-reconfigure locales`
(Enter 'Y' for every choice question except for 'Keeping local version...' which is N or O)
`apt update && apt upgrade && apt full-upgrade && apt --purge autoremove`
II. Configuring Network
To set preference to ipv4 (optional)
`nano /etc/gai.conf`
un-comment "precedence ::ffff:0:0/96 100" by removing preceding pound
When prompted, type y and press enter.
To disable ipv6 completely add following lines to sysctl.conf
(optional)
`nano /etc/sysctl.conf`
`net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1`
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1`
And execute
`sysctl -p`
Or alternatively edit grub and append "ipv6.disable=1", update and reboot
`nano /etc/default/grub`
GRUB_CMDLINE_LINUX_DEFAULT=".. .. ipv6.disable=1"
GRUB_CMDLINE_LINUX=".. .. ipv6.disable=1"
And execute update and reboot
`update-grub`
Installing 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
`nano iptables.sh`
`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`
Rules for ipv4 (when enabled)
`::bash::iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -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
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
iptables -A INPUT -i lo -j ACCEPT
iptables -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
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
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
iptables -A OUTPUT -p tcp -m multiport --sports 22,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
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
iptables -A INPUT -p udp --dport 1900 -j DROP
iptables -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]: "
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
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`
iptables -P FORWARD DROP
iptables -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
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
iptables -A INPUT -i lo -j ACCEPT
iptables -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
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
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
iptables -A OUTPUT -p tcp -m multiport --sports 22,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
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
iptables -A INPUT -p udp --dport 1900 -j DROP
iptables -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]: "
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
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`
Rules for ipv6 (when enabled)
`::bash::ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -6 -A INPUT -s ::1/128 ! -i lo -j DROP
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -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
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
ip6tables -A INPUT -p tcp -m multiport --dports 80,443 --syn -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -p tcp -m multiport --sports 80,443 --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
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
ip6tables -A INPUT -p udp --dport 1900 -j DROP
ip6tables -A INPUT -p udp --sport 53 -j DROP
ip6tables -A INPUT -m limit --limit 1/second --limit-burst 100 -j LOG --log-prefix "iptables[DOS]: "
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
ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m limit --limit 150/second --limit-burst 160 -j ACCEPT`
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -6 -A INPUT -s ::1/128 ! -i lo -j DROP
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -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
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
ip6tables -A INPUT -p tcp -m multiport --dports 80,443 --syn -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -p tcp -m multiport --sports 80,443 --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
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
ip6tables -A INPUT -p udp --dport 1900 -j DROP
ip6tables -A INPUT -p udp --sport 53 -j DROP
ip6tables -A INPUT -m limit --limit 1/second --limit-burst 100 -j LOG --log-prefix "iptables[DOS]: "
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
ip6tables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m limit --limit 150/second --limit-burst 160 -j ACCEPT`
Rules for ipv6 (when disabled)
`::bash::ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT DROP`
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT DROP`
Execute script to add rules to iptables
`sh -x iptables.sh`
If ip6tables rules failed, retry after switiching to legacy mode
`update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy`
To save the rules and restore it after every boot
`iptables-save > /etc/iptables.rules`
`iptables-save > /etc/iptables.rules`
`ip6tables-save > /etc/ip6tables.rules`
`iptables-restore < /etc/iptables.rules`
`iptables-restore < /etc/iptables.rules`
`ip6tables-restore < /etc/ip6tables.rules`
To restore it automatically after reboot, add to cron jobs
`nano /etc/crontab`
`@reboot root iptables-restore < /etc/iptables.rules
@reboot root ip6tables-restore < /etc/ip6tables.rules`
To restore it automatically after reboot, add to cron jobs
`nano /etc/crontab`
`@reboot root iptables-restore < /etc/iptables.rules
@reboot root ip6tables-restore < /etc/ip6tables.rules`
III. Configuring Apache Server and SSL
For aws-only
Set to preserve hostname on cloud init configs
`nano /etc/cloud/cloud.cfg`
`preserve_hostname: true`
Then set hostname
`hostnamectl set-hostname --static example.com`
For non-aws
Set hostname
`hostnamectl set-hostname example.com`
Configure ip with hosts (replace example.com and replace x.x.x.x [ipv4] and y:y:y:y:y:y:y [ipv6]).
`nano /etc/hosts`
y:y:y:y:y:y:y example.com.example.com example.com`
`hostname`
`hostname -f`
Set Localtime
`dpkg-reconfigure tzdata`
`apt update && apt upgrade`
`apt install apache2 apache2-doc apache2-utils libapache2-mod-security2 libapache2-mod-evasive`
Securing Apache
Add/Update following parameters on evasive config
nano /etc/apache2/mods-available/evasive.conf
`<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 5
DOSSiteCount 50
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 3600
DOSLogDir "/var/log/apache2/"
</IfModule>`
DOSHashTableSize 3097
DOSPageCount 5
DOSSiteCount 50
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 3600
DOSLogDir "/var/log/apache2/"
</IfModule>`
To whitelist ip's, add following param (replace y.. with ipv4 or ipv6)
`DOSWhitelist y.y.y.y`
Enable security, evasive and headers module
`a2enmod security2`
`a2enmod evasive`
`a2enmod headers`
Edit apache conf and add or update following config
`nano /etc/apache2/apache2.conf`
`KeepAlive Off
ServerSignature Off
ServerTokens Prod`
ServerSignature Off
ServerTokens Prod`
Edit and enable Prefork module
`nano /etc/apache2/mods-available/mpm_prefork.conf`
Set MaxConnectionsPerChild to a valid number (eg.100) to prevent memory leaks. Edit other values to fine tune apache.
`a2dismod mpm_event`
`a2enmod mpm_prefork`
`systemctl restart apache2`
Disable default apache virtual host
`a2dissite 000-default.conf`
Add virtual host configuration and save file (replace example.com)
`nano /etc/apache2/sites-available/example.com.conf`
`::apacheconfig::<VirtualHost *:80>
ServerAdmin webmaster@example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/site/
<Directory "/var/www/example.com/.well-known/acme-challenge/">
Options None
AllowOverride None
ForceType text/plain
RedirectMatch 404 "^(?!/\.well-known/acme-challenge/[\w-]{43}$)"
</Directory>
RedirectMatch 301 ^((?!\/(.well-known\/acme-challenge\/)).*)$ https://example.com$1
</VirtualHost>`
Create directories for your public site and logs (replace example.com)
`mkdir -p /var/www/example.com/site`
`mkdir /var/www/example.com/logs`
Enable the site and reload apache (replace example.com)
`a2ensite example.com.conf`
`systemctl reload apache2`
`nano /etc/apache2/mods-available/mpm_prefork.conf`
Set MaxConnectionsPerChild to a valid number (eg.100) to prevent memory leaks. Edit other values to fine tune apache.
`a2dismod mpm_event`
`a2enmod mpm_prefork`
`systemctl restart apache2`
Disable default apache virtual host
`a2dissite 000-default.conf`
Add virtual host configuration and save file (replace example.com)
`nano /etc/apache2/sites-available/example.com.conf`
`::apacheconfig::<VirtualHost *:80>
ServerAdmin webmaster@example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/site/
<Directory "/var/www/example.com/.well-known/acme-challenge/">
Options None
AllowOverride None
ForceType text/plain
RedirectMatch 404 "^(?!/\.well-known/acme-challenge/[\w-]{43}$)"
</Directory>
RedirectMatch 301 ^((?!\/(.well-known\/acme-challenge\/)).*)$ https://example.com$1
</VirtualHost>`
Create directories for your public site and logs (replace example.com)
`mkdir -p /var/www/example.com/site`
`mkdir /var/www/example.com/logs`
Enable the site and reload apache (replace example.com)
`a2ensite example.com.conf`
`systemctl reload apache2`
Repeat the three step procedure to create multiple sites.
- Create virtual config for site
- Create directories for site
- Enable site
B. Installing SSL
Install certbot client to obtain ssl from letsencrypt.com
`apt install certbot python-certbot-apache`
Getting a certificate using webroot and certbot. (Enter an email for updates)
`apt install certbot python-certbot-apache`
Getting a certificate using webroot and certbot. (Enter an email for updates)
Use --rsa-key-size 3072 parameter to change key size
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`
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
To increase security, generate DH bit group
`openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048`
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."
`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`
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
To increase security, generate DH bit group
`openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048`
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."
Add/update following ssl parameters to ssl module config
`nano /etc/apache2/mods-available/ssl.conf`
`::apacheconfig::SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol -all +TLSv1.3 +TLSv1.2
SSLHonorCipherOrder on
SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1
SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"
SSLCompression off
SSLSessionTickets off
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingCache shmcb:/var/run/ocsp(128000)`
SSLProtocol -all +TLSv1.3 +TLSv1.2
SSLHonorCipherOrder on
SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1
SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"
SSLCompression off
SSLSessionTickets off
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingCache shmcb:/var/run/ocsp(128000)`
Enable ssl mod
`a2enmod ssl`
`systemctl restart apache2`
Append to vhost file to include ssl config (replace example.com)
`nano /etc/apache2/sites-available/example.com.conf`
`::apacheconfig::<VirtualHost *:443>
ServerAdmin webmaster@example.com
ServerName example.com
ServerAlias www.example.com
AddType application/x-httpd-php .php
DocumentRoot /var/www/example.com/site/
DirectoryIndex index.php index.html index
ErrorLog /var/www/example.com/logs/error.log
CustomLog /var/www/example.com/logs/access.log combined
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
Header always set Strict-Transport-Security "max-age=15768000"
RequestHeader append "X-Forwarded-Proto" "https"
RequestHeader set "X-Forwarded-Ssl" "on"
</VirtualHost>`
ServerAdmin webmaster@example.com
ServerName example.com
ServerAlias www.example.com
AddType application/x-httpd-php .php
DocumentRoot /var/www/example.com/site/
DirectoryIndex index.php index.html index
ErrorLog /var/www/example.com/logs/error.log
CustomLog /var/www/example.com/logs/access.log combined
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
Header always set Strict-Transport-Security "max-age=15768000"
RequestHeader append "X-Forwarded-Proto" "https"
RequestHeader set "X-Forwarded-Ssl" "on"
</VirtualHost>`
Check ssl-rating for A+
In your browser:
`https://www.ssllabs.com/ssltest/analyze.html?d=example.com`
In your browser:
`https://www.ssllabs.com/ssltest/analyze.html?d=example.com`
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`
`::bash::30 1 * * * /usr/bin/certbot renew >> /var/log/le-renew.log
35 1 * * * /bin/systemctl restart apache2`
`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`
`::bash::30 1 * * * /usr/bin/certbot renew >> /var/log/le-renew.log
35 1 * * * /bin/systemctl restart apache2`
IV. Installing PHP 7.3 and MariaDB
A. Installing PHP
PHP7.3 is available with Debian 10 repository
`apt install php7.3-cli php7.3-cgi php7.3-fpm php7.3-mysql php7.3-json php7.3-curl php7.3-mbstring php7.3-zip libapache2-mod-php7.3`
Link to other usable php extensions : https://www.php.net/manual/en/extensions.alphabetical.php
Securing PHP : Edit php.ini
`nano /etc/php/7.3/apache2/php.ini`
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 php defaults, enable fcgi modules and restart fpm
`update-alternatives --set php /usr/bin/php7.3`
Link to other usable php extensions : https://www.php.net/manual/en/extensions.alphabetical.php
Securing PHP : Edit php.ini
`nano /etc/php/7.3/apache2/php.ini`
- Set 0 for cgi.fix_pathinfo
- 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
When using FCGI, edit php.ini in fpm update above changes
`nano /etc/php/7.3/fpm/php.ini`
http://php.net/manual/en/session.security.ini.php
https://medium.com/the-white-hat-elephpant/a-look-into-sessions-and-security-b6939a8f6e92
Set php defaults, enable fcgi modules and restart fpm
`update-alternatives --set php /usr/bin/php7.3`
`a2enmod proxy_fcgi setenvif`
`a2enconf php7.3-fpm`
`systemctl restart php7.3-fpm`
Create a php page to test (optional) (replace example.com)
`nano /var/www/example.com/site/index.php`
`::php::<?php echo "Welcome to example.com"; die(); ?>`
`nano /var/www/example.com/site/index.php`
`::php::<?php echo "Welcome to example.com"; die(); ?>`
To use FCGI for php, include following within ssl vhost (optional)
`::apacheconfig::<LocationMatch "(.*)\.(php)">
ProxyPassMatch "unix:/var/run/php/php7.3-fpm.sock|fcgi://localhost/var/www/example.com/site/"
</LocationMatch>`
ProxyPassMatch "unix:/var/run/php/php7.3-fpm.sock|fcgi://localhost/var/www/example.com/site/"
</LocationMatch>`
This is run all php scripts using FCGI proxy instead of Apache handler. Use phpinfo(); to check.
B. Installing MariaDB
`apt -y install mariadb-server mariadb-client`
Secure MariaDB (set Y for all and set root pass)
`mysql_secure_installation`
Check status of MariaDB
`systemctl status mariadb`
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)
`::sql::CREATE DATABASE db_name;`
`::sql::CREATE USER 'db_user'@'127.0.0.1' IDENTIFIED BY 'db_pass';`
`::sql::GRANT ALL PRIVILEGES ON db_name.* TO 'db_user'@'127.0.0.1';`
Check mysql.user table for limited user and flush.
`::sql::SELECT User, Host, plugin FROM mysql.user;`
`::sql::FLUSH PRIVILEGES;`
`\q`
Restart MariaDB and PHP to save changes
`service mariadb restart`
`systemctl restart php7.3-fpm`
C. Installing phpmyadmin
Get the latest pure binary file (.tar.gz) from https://www.phpmyadmin.net/downloads/
`wget https://files.phpmyadmin.net/phpMyAdmin/4.9.5/phpMyAdmin-4.9.5-all-languages.tar.gz`
`tar xvf phpMyAdmin-4.9.5-all-languages.tar.gz`
Move and rename the directory (replace 'nothingtosee')
`mv phpMyAdmin-4.9.5-all-languages /usr/share/`
`mv -T /usr/share/phpMyAdmin-4.9.5-all-languages /usr/share/nothingtosee`
`ls -al /usr/share/`
Create Symbolic link to phpmyadmin (replace 'nothingtosee' & 'example.com')
`ln -s /usr/share/nothingtosee /var/www/example.com/site`
Visit http://example.com/nothingtosee/ to see phpmyadmin page.
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')
`nano /usr/share/nothingtosee/config.inc.php`
$cfg['blowfish_secret'] = 'bf_secret';
$cfg['Servers'][$i]['host'] = '127.0.0.1';
Add password to the phpmyadmin page (replace example_user with username and enter a password for auth)
`htpasswd -c -B /etc/apache2/pma_pass example_user`
Edit hosts file to reflect addition (replace example.com) and add the following within VirtualHost tag
`nano /etc/apache2/sites-available/example.com.conf`
`::apacheconfig::<Directory "/var/www/example.com/site/nothingtosee">
AuthType Basic
AuthName "Restricted Content"
AuthUserFile /etc/apache2/pma_pass
Require valid-user
</Directory>`
`systemctl restart apache2`
Visit http://example.com/nothingtosee/ to see auth.
If there are session based errors, provide full access to sessions folder
`chmod 777 /var/lib/php/sessions`
Login in to MariaDB (with root pass)
`mariadb -u root -p`
Create a database for limited user (replace db_name, db_user, db_pass)
`::sql::CREATE DATABASE db_name;`
`::sql::CREATE USER 'db_user'@'127.0.0.1' IDENTIFIED BY 'db_pass';`
`::sql::GRANT ALL PRIVILEGES ON db_name.* TO 'db_user'@'127.0.0.1';`
Check mysql.user table for limited user and flush.
`::sql::SELECT User, Host, plugin FROM mysql.user;`
`::sql::FLUSH PRIVILEGES;`
`\q`
Restart MariaDB and PHP to save changes
`service mariadb restart`
`systemctl restart php7.3-fpm`
C. Installing phpmyadmin
Get the latest pure binary file (.tar.gz) from https://www.phpmyadmin.net/downloads/
`wget https://files.phpmyadmin.net/phpMyAdmin/4.9.5/phpMyAdmin-4.9.5-all-languages.tar.gz`
`tar xvf phpMyAdmin-4.9.5-all-languages.tar.gz`
Move and rename the directory (replace 'nothingtosee')
`mv phpMyAdmin-4.9.5-all-languages /usr/share/`
`mv -T /usr/share/phpMyAdmin-4.9.5-all-languages /usr/share/nothingtosee`
`ls -al /usr/share/`
Create Symbolic link to phpmyadmin (replace 'nothingtosee' & 'example.com')
`ln -s /usr/share/nothingtosee /var/www/example.com/site`
Visit http://example.com/nothingtosee/ to see phpmyadmin page.
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')
`nano /usr/share/nothingtosee/config.inc.php`
$cfg['blowfish_secret'] = 'bf_secret';
$cfg['Servers'][$i]['host'] = '127.0.0.1';
Add password to the phpmyadmin page (replace example_user with username and enter a password for auth)
`htpasswd -c -B /etc/apache2/pma_pass example_user`
Edit hosts file to reflect addition (replace example.com) and add the following within VirtualHost tag
`nano /etc/apache2/sites-available/example.com.conf`
`::apacheconfig::<Directory "/var/www/example.com/site/nothingtosee">
AuthType Basic
AuthName "Restricted Content"
AuthUserFile /etc/apache2/pma_pass
Require valid-user
</Directory>`
`systemctl restart apache2`
Visit http://example.com/nothingtosee/ to see auth.
If there are session based errors, provide full access to sessions folder
`chmod 777 /var/lib/php/sessions`
V. Setting up SFTP file access
Create a new group (replace example_group)
`groupadd example_group`
Add Limited User Account (replace example_user and enter password for user)
`adduser example_user`
Add limited_user to the group (For AWS only)
`adduser example_user example_group`
For AWS EC2, creating ssh keys is the only way now. Follow instructions given below to create ssh keys.
Mod limited_user to the group with root directory (For non-aws VPS providers DO, Linode, Vultr, etc..)
`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/example.com`
`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)
`::bash::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)
Adding Public Key Auth for SSH
Create keypair using terminal (for Linux only)
`ssh-keygen -t rsa -b 4096 -f ~/.ssh/example_user-example.com-ssh.key`
Install and open putty-keygen.exe (for Windows only)
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 (non-aws vps)
`mkdir ~/.ssh; touch ~/.ssh/authorized_keys; chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys`
Create new directory for auth key (aws only)
`mkdir /home/example_user/.ssh; touch /home/example_user/.ssh/authorized_keys; chmod 700 /home/example_user/.ssh; chmod 600 /home/example_user/.ssh/authorized_keys; chown -R example_user:example_user /home/example_user/.ssh`
Edit the file and copy public key directly from keygen (or .pub file, if created from terminal) and paste here
For non-aws
`nano ~/.ssh/authorized_keys`
For aws
`nano /home/example_user/.ssh/authorized_keys`
Make sure private key matches the saved public key for that user.
Restart ssh to confirm changes
`service ssh restart`
`systemctl restart apache2`
Try authenticating using Filezilla/Winscp to confirm access
VI. Optional commands
To Delete Limited User Account
`deluser --remove-home username`
To Delete any folders (created by mistake)
`rm -r -f /path/`
Restart PHP & Apache2
`systemctl restart php7.3-fpm apache2`
To revoke and remove ssl cert using certbot
`certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem`
`rm -rf /etc/certbot/archive/example.com/`
`rm -rf /etc/certbot/live/example.com/`
`rm -rf /etc/certbot/renewal/example.com.conf`
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`
`::sql::ALTER USER 'root'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY 'password';`
To check Apache status and error log
`systemctl status apache2.service`
or
`tail -n 20 /var/log/apache2/error.log`
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.3-memcached`
Add memcached extension to php.ini & restart
`nano /etc/php/7.3/fpm/php.ini`
`extension=memcached`
`systemctl restart php7.3-fpm`
Post a Comment