Linux Server setup

Apache, PHP, Composer, MySQL

In this chapter, we will set up a web application based on PHP using the Laravel framework.

As a server service, we could use the nginx server (reverse proxy) we have already set up, but it is better to add Apache as a separate internal service in between. This makes it easier to convert or scale the system later on. We also maintain a clean distribution of tasks. For example, the implementation of TLS certificates, which is the task of the reverse proxy.

PHP was one of the most popular scripting languages for a long time and has lost support drastically, especially in recent years. Although PHP does not fare well in surveys, it is still the most widely used server-side language for websites. This is mainly because popular CMSs such as Wordpress or Typo3 are written in PHP. The package management software for PHP is called Composer, which is used to obtain PHP modules from the Packagist platform.

We use the Laravel framework with the relational database MySQL.

I will create the web application in the folder /var/www/ We had already prepared that in Subdomain Server Block (dev). Be sure to adjust that accordingly for yourself at the appropriate point.

Install and reset Apache

As usual, we install Apache with apt:

__$ sudo apt install -y apache2

It is likely that error messages appear because port 80 is already used by Nginx (Failed to start The Apache HTTP Server.). Since we don't want to bind Apache to port 80 anyway, we can ignore the error.

Apache automatically creates a default page. The HTML files are located in /var/www/html. We don't really need them, so they could be deleted.

Similar to nginx with server blocks, Apache works with virtual hosts.

A virtual host, also called VHOST, has already been created by Apache. This is defined in the configuration file /etc/apache2/sites-available/000-default.conf and responds to port 80.

__$ less /etc/apache2/sites-available/000-default.conf


<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.

  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

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Of course, we don't want this to happen because we already have nginx connected to port 80 as a reverse proxy. We disable the virtual host by using the Apache command a2dissite to unlink the symbolic link from /etc/apache2/sites-enabled/000-default.conf to the configuration file.

To be able to execute the command in the correct place, we change to the /etc/apache2/sites-enabled directory:

__$ cd /etc/apache2/sites-enabled/

Then we disable the page or virtual host:

__$ sudo a2dissite 000-default.conf

We add a port 3600 in the /etc/apache2/ports.conf. This will later be responsible for our Laravel application. We need to disable the default port 80, so we just comment that out:

__$ sudo nano /etc/apache2/ports.conf

The file /etc/apache2/ports.conf should then look like this:

Excerpt from /etc/apache2/ports.conf

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

#Listen 80
Listen 3600

<IfModule ssl_module>
        Listen 443

<IfModule mod_gnutls.c>
        Listen 443

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Save and close (CTRL+s, CTRL+x).

Let's restart Apache so that the changes are applied:

__$ sudo systemctl restart apache2

If Apache was not running at all due to previous error, we start Apache regularly:

__$ sudo systemctl start apache2

For control we can query the status of Apache. It should display active (running):

__$ sudo systemctl status apache2

We can find out if Apache is bound to port 3600 with the following command:

__$ sudo lsof -i -P | grep LISTEN

The output is a list of all network services (-i) and their port bindings (-P). Apache with port 3600 should be here:

apache2   13045            root    6u  IPv6 125158      0t0  TCP *:3600 (LISTEN)
apache2   27619        www-data    6u  IPv6 125158      0t0  TCP *:3600 (LISTEN)

Assign www-data rights

There will be an access problem later because Apache and tom need access to the web directory. Apache created a new www-data group that we will take advantage of.

First, we include tom with usermod n the www-data group. Instead of the username, we simply use the variable $USER, which stands for the current user.

__$ sudo usermod -a -G www-data $USER

To make the /var/www/ directory accessible to Apache, we change its group membership to www-data with chgrp.

__$ sudo chgrp -R www-data /var/www/

By sharing the www-data group, both can work on the web files.

Create virtual host

We create a new virtual host for our web project. We will assign the internal port 3600 to this and also store the root directory to the web project. In my case this is /var/www/

The public folder does not exist yet, but is quickly created with mkdir:

__$ mkdir /var/www/

We activate the Apache module mod_rewrite with a2enmod:

__$ sudo a2enmod rewrite

For the VHOST, we first create a configuration file. The name should be in "reverse notation" ( according to convention:

__$ sudo nano /etc/apache2/sites-available/

In this file we define the virtual host as follows:


<VirtualHost *:3600>
  DocumentRoot /var/www/
  <Directory /var/www/>
    Options -Indexes +FollowSymLinks
    AllowOverride all
    Require all granted
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

This can be activated by creating a symbolic link in the directory /etc/apache2/sites-available. To do this, we first change there:

__$ cd /etc/apache2/sites-available/

We activate the page with the command a2ensite:

__$ sudo a2ensite

For the changes to take effect, Apache must reread the configuration:

__$ sudo systemctl reload apache2

Apache2 Log files

The two log files, whose paths are defined by variable in the virtual host, are usually located at /var/log/apache2/.

The access log:

__$ sudo tail -f /var/log/apache2/access.log

The error log:

__$ sudo tail -f /var/log/apache2/error.log

Install PHP

In addition to the php module, we install other auxiliary packages:

  • libapache2-mod-php is important for working with Apache.
  • php-mysql we need for the interaction with MySQL.
  • With php-cli (PHP Command Line Interface) PHP can be executed via the command line.
  • Composer packages unzip themselves by unzip.
  • phpunit is a tool for checking PHP scripts.

__$ sudo apt install -y php libapache2-mod-php php-mysql php-cli phpunit unzip

Install Composer 2

Composer is the package manager for PHP modules. We will also use it to obtain Laravel later.

It makes sense to install Composer only for the current user. As installation location ~/.local/bin under Home is suitable for this. Let's create the path for safety in case it doesn't exist:

__$ mkdir -p ~/.local/bin

And switch to there:

__$ cd ~/.local/bin

Then we download Composer via an installation file:

__$ php -r "copy('', 'composer-setup.php');"
__$ php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
__$ php composer-setup.php
__$ php -r "unlink('composer-setup.php');"

To allow composer to be run as a command from anywhere, we put an alias in the ~/.bash_aliases file:/p>

__$ echo 'alias composer="php ~/.local/bin/composer.phar"' >> ~/.bash_aliases

And let the system re-read the bash configuration file:

__$ source ~/.bashrc

With Composer, modules can be installed globally, which can then be used system-wide. Since we have set up Composer for tom only, we should use global show to check how the storage location for global packages is set:

__$ composer global show

The path /home/tom/.config/composer should be mentioned in the output:

Composer could not find a composer.json file in /home/tom/.config/composer

Create database in MySQL

We have already set up the MySQL database in the Installing MySQL chapter.

Therefore, we can now simply call the MySQL console:

__$ sudo mysql

Create a new database user tom that can only act locally and not remotely. The password should be tom123 , which is set with IDENTIFIED BY:

__gt CREATE USER 'tom'@'localhost' IDENTIFIED BY 'tom123';

Create a new database laraveldb:

__gt CREATE DATABASE laraveldb;

Grant the user tom access rights to the previously created database:

__gt GRANT ALL PRIVILEGES ON laraveldb.* TO 'tom'@'localhost';

To make sure that changes are applied, let's re-read the new privileges with FLUSH PRIVILEGES:


We can leave the MySQL console again with exit:

__gt exit