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
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
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
Change password and remember it carefully. This password is not the password of your system user, rather it is your postgres admin password.
\password
Install php
Add repository
sudo add-apt-repository ppa:ondrej/php
sudo apt update
Now, run the following command to install latest php,
apt install php -y
Verify PHP version
php -v
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
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
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;
}
}
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)
Why all this when there are docker containers?
You are absolutely right. But in some cases this tutorial might be helpful for someone.