How To Install Linux, Apache, MySQL, PHP (LAMP) Stack on Debian 9 Stretch
I
am a new user of Debian 9 operating system. Can you tell me how to setup and install LAMP stack on a Debian 9 (Stretch)?
LAMP is an acronym for four open source software frequently used to develop the web applications (such as forums, blogs, and business sites):
Linux operating system
Apache web server
MySQL/MariaDB relational database management system (RDBMS)
PHP server-side programming language
This tutorial shows you how to install LAMP (Apache version 2, PHP version 7, MariaDB version 10.2) stack on a Debian 9 Linux server along with firewall settings to open tcp port 80, 22, and 443.
Step 1: Apply patches if any
Type the following apt-get command/apt command to update the system:
$ sudo apt update
Sample outputs:
Hit:1 http://security.debian.org stretch/updates InRelease
Hit:2 http://cdn-fastly.deb.debian.org/debian stretch InRelease
Reading package lists… Done
Building dependency tree
Reading state information… Done
38 packages can be upgraded. Run apt list –upgradable to see them.
To patch it with the latest updates, run:
$ sudo apt-get upgrade
Sample outputs:
Reading package lists… Done
Building dependency tree
Reading state information… Done
Calculating upgrade… Done
The following packages will be upgraded:
apt bash debconf debian-archive-keyring debianutils dpkg file gcc-6-base init init-system-helpers libapt-pkg5.0 libc-bin libc-l10n libc6 libcryptsetup4 libdns-export162
libelf1 libgcc1 libgcrypt20 libisc-export160 libmagic-mgc libmagic1 libpam-modules libpam-modules-bin libpam-runtime libpam0g libssl1.0.2 libssl1.1 libstdc++6
libsystemd0 libudev1 locales login multiarch-support passwd perl-base systemd systemd-sysv
38 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 26.3 MB of archives.
After this operation, 82.9 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://cdn-fastly.deb.debian.org/debian stretch/main amd64 debianutils amd64 4.8.1.1 [100 kB]
Get:2 http://cdn-fastly.deb.debian.org/debian stretch/main amd64 bash amd64 4.4-5 [1427 kB]
….
..
…
Setting up libmagic1:amd64 (1:5.30-1) …
Setting up libssl1.0.2:amd64 (1.0.2l-2) …
Processing triggers for libc-bin (2.24-11) …
Setting up libssl1.1:amd64 (1.1.0f-3) …
Setting up libc-l10n (2.24-11) …
Setting up locales (2.24-11) …
Generating locales (this might take a while)…
en_US.UTF-8… done
Generation complete.
Setting up init (1.48) …
Setting up libdns-export162 (1:9.10.3.dfsg.P4-12.3) …
Setting up file (1:5.30-1) …
Processing triggers for libc-bin (2.24-11) ..
Step 2: Install Apache http server
Type the following command:
$ sudo apt install apache2
Sample outputs:
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following additional packages will be installed:
apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.2-0 ssl-cert
Suggested packages:
www-browser apache2-doc apache2-suexec-pristine | apache2-suexec-custom openssl-blacklist
The following NEW packages will be installed:
apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.2-0 ssl-cert
0 upgraded, 10 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/2143 kB of archives.
After this operation, 7137 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
ebconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package mime-support.
(Reading database … 13992 files and directories currently installed.)
Preparing to unpack …/00-mime-support_3.60_all.deb …
Unpacking mime-support (3.60) …
Selecting previously unselected package libapr1:amd64.
….
..
…
Enabling module filter.
Enabling module deflate.
Enabling module status.
Enabling module reqtimeout.
Enabling conf charset.
Enabling conf localized-error-pages.
Enabling conf other-vhosts-access-log.
Enabling conf security.
Enabling conf serve-cgi-bin.
Enabling site 000-default.
Created symlink /etc/systemd/system/multi-user.target.wants/apache2.service ? /lib/systemd/system/apache2.service.
Created symlink /etc/systemd/system/multi-user.target.wants/apache-htcacheclean.service ? /lib/systemd/system/apache-htcacheclean.service.
Processing triggers for libc-bin (2.24-11) …
Processing triggers for systemd (232-25) …
You can view default page by typing the IP address of your server. To find the IP address of your server use the ip command/ifconfig command as follows:
$ ifconfig eth0
$ ip a show eth0
$ ip a show eth0 | grep -w inet
Sample outputs:
inet 10.114.13.8/24 brd 10.114.13.255 scope global eth0
Fire a web browser and type the following url:
http://10.114.13.8
Sample outputs:
Fig.01: Default Debian 9 Apache 2 page
The Apache HTTP server successfully installed on your server. You can change the default page by editing the index.html file located in /var/www/html/ directory:
$ sudo vi /var/www/html/index.html
How do I stop/start/restart/reload Apache HTTP server?
The syntax is as follows:
$ sudo systemctl {start|stop|restart|reload|status|graceful-stop|force-reload} apache2
To stop Apache 2 server, run:
$ sudo systemctl stop apache2
To start Apache 2 server, run:
$ sudo systemctl start apache2
To restart Apache 2 server, run:
$ sudo systemctl restart apache2
To reload Apache 2 server, run:
$ sudo systemctl reload apache2
To see status of Apache 2 server, run:
$ sudo systemctl status apache2
Fig.02: Controlling Apache 2 server with systemctl command
How do I change configuration of Apache HTTP server?
You need to edit files located in /etc/apache2/ directory:
$ cd /etc/apache2/
$ ls -l
Sample outputs:
total 32
-rw-r–r– 1 root root 7224 Jan 25 22:59 apache2.conf
drwxr-xr-x 2 root root 7 Jun 13 18:46 conf-available
drwxr-xr-x 2 root root 7 Jun 13 18:46 conf-enabled
-rw-r–r– 1 root root 1782 Jan 25 21:16 envvars
-rw-r–r– 1 root root 31063 Jan 25 21:16 magic
drwxr-xr-x 2 root root 138 Jun 13 18:46 mods-available
drwxr-xr-x 2 root root 31 Jun 13 18:46 mods-enabled
-rw-r–r– 1 root root 320 Jan 25 21:16 ports.conf
drwxr-xr-x 2 root root 4 Jun 13 18:46 sites-available
drwxr-xr-x 2 root root 3 Jun 13 18:46 sites-enabled
You need to edit or add a new config file in /etc/apache2/conf-available/ directory. Here is a default config file:
$ cat /etc/apache2/sites-enabled/000-default.conf
Sample outputs:
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request s Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Available loglevels: trace8, …, trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with a2disconf .
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
See Apache Name Based VirtualHost Example for more info on how to configure virtual hosting on Debian 9.
Step 3: Install MariaDB server
MariaDB is RDBMS and drop in replacement for original MySQL server. It is one of the most popular database servers in the world. It’s made by the original developers of MySQL and guaranteed to stay open source. To install MariaDB server, run:
$ sudo apt install default-mysql-server
OR
$ sudo apt install mariadb-server
Sample outputs:
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following additional packages will be installed:
galera-3 gawk libaio1 libarchive13 libcgi-fast-perl libcgi-pm-perl libdbd-mysql-perl libdbi-perl libencode-locale-perl libfcgi-perl libhtml-parser-perl
libhtml-tagset-perl libhtml-template-perl libhttp-date-perl libhttp-message-perl libio-html-perl libjemalloc1 liblwp-mediatypes-perl liblzo2-2 libmariadbclient18
libmpfr4 libreadline5 libreadline7 libsigsegv2 libterm-readkey-perl libtimedate-perl liburi-perl mariadb-client-10.1 mariadb-client-core-10.1 mariadb-common
mariadb-server-10.1 mariadb-server-core-10.1 mysql-common psmisc readline-common socat
Suggested packages:
gawk-doc lrzip libclone-perl libmldbm-perl libnet-daemon-perl libsql-statement-perl libdata-dump-perl libipc-sharedcache-perl libwww-perl mailx mariadb-test
netcat-openbsd tinyca readline-doc
The following NEW packages will be installed:
default-mysql-server galera-3 gawk libaio1 libarchive13 libcgi-fast-perl libcgi-pm-perl libdbd-mysql-perl libdbi-perl libencode-locale-perl libfcgi-perl
libhtml-parser-perl libhtml-tagset-perl libhtml-template-perl libhttp-date-perl libhttp-message-perl libio-html-perl libjemalloc1 liblwp-mediatypes-perl liblzo2-2
libmariadbclient18 libmpfr4 libreadline5 libreadline7 libsigsegv2 libterm-readkey-perl libtimedate-perl liburi-perl mariadb-client-10.1 mariadb-client-core-10.1
mariadb-common mariadb-server-10.1 mariadb-server-core-10.1 mysql-common psmisc readline-common socat
0 upgraded, 37 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/27.1 MB of archives.
After this operation, 195 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libmpfr4:amd64.
(Reading database … 14762 files and directories currently installed.)
Preparing to unpack …/libmpfr4_3.1.5-1_amd64.deb …
….
..
…
Setting up libdbd-mysql-perl (4.041-2) …
Setting up mariadb-client-10.1 (10.1.23-9+deb9u1) …
Setting up mariadb-server-10.1 (10.1.23-9+deb9u1) …
Created symlink /etc/systemd/system/mysql.service ? /lib/systemd/system/mariadb.service.
Created symlink /etc/systemd/system/mysqld.service ? /lib/systemd/system/mariadb.service.
Created symlink /etc/systemd/system/multi-user.target.wants/mariadb.service ? /lib/systemd/system/mariadb.service.
Setting up default-mysql-server (1.0.2) …
Processing triggers for libc-bin (2.24-11) …
Processing triggers for systemd (232-25) …
How do I secure MariaDB mysql server?
Type the following command:
$ sudo mysql_secure_installation
Sample session:
Fig.03: Keeping your MariaDB database server safe
Please note that MariaDB/mysql root account and system root account are two different accounts. This is not the root account used for your server management. So make sure you set different passwords.
How do I test my MariaDB installation?
Type the following command:
$ mysql -u root -p
You will greeted with MariaDB mysql prompt. You can type sql commands to see databases, version and much more:
MariaDB [(none)]> show databases;
MariaDB [(none)]> exit
Sample outputs:
Fig.04: Testing MariaDB/MySQL server installation
See the following tutorials for additional tasks such as adding a new database, users and SSL config:
Mysql User Creation: Setting Up a New MySQL User Account
Create a MySQL Database, Tables and Insert Data
How to setup MariaDB SSL and secure connections from clients
Step 4: Install PHP version 7
PHP version 7 is at least 30-50% faster as compare to PHP 5.6. So let us install PHP version 7 along with php modules for on a Debian 9 server:
$ sudo apt install php7.0 libapache2-mod-php7.0 php7.0-mysql php7.0-gd php7.0-opcache
Sample outputs:
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following additional packages will be installed:
fontconfig-config fonts-dejavu-core libfontconfig1 libfreetype6 libgd3 libjbig0 libjpeg62-turbo libpng16-16 libtiff5 libwebp6 libx11-6 libx11-data libxau6 libxcb1
libxdmcp6 libxpm4 php-common php7.0-cli php7.0-common php7.0-json php7.0-readline
Suggested packages:
php-pear libgd-tools
The following NEW packages will be installed:
fontconfig-config fonts-dejavu-core libapache2-mod-php7.0 libfontconfig1 libfreetype6 libgd3 libjbig0 libjpeg62-turbo libpng16-16 libtiff5 libwebp6 libx11-6 libx11-data
libxau6 libxcb1 libxdmcp6 libxpm4 php-common php7.0 php7.0-cli php7.0-common php7.0-gd php7.0-json php7.0-mysql php7.0-opcache php7.0-readline
0 upgraded, 26 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/8,129 kB of archives.
After this operation, 25.9 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libxau6:amd64.
(Reading database … 15880 files and directories currently installed.)
Preparing to unpack …/00-libxau6_1%3a1.0.8-1_amd64.deb …
….
..
..
Setting up libx11-6:amd64 (2:1.6.4-3) …
Setting up php7.0-cli (7.0.19-1) …
update-alternatives: using /usr/bin/php7.0 to provide /usr/bin/php (php) in auto mode
update-alternatives: using /usr/bin/phar7.0 to provide /usr/bin/phar (phar) in auto mode
update-alternatives: using /usr/bin/phar.phar7.0 to provide /usr/bin/phar.phar (phar.phar) in auto mode
Creating config file /etc/php/7.0/cli/php.ini with new version
Setting up libxpm4:amd64 (1:3.5.12-1) …
Setting up libapache2-mod-php7.0 (7.0.19-1) …
Creating config file /etc/php/7.0/apache2/php.ini with new version
Module mpm_event disabled.
Enabling module mpm_prefork.
apache2_switch_mpm Switch to prefork
apache2_invoke: Enable module php7.0
Setting up libgd3:amd64 (2.2.4-2) …
Setting up php7.0 (7.0.19-1) …
Setting up php7.0-gd (7.0.19-1) …
Creating config file /etc/php/7.0/mods-available/gd.ini with new version
Processing triggers for libc-bin (2.24-11) …
Processing triggers for libapache2-mod-php7.0 (7.0.19-1) …
This will install:
PHP version 7 for Apache 2
PHP 7 mysql connectivity module
PHP 7 OpCache module to speed up scripts
PHP 7 GD module for graphics
You can search and install additional PHP modules using the following syntax:
[search php7 modules] ##
$ apt-cache search php7 | grep module
$ apt search php7 | grep mysql
$ apt-cache search php7 | egrep mysql|gd|zip
$ apt-cache search php7 | more
$ apt search php7 | more
[search php7 modules] ##
$ sudo apt install {module-name-here}
Finally, restart Apache 2 HTTP server, run:
$ sudo systemctl restart apache2
To test PHP installation, create a script called test.php in /var/www/html/ directory:
$ sudo vi /var/www/html/test.php
Append the following PHP code in it:
<?php phpinfo(); ?>
Fire a web-browser and type the following url:
http://10.114.13.8/test.php
Sample outputs:
Fig.05: Testing PHP 7 with Apache 2
PHP now installed and running on your server. It is time to secure PHP, see:
Linux: 25 PHP Security Best Practices For Sys Admins
At this stage you have a full fledged LAMP server running a Debian 9.
Step 5: Configure firewall to open port 80 and 443
Type the following command to install ufw firewall frontend:
$ sudo apt install ufw
Sample outputs:
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following NEW packages will be installed:
ufw
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 164 kB of archives.
After this operation, 848 kB of additional disk space will be used.
Get:1 http://mirrors.kernel.org/debian stretch/main amd64 ufw all 0.35-4 [164 kB]
Fetched 164 kB in 0s (180 kB/s)
Preconfiguring packages …
Selecting previously unselected package ufw.
(Reading database … 43888 files and directories currently installed.)
Preparing to unpack …/archives/ufw_0.35-4_all.deb …
Unpacking ufw (0.35-4) …
Setting up ufw (0.35-4) …
Creating config file /etc/ufw/before.rules with new version
Creating config file /etc/ufw/before6.rules with new version
Creating config file /etc/ufw/after.rules with new version
Creating config file /etc/ufw/after6.rules with new version
Created symlink /etc/systemd/system/multi-user.target.wants/ufw.service ? /lib/systemd/system/ufw.service.
Processing triggers for systemd (232-25) …
Processing triggers for man-db (2.7.6.1-2) …
Processing triggers for rsyslog (8.24.0-1) …
You must allow access to SSH port 22:
$ sudo ufw allow 22
Rules updated
Rules updated (v6)
Open port 80 and 443
$ sudo ufw allow 80
$ sudo ufw allow 443
Now you have default policy and ssh port including 80/443 allowed. It is safe to start enable the firewall, enter:
$ sudo ufw enable
Sample outputs:
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
To see firewall rules, run:
$ sudo ufw status verbose
Sample outputs:
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
— —— —-
22 ALLOW IN Anywhere
80 ALLOW IN Anywhere
443 ALLOW IN Anywhere
22 (v6) ALLOW IN Anywhere (v6)
80 (v6) ALLOW IN Anywhere (v6)
443 (v6) ALLOW IN Anywhere (v6)
And there you have it, LAMP installed and running sucessfully on a Debian 9 system. Take a look at other tutorials for more info:
Securing Your Linux Server
Securing Your OpenSSH Server