DEV Community

Narayan Adhikary
Narayan Adhikary

Posted on • Edited on

Laravel Dev Environment in Linux

This article guides you through installing and configuring Nginx for local development on Linux. It covers installing Nginx, PostgreSQL, PHP, and Laravel's required extensions. Additionally, it explains configuring Nginx for multiple domains and subdomains using virtual hosts.

Install nginx

sudo apt update
sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode

Verify Nginx installation:

Open your browser and navigate to http://localhost. You should see the Nginx welcome page. But if your distro comes with apache2 pre-installed you should see the welcome page of apache2. No, worries we will fix that later.

Install Postgresql

See details here

# Create the file repository configuration:
sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

# Import the repository signing key:
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

# Update the package lists:
sudo apt-get update

# Install the latest version of PostgreSQL.
# If you want a specific version, use 'postgresql-12' or similar instead of 'postgresql':
sudo apt-get -y install postgresql
Enter fullscreen mode Exit fullscreen mode

After successful Installation, open terminal and do the following:

Switch to postgresql console. It will ask for sudo (super user password)

sudo -u postgres psql
Enter fullscreen mode Exit fullscreen mode

Change password and remember it carefully. This password is not the password of your system user, rather it is your postgres admin password.

\password
Enter fullscreen mode Exit fullscreen mode

Install php

Add repository

sudo add-apt-repository ppa:ondrej/php
sudo apt update
Enter fullscreen mode Exit fullscreen mode

Now, run the following command to install latest php,

apt install php -y
Enter fullscreen mode Exit fullscreen mode

Verify PHP version

php -v
Enter fullscreen mode Exit fullscreen mode

If it shows the php version, then it is installed successfully.

Install Laravel required php extensions

sudo apt install php-ctype php-curl php-xml php-fileinfo php-mbstring php-pdo php-tokenizer php-session php-hash php-dom php-filter php-pgsql
Enter fullscreen mode Exit fullscreen mode

Now, as you have nginx installed, you might not need apache. So, it can be removed from your system by following the
below method:

sudo service apache2 stop
sudo apt-get purge apache2 apache2-utils apache2.2-bin apache2-common
sudo apt-get autoremove
Enter fullscreen mode Exit fullscreen mode

Our required components are installed. Now, its time for configuration.

In https://laravel.com/docs/10.x/deployment#nginx Laravel provided a basic nginx configuration to run laravel projects. But for most of the cases its perfectly fine.

server {
    listen 80;
    listen [::]:80;
    server_name example.com;
    root /srv/example.com/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index 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.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

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

You can make this configuration file for each sites, or this can be
like https://serverfault.com/questions/623327/configuring-multiple-domain-in-nginx-in-one-file.
Anyway, I am not going for that, you can try it if you like.

Domain and Subdomains for Local Development

Before further discussion, lets know about the mechanism. First, when you visit a website by using a domain, the OS
looks up for the IP in DNS cache, then it visits the website by IP after resolving it.

To, access websites hosted locally by local domains or subdomains, we need to tell the OS how to handle it. This is done
by vhosts. The configuration for vhosts is at `/etc/hosts. If you see the contents you will find something like this:

127.0.0.1   localhost
127.0.0.1   local1.test
127.0.0.1   local2.test
127.0.0.1   subdomain.local2.test
127.0.1.1   wovosoft

See the top-most loop back ip 127.0.0.1 and 127.0.1.1. Each line is paired with IP and domain name. The lines instructs the OS to forward all the requests for local1.test, local2.test and localhost to the same IP address 127.0.0.1 on port 80. Now the question is how, the server will know, for which domain which application should handle the request? Well, this is determined by server applications like apache or nginx. Here we will go for nginx.

Now, reconsider the above nginx configuration provided by laravel. We, can use that sample to instruct nginx how to
handle the request for different domains or sub-domains.

Configuration for local1.test

server {
    listen 80;
    listen [::]:80;
    server_name local1.test;
    root /home/your_username/sites/local1/public;
 
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
 
    index 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.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
 
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Configuration for local2.test

server {
    listen 80;
    listen [::]:80;
    server_name local2.test;
    root /home/your_username/sites/local2/public;
 
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
 
    index 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.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
 
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

So, if you look carefully, you will understand that for local domains, all requests are forwarded to 127.0.0.1 at port
80 by using /etc/hosts configuration file. You need to append a line for each local websites in that file. After that you need to make the configuration files.

Storing and instructing nginx to use configuration files

By default, nginx stores configuration files in /etc/nginx/sites-available and /etc/nginx/sites-enabled. And enables the sites by creating a symlink in /etc/nginx/sites-enabled to the configuration file in /etc/nginx/sites-available.

sudo ln -s /etc/nginx/sites-available/your_config_file.conf /etc/nginx/sites-enabled

But managing this procedure every time in local development is a bit of hassle. So, we will use a different approach.
We, will create folder outside the hidden area. For example /home/your_username/nginx/domains
or /home/your_username/nginx/sites-enabled anything else that is easily accessible by you.

Next, open the nginx configuration file at /etc/nginx/nginx.conf and add the following line in the http block.

include /home/your_username/nginx/domains/*;

If you want to use /home/your_username/nginx/sites-enabled then add the following line in the http block.

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    gzip on;
    gzip_disable "msie6";
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_proxied any;
    gzip_vary on;

    gzip_types
    application/atom+xml
    application/javascript
    application/json
    application/rss+xml
    application/vnd.ms-fontobject
    application/x-font-ttf
    application/x-web-app-manifest+json
    application/xhtml+xml
    application/xml
    font/opentype
    image/svg+xml
    image/x-icon
    text/css
    text/plain
    text/x-component;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    #PUT IT HERE
    include /home/your_username/nginx/sites-enabled/*;
}

And if you want the configuration files to have .conf extension, then add the following line in the http block.
Actually, this is a good practice, and it can give you some idea about the file type.

include /home/your_username/nginx/domains/*.conf;

Now, do the same for /etc/hosts file. Add the following line at the bottom of the file.

#include "/home/your_username/hosts/custom.conf"

This custom.conf file is easily editable and accessible. So, you can add or remove domains or subdomains easily.

Notable points

After applying all previous configurations, sometimes you may get errors about laravel.log file cannot be opened in append mode, or bootstrap/cache is not accessible. This happens because of current users or www-data users permission access. To fix this follow the next steps:

Never set a directory to 777. you should change directory ownership. so set your current user that you are logged in with as owner and the webserver user (www-data, apache, ...) as the group. You can try this:

sudo chown -R $USER:www-data storage
sudo chown -R $USER:www-data bootstrap/cache

then to set directory permission try this:

chmod -R 775 storage
chmod -R 775 bootstrap/cache

See more about this configuration at:https://stackoverflow.com/a/45673457

** Happy Coding **

Top comments (2)

Collapse
 
sergonie profile image
Sergonie

Why all this when there are docker containers?

Collapse
 
wovosoft profile image
Narayan Adhikary

You are absolutely right. But in some cases this tutorial might be helpful for someone.