Run Laravel locally on Ubuntu using Apache virtual host
Tags: laravel, apache, ubuntu, php
Published: 2024-06-08 15:58:57

Refresh APT metadata.

```bash
sudo apt update
```

## Installing MySQL

Install MySQL:

```bash
sudo apt install mysql-server
```

Enter MySQL to edit the `root` user password:

```bash
sudo mysql
```

```sql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
```

Re-enter MySQL to create a database for our app, but using the credentials this time:

```bash
mysql -u root -p
```

```sql
CREATE DATABASE my_app;
```

References:

- <https://www.digitalocean.com/community/tutorials/how-to-install-lamp-stack-on-ubuntu#step-2-installing-mysql>

## Installing Apache

Ubuntu usually comes bundled with a running Apache server but still, I'll include the installation steps.

```bash
sudo apt-get install apache2 -y
```

Check if Apache is installed by verifying its version:

```bash
apache2ctl -v
```

Check if your firewall is active:

```bash
sudo ufw status
sudo ufw app list
```

If it returned `Status: active` then allow HTTP traffic on Apache:

```bash
sudo ufw allow in "Apache"
```

Now, visiting `http://localhost` should display "Apache2 Default Page".

References:

- <https://ubuntu.com/tutorials/install-and-configure-apache#2-installing-apache>
- <https://www.digitalocean.com/community/tutorials/how-to-install-lamp-stack-on-ubuntu#step-1-installing-apache-and-updating-the-firewall>

## Installing PHP

Register the following repo that enables the installation of multiple PHP versions at once.

```bash
sudo add-apt-repository ppa:ondrej/php
```

Install PHP `8.1`.

```bash
sudo apt install php8.1
```

> If you opt for a different version then just replace `8.1` with your version whenever you copy a command.

Add PHP module to Apache server:

```bash
sudo apt install libapache2-mod-php8.1
```

Install the extensions required by Laravel:

```bash
sudo apt install php8.1-mbstring php8.1-xmlrpc php8.1-soap php8.1-gd php8.1-xml php8.1-cli php8.1-zip php8.1-bcmath php8.1-tokenizer php8.1-json php8.1-pear
```

The newly installed extensions will be automatically enabled with their configs placed at `/etc/php/8.1/cli/conf.d/`.

References:

- <https://www.digitalocean.com/community/tutorials/how-to-install-lamp-stack-on-ubuntu#step-3-installing-php>
- <https://www.hostinger.com/tutorials/how-to-install-laravel-on-ubuntu>

## Installing composer

Check <https://getcomposer.org/download/>.

## A new Laravel app

```bash
cd
mkdir dev
cd dev
```

> I like to place my code at `~/dev`.

Create a new Laravel app:

```bash
composer global require laravel/installer
laravel new my_app --git
```

Set the correct permissions to enable Apache to execute your PHP code.

```bash
sudo chown -R www-data:www-data /home/me/dev/my_app
sudo chmod -R 777 /home/me/dev/my_app
sudo chmod o+x /home/me
sudo chmod o+x /home/me/dev
sudo chmod o+x /home/me/dev/
sudo chmod o+x /home/me/dev/my_app
```

Set `.env` with your app and database details.

## Faking a domain name

We will add a domain name for our app that only our machine knows about by editing `/etc/hosts`. We will configure it to let our machine know that the domain name `my_app.local` is on the loopback IP address `127.0.0.1`.

```bash
sudo nano /etc/hosts
```

```ini
# Add this line anywhere
127.0.0.1 my_app.local
```

Test that you configured the domain correctly by pinging it:

```bash
ping my_app.local
```

> Note that using internet top-level domains like `.com` will most likely not work. So I recommend sticking to `.local` for testing locally without HTTPS and without a registered domain name.

## Setting up the virtual host

Now we move to `/etc/apache2/sites-available/` and use as our base virtual host config file:

```bash
cd /etc/apache2/sites-available/
sudo cp 000-default.conf my_app-local.conf
sudo nano my_app-local.conf
```

And edit `my_app-local.conf` to look like this:

```ini
<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 my_app.local   
        ServerAlias www.my_app.local

        ServerAdmin webmaster@localhost
        DocumentRoot /home/me/dev/my_app/public

        <Directory /home/me/dev/my_app/public>
                Options FollowSymLinks MultiViews
                AllowOverride All
                Require all granted
        </Directory>

        ReWriteEngine On

        # 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>
```

Check the validity of the config you added:

```bash
sudo apache2ctl configtest
```

Enable your new site:

```bash
sudo a2ensite my_app-local.conf
```

Also, enable the rewrite module to be able to have URLs that do not point only to real files:

```bash
sudo a2enmod rewrite
```

The final thing to do is restart Apache to reload the new config:

```bash
sudo systemctl restart apache2
// or
sudo systemctl reload apache2
```

References:

- <https://ubuntu.com/tutorials/install-and-configure-apache>

## Finally

Visit `http://my_app.local`.