Preparation for Developing Laravel Apps on WSL2

Preparation for Developing Laravel Apps on WSL2
Photo by Mohammad Rahmani / Unsplash

Website development comes with a complexity cost in setting up the right development environment that it ends up taking much of your time from actual development.

While enthusiastic about linux. Windows is still my daily driver due to work. On spare times I would work on my projects discretely at the office. But having linux at home and windows at the office makes me waste time applying dos2linux on all the code that I worked on during the day.

So I tried WAMPServer, XAMPP, laragon and Docker. These are great products. But I prefer to use nginx as opposed to apache2. Docker would have been the best way but due to the complexity and the learning curve I have to ditch it due to my limited time. That's when it hit me that Docker uses WSL2 anyway why not just use WSL2?

So after cleaning up my System. Reinstalled my WSL2 Ubuntu distro. The steps below are what I did to start developing my laravel project on WSL2

Updating the System

sudo apt update && sudo apt upgrade -y  && sudo dist-upgrade -y && do-release-upgrade

Remove apache2

type apache2 >/dev/null 2>&1 && { sudo apt purge apache2 apache2* }

Install php, nginx, mysql

sudo apt install php php php-fpm php-mbstring php-xml php-bcmath nginx mysql-server

Install composer

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

Note: Instructions taken from getcomposer.org

Install nvm, npm, nodejs

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
nvm install --lts

Note: Instructions taken from learn.microsoft.com

Add User to www-data group

sudo usermod -a -G www-data <username>

Create a Laravel project


Directories

Begin by planning your directory structure. Commonly used pattern is to use '~/projects/<project name>' to host the actual project then symbolically linking the directory to '/var/www/html/<project name> then setting the correct owner and permissions.

mkdir -p ~/projects/<project name>
sudo ln -s ~/projects/<project name> /var/www/html/

Note: mkdir -p creates the directory you want including all the parent directories if needed

Check if everything is in order (Optional)

A Udemy instructor Piotr Jura has created a php script to check if your system is ready for Laravel Projects

check.php <- this will take you to a github gist.

Alternatively we can download the file using curl...

https://gist.githubusercontent.com/piotr-jura-udemy/1037a78c7e7cb1074125b453972d2fcf/raw/1fddb5c4072bb536c80224cb6dd2c289646f2434/check.php

Option 1:

mv check.php to temp
touch check.php
echo '#!'"$(which php)" > check.php
echo "$(cat temp)" >> check.php
chmod +x check.php
./check.php

Option 2:

php check.php

Create Project

cd ~/projects/<project name>
composer create-project laravel/laravel .

Change Ownership

sudo chown -R $USER:www-data ~/projects/<project name>

Change Permissions

# set the proper permissions for folders and files
sudo find . -type f -exec chmod 664 {} \;   
sudo find . -type d -exec chmod 775 {} \;

Note: Taken from this stack overflow answer

Create mySQL Database & User

sudo mysql -e "CREATE DATABASE '<database>';"
sudo mysql -e "CREATE USER '<username>' IDENTIFIED by '<password>';"
sudo mysql -e "GRANT ALL PRIVIlEGES on <database>.* TO  '<username>';"

Note: Replace <database>, <username> and <password> to actual values

Modify .env File

Off the shelf a laravel app uses SQLite.

DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=

Excerpt of default .env

cd ~/projects/<project name>
nano .env

Modify the .env file.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<database>
DB_USERNAME=<username>
DB_PASSWORD=<password>

There are other fields on this file that you might want to change like APP_NAME but for our purpose the above is enough for now.

Create/Modify nginx conf

sudo nano /etc/nginx/sites-available/<project name>

Copy and paste below conf. make sure to change those enclosed in angle brackets to correct values. It is also possible to add an entry in your windows host file and use that instead of localhost.

[default]
server {
    listen 80;
    server_name localhost;
    root /var/www/html/<project name>/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.html index.htm index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }

}
[/default]

Once that is created, symbolically link it to sites-enabled...

# do this if using localhost
sudo rm /etc/nginx/sites-enabled/default

sudo ln -s /etc/nginx/sites-available/<project name> /etc/nginx/sites-enabled/<project name>

Bring it Live!

cd ~/projects/<project name>
php artisan migrate

sudo systemctl start nginx
sudo systemctl start mysql

After this step just open a browser and type localhost

Optional:
cd ~/projects/<project name>
code .