Laravel 7 Deployment on Centos7 OCI machine using nginx with free SSL
I recently got a chance to do a small work on a friend’s project and will summarize the secret steps to have a production deployment on Oracle Cloud of a Laravel project on Centos 7 updated 2020.
The project is split into the bellow steps:
- Environment Provisioning
- OCI Configuration
- Network Setup
- Machine creation
- Domain acquisition
- Packages installation
- PHP Installation
- Composer Installation
- GIT
- OCI Configuration
- Database configuration
- Project setup
- cerbot installation
- Laravel project creation
- ngix installation and configuration
Environment Provisioning
OCI Configuration
This is short version of this post
Network Setup
Create a new VCN using the VCN wizard (make sure it not use DNS hostnames)
Machine creation
Create the VM and get the public ip here we will assume the ip is 139.123.22.3
make sure you open the ports on the VM firewall and the the OCI console firewall, the ports we will use are 80,443,3306
Domain acquisition
The very first thing we need is to obtains a domain, you can buy it wherever you want but I personally prefer google domains, it is cheap (about 10USD annually) and they include the data protection for you domain which is very important of the email that you use for the domain registration will fill of spam in no time.
Once you have bought it you should have something like this
from which you can manage the DNS, click it and go to the bottom, there you can add DNS records to connect the VM where your site is hosted to the domain.
Here we will assume the domain is dragon.dev
Insert the below records
Type: A
Name: @
TTL: 1H
Value: 139.123.22.3
Type: CNAME
Name: www
TTL: 1H
Value: dragon.dev
hit save and the DNS should be ready, to make sure it works, from the terminal execute
dig +trace dragon.dev
dig +trace www.dragon.dev
They should return the IP that you assigned above, the change should take a up to 2 days depending on where you bought the domain and their DNS servers, in google domains it takes like 2 minutes.
Packages installation
PHP 7.4 installation
yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum -y install yum-utils
yum-config-manager --enable remi-php74
yum update -y
yum install -y php php-cli
yum install -y php-cli php-fpm php-mysqlnd php-zip php-devel php-gd php-mcrypt php-mbstring php-curl php-xml php-pear php-bcmath php-json php-fpm
Composer install
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
sudo mv composer.phar /usr/local/bin/composer
verify installs
php -v
composer -V
nodejs installation
curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash -
sudo yum install -y nodejs
git installation
yum remove -y git*
yum install -y https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpm
yum install -y git
Database configuration
click here
Project setup
Cerbot Installation
First as root, we need to install cerbot
, which is the utility we will use later to generate the certificates for the domain.
yum install -y install python3-devel gcc augeas-libs openssl-devel libffi-devel \ redhat-rpm-config ca-certificates openssl
cd /home/$USER
git clone https://github.com/certbot/certbot
cd certbot
python tools/venv3.py
source venv3/bin/activate
Learn about testing cerbot
executions here
Laravel project creation
cd /var/www/
composer create-project --prefer-dist "laravel/laravel=~7" dragon.dev
cd dragon.dev
composer install
npm install
cp .env.example .env
add to the .env
the database credentials
APP_KEY=$your key
APP_DEBUG=false
APP_URL=https://dragon.dev
...
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=$database
DB_USERNAME=$user
DB_PASSWORD=$pass
...
run the Laravel migrations
php artisan migrate
chmod -R 777 storage
chmod -R 777 bootstrap/cache
the project was deployed home will be /var/www/dragon.dev
the Laravel public folder will be on /var/www/dragon.dev/public
nginx installation and configuration
yum install -y nginx
The folder configuration will be /etc/nginx
now lets create some folders and files
cd /etc/nginx
mkdir sistes-available
mkdir sistes-enabled
touch sistes-available/dragon.dev.conf
ln -s sistes-available/dragon.dev.conf sistes-enabled
Then modify the file /etc/nginx/nginx.conf
its content should look like this (specially the include
part)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# this is where the configs are located
include /etc/nginx/sites-enabled/*.conf;
php fast cgi configuration
systemctl start php-fpm
systemctl enable php-fpm
Now we need to identify the socket created by the above command, to do so, open
/etc/php-fpm.d/www.conf
if it is not there, you need to locate it using
locate www.conf
Inside, look for listen
listen = 127.0.0.1:9000
This little bastard is where the nginx server will submit the php code, it could also be something like
unix:/run/php/php7.4-fpm.sock;
it depends on the Linux flavor you use, now let’s edit dragon.dev.conf
server {
listen 80;
listen [::]:80 ipv6only=on;
# Log files for Debugging
access_log /var/log/nginx/laravel-access.log;
error_log /var/log/nginx/laravel-error.log;
# Webroot Directory for Laravel project
root /var/www/dragon.dev/public;
index index.php index.html index.htm;
# Your Domain Name
server_name dragon.dev www.dragon.dev;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM Configuration Nginx
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Special attention to the value of fastcgi_pass
this is just a temporary configuration that will allow to access to the domain on port 80
, however, on modern browser this won’t work due to security reasons, this will be used only to allow validate the domain and generate the certificates with cerbot
Now you can start nginx
systemctl restart nginx
Certificates creation
certbot certonly --webroot \
--webroot-path=/var/www/dragon.dev/public \
-d dragon.dev \
-d www.dragon.dev
The expected output should look like
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/dragon.dev/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/dragon.dev/privkey.pem
Your cert will expire on 2020-12-15. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
finally, we need to edit /etc/nginx/sites-available/dragon.dev.conf
to add the TLS
server {
listen 80;
listen [::]:80;
server_name dragon.dev www.dragon.dev;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
root /var/www/dragon.dev/public;
index index.php index.html index.htm;
ssl_certificate "/etc/letsencrypt/live/dragon.dev/fullchain.pem";
ssl_certificate_key "/etc/letsencrypt/live/dragon.dev/privkey.pem";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
server_name dragon.dev www.dragon.dev;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM Configuration Nginx
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
location ~ /.well-known {
allow all;
}
}
Restart nginx
systemctl restart nginx
finally open the browser and enjoy
https://dragon.dev
References
https://stackoverflow.com/questions/40059745/nginx-connect-to-unix-var-run-php7-0-fpm-sock-failed-2-no-such-file-or-dir
https://www.digitalocean.com/community/tutorials/how-to-deploy-a-laravel-application-with-nginx-on-ubuntu-16-04
https://www.linode.com/docs/web-servers/apache/how-to-install-and-configure-fastcgi-and-php-fpm-on-centos-8/
https://certbot.eff.org/docs/contributing.html
https://linux4one.com/how-to-install-laravel-php-framework-with-nginx-on-centos-7