Check PHP Version (both cases)
Every Laravel distrubution has a compatible PHP version, so you need to check your PHP version before installing Laravel. Run the below command:
root@mail:~# php -v
You can see all PHP’s your server has by running this command:
root@mail:~# update-alternatives –config php
If Laravel distrubition is 5.x to 8.x, you need to go for PHP7.4. For distributions >= 9.x, you need to go for PHP >=8.0. You can check Laravel documentation by clicking here. You can refer to Install PHP on Ubuntu article.
Install The Required PHP Extensions (both cases)
After installing the compatible PHP version, we need to install MySQL extension by running the command:
root@mail:~# apt install php7.4-mysql
Also, if your website deals with images, we need to install the PHP GD extension by running the command:
root@mail:~# apt install php7.4-gd
Laravel will need some PHP extensions like below:
openssl
PDO
mbstring
tokenizer
xml
ctype
json
So check your server by running the command:
root@mail:~# php -m
If they’re not installed, you can install them by running:
root@mail:~# apt install openssl PDO mbstring tokenizer xml ctype json
Once you finish the installation, remove the repository we added to install PHP and its extensions by running the command below. Notice that after removing it, when you run apt-upgrade, it will not offer you to upgrade to a higher PHP veresion. So this way you can upgrade the PHP manually whenever you want.
root@mail:~# add-apt-repository ppa:ondrej/php --remove
Case 1: Start a New Laravel Project
Install Laravel Composer
Enter tmp
directory first:
root@mail:~# cd /tmp
Run the below command:
root@mail:/tmp# curl -sS https://getcomposer.org/installer | php
Move the composer to bin
directory
root@mail:/tmp# mv composer.phar /usr/local/bin/composer
Launch Your Project
Enter the html directory by running the command:
root@mail:~# cd /var/www/html
If you want to install the latest version of Laravel, run the below command:
root@mail:/var/www/html# composer create-project --prefer-dist laravel/laravel my-laravel-project
If you want to install a previous distribution, let’s say 5.5.*, run this command:
root@mail:/var/www/html# composer create-project laravel/laravel="5.5.*" my-laravel-project
You will get the below prompt, type “y”, then hit enter key.
Continue as root/super user [yes]?
Once the installation is done, you will get something like this:
83 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force
INFO No publishable resources for tag [laravel-assets].
No security vulnerability advisories found.
> @php artisan key:generate --ansi
INFO Application key set successfully.
To see Laravel distrubution in the installed project, just open the composer file inside the project by running the command:
root@mail:~# nano /var/www/html/my-laravel-project/composer.json
You will see it like this:
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=7.0.0",
"fideloper/proxy": "~3.3",
"laravel/framework": "5.5.*",
"laravel/tinker": "~1.0"
},
.
.
.
If you install the latest version, you will get something like this:
{
"name": "laravel/laravel",
"type": "project",
"description": "The skeleton application for the Laravel framework.",
"keywords": ["laravel", "framework"],
"license": "MIT",
"require": {
"php": "^8.1",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.3",
"laravel/tinker": "^2.8"
},
.
.
.
Alternatively, you can enter the project directory and run the below command to find the exact distribution:
root@mail:/var/www/html/vpsprof# php artisan --version
This is the response:
Laravel Framework 10.38.1
Manage Database Files (Database Migration)
Laravel offers creating a database structure for all database tables in PHP files. So these PHP files that have the database structure of the tables called database migrations. To find the database migrations, go to this directory:
root@mail:~# ls /var/www/html/my-laravel-project/database/migrations/
The result is like this for a new project created in 2023:
2014_10_12_000000_create_users_table.php 2019_08_19_000000_create_failed_jobs_table.php
2014_10_12_100000_create_password_reset_tokens_table.php 2019_12_14_000001_create_personal_access_tokens_table.php
So anytime you want to create tables in the database, you just need a simple command.
But before that, we need to create a database and user for our new project. Follow this guide here: Create New MySQL Database.
After that enter the database info in the .env hidden file. Open the file:
root@mail:/var/www/html/my-laravel-project# nano .env
Enter the value of your database variables as seen below.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_laravel_project_db
DB_USERNAME=my_laravel_project_user
DB_PASSWORD=12345678
Note that MySQL doesn’t accept dashes in database name but it’s allowed in the database usernam.
Now, it’s the time to deploy the database tables. Run this comand:
root@mail:/var/www/html/my-laravel-project# php artisan migrate
You will see a result like below:
root@mail:/var/www/html/my-laravel-project# php artisan migrate
INFO Preparing database.
Creating migration table ..................................................................................... 11ms DONE
INFO Running migrations.
2014_10_12_000000_create_users_table ......................................................................... 10ms DONE
2014_10_12_100000_create_password_reset_tokens_table .......................................................... 3ms DONE
2019_08_19_000000_create_failed_jobs_table .................................................................... 8ms DONE
2019_12_14_000001_create_personal_access_tokens_table ........................................................ 11ms DONE
Create Your Own Database File (Database Migration)
We will make a database migration for posts table. The database migration name (php file) is: migrate_posts
and the database table name is posts
. Run this command inside the project directory:
root@mail:/var/www/html/my-laravel-project# php artisan make:migration migrate_posts --create=posts
The result will be like below:
root@mail:/var/www/html/my-laravel-project# php artisan make:migration migrate_posts --create=posts
INFO Migration [database/migrations/2023_12_21_130810_migrate_posts.php] created successfully.
Let’s open the database migration file by running the command:
root@mail:/var/www/html/my-laravel-project# nano database/migrations/2023_12_21_130810_migrate_posts.php
Here’s the default content:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->increments('id');
$table->text('body');
$table->string('tag_ids');
$table->string('country');
$table->string('city');
$table->string('ip');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Here’s the file after editing. I commented two lines.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
//$table->id();
//$table->timestamps();
$table->increments('id');
$table->text('body');
$table->string('tag_ids');
$table->string('country');
$table->string('city');
$table->string('ip');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
This file has connection with the pre-existing users table. So let’s edit the table users and open the file as below:
root@mail:/var/www/html/my-laravel-project# nano database/migrations/2014_10_12_000000_create_users_table.php
And here’s the updated content:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
//$table->id();
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
}
};
Now, let’s publish/create the tables (or call it migrate the database) by running the command:
root@mail:/var/www/html/my-laravel-project# php artisan migrate
It’s successful. We will get like this:
root@mail:/var/www/html/my-laravel-project# php artisan migrate
INFO Running migrations.
2014_10_12_000000_create_users_table ......................................................................... 16ms DONE
2014_10_12_100000_create_password_reset_tokens_table .......................................................... 3ms DONE
2019_08_19_000000_create_failed_jobs_table .................................................................... 8ms DONE
2019_12_14_000001_create_personal_access_tokens_table ........................................................ 12ms DONE
2023_12_21_130810_migrate_posts ............................................................................... 9ms DONE
MySQL database will have the new tables as below:
MariaDB [my_laravel_project_db]> show tables;
+---------------------------------+
| Tables_in_my_laravel_project_db |
+---------------------------------+
| failed_jobs |
| migrations |
| password_reset_tokens |
| personal_access_tokens |
| posts |
| users |
+---------------------------------+
6 rows in set (0.002 sec)
When you start your new project, if there are existing tables and you want to drop them and avoid the error (tables already exist), run the below command:
root@mail:/var/www/html/my-laravel-project# php artisan migrate:fresh
To rollback the migration, run this command. It will drop all the migrated tables in the database.
root@mail:/var/www/html/my-laravel-project# php artisan migrate:rollback
You will see such results:
root@mail:/var/www/html/my-laravel-project# php artisan migrate:rollback
INFO Rolling back migrations.
2023_12_21_130810_migrate_posts .............................................................................. 11ms DONE
2019_12_14_000001_create_personal_access_tokens_table ......................................................... 3ms DONE
2019_08_19_000000_create_failed_jobs_table .................................................................... 2ms DONE
2014_10_12_100000_create_password_reset_tokens_table .......................................................... 3ms DONE
2014_10_12_000000_create_users_table .......................................................................... 3ms DONE
MySQL database will look like this:
MariaDB [my_laravel_project_db]> show tables;
+---------------------------------+
| Tables_in_my_laravel_project_db |
+---------------------------------+
| migrations |
+---------------------------------+
1 row in set (0.002 sec)
You can rollback one step by running this command:
root@mail:/var/www/html/my-laravel-project# php artisan migrate:rollback --step=1
If you run this command after migrating all tables, itwill rollback the last table as below:
root@mail:/var/www/html/my-laravel-project# php artisan migrate:rollback --step=1
INFO Rolling back migrations.
2023_12_21_130810_migrate_posts ............................................................................... 8ms DONE
Case 2: Run a Pre-existing Laravel Project
If you will migrate a Laravel project from one server to another, you don’t need to install the composer. Just do it as if it’s a normal website.
First, you need to make sure that the PHP version on your server is compatible with Laravel distribution. You can check that by going to the file:
root@mail:~# nano /var/www/html/my-laravel-project/composer.json
For example, if the version is 5.x, the compatible PHP version is 7.4. if iRedMail doesn’t use the version 7.4, you need to install PHP7.4. You can refer to Install PHP on Ubuntu article.
Import the Database
You need to create a database and user for the website. Refer to Create New MySQL Database article.
Make sure to import the database of the website you want to migrate by running this command.
root@mail:~# mysql -u my_laravel_project_user -p my_laravel_project_db < /var/www/html/my-laravel-project/my_laravel_project_db.sql
And you need to have the site files too.
Manage Permissions (both cases)
Run the below commands:
root@mail:~# chown -R www-data:www-data /var/www/html/my-laravel-project
root@mail:~# chmod -R 755 /var/www/html/my-laravel-project
root@mail:~# find /var/www/html/my-laravel-project-type f -exec chmod 664 {} \;
We already explained this part in this article: Download WordPress and Get it Ready for Installation
Nginx Virtual Hosts (for both cases)
First, we need to generate the certificate, as below:
root@mail:~# certbot --nginx certonly -d vpsprof.com
You can refer to the article to learn more: Nginx Virtual Hosts Configuration.
Open a virtual hosts file as below:
root@mail:~# nano /etc/nginx/sites-available/vpsprof.com.conf
If iRedMail Doesn’t Use the Compatible PHP version
If iRedMail doesn’t use the same PHP version which is compatible with Laravel distribution, enter this code:
# HTTP
server {
server_name vpsprof.com www.vpsprof.com;
# Redirect http://www.site to https://site
if ($host = www.vpsprof.com) {
return 301 https://$host$request_uri;
}
# Redirect http://site to https://site
if ($host = vpsprof.com) {
return 301 https://$host$request_uri;
}
# Redirect all insecure http:// requests to https://
return 301 https://$host$request_uri;
}
# HTTPS
server {
# ipv4 with http2
## For Nginx version < 1.25.1
listen 443 ssl http2;
## For Nginx version >= 1.25.1
#listen 443 ssl;
#http2 on;
# ipv6 with http2
#listen [::]:443 ssl http2;
# SSL Certificate
ssl_certificate /etc/letsencrypt/live/vpsprof.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vpsprof.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Website URL and Directory
server_name vpsprof.com www.vpsprof.com;
root /var/www/html/my-laravel-project/public;
index index.php index.html;
# Connect Nginx to PHP
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Don't allow pages to be rendered in an iframe on external domains.
add_header X-Frame-Options "SAMEORIGIN";
# MIME sniffing prevention
add_header X-Content-Type-Options "nosniff";
# Enable cross-site scripting filter in supported browsers.
add_header X-Xss-Protection "1; mode=block";
# Prevent access to hidden files
location ~* /\.(?!well-known\/) {
deny all;
}
# Prevent access to certain file extensions
location ~\.(ini|log|conf)$ {
deny all;
}
# Enable WordPress Permanent Links
# If we don’t add the below, website directories will get 404 error (like: site/admin or site/sample-page)
location / {
try_files $uri $uri/ /index.php?$args;
}
}
Note that the root directory for Laravel, should end up with public directory like this: /var/www/html/vpsprof/public
If iRedMail Uses the Compatible PHP version
If iRedMail is using the compatible PHP version, you need to enter this code:
# HTTP
server {
server_name vpsprof.com www.vpsprof.com;
# Redirect http://www.site to https://site
if ($host = www.vpsprof.com) {
return 301 https://$host$request_uri;
}
# Redirect http://site to https://site
if ($host = vpsprof.com) {
return 301 https://$host$request_uri;
}
# Redirect all insecure http:// requests to https://
return 301 https://$host$request_uri;
}
# HTTPS
server {
# ipv4 with http2
## For Nginx version < 1.25.1
listen 443 ssl http2;
## For Nginx version >= 1.25.1
#listen 443 ssl;
#http2 on;
# ipv6 with http2
#listen [::]:443 ssl http2;
# SSL Certificate
ssl_certificate /etc/letsencrypt/live/vpsprof.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vpsprof.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Website URL and Directory
server_name vpsprof.com www.vpsprof.com;
root /var/www/html/my-laravel-project/public;
index index.php index.html;
## Below are iRedMail included
#include /etc/nginx/templates/misc.tmpl;
#include /etc/nginx/templates/ssl.tmpl;
#include /etc/nginx/templates/iredadmin.tmpl;
#include /etc/nginx/templates/roundcube.tmpl;
#include /etc/nginx/templates/sogo.tmpl;
#include /etc/nginx/templates/netdata.tmpl;
# Connect Nginx to PHP
include /etc/nginx/templates/php-catchall.tmpl;
#include /etc/nginx/templates/stub_status.tmpl;
# Don't allow pages to be rendered in an iframe on external domains.
add_header X-Frame-Options "SAMEORIGIN";
# MIME sniffing prevention
add_header X-Content-Type-Options "nosniff";
# Enable cross-site scripting filter in supported browsers.
add_header X-Xss-Protection "1; mode=block";
# Prevent access to hidden files
location ~* /\.(?!well-known\/) {
deny all;
}
# Prevent access to certain file extensions
location ~\.(ini|log|conf)$ {
deny all;
}
# Enable WordPress Permanent Links
# If we don’t add the below, website directories will get 404 error (like: site/admin or site/sample-page)
location / {
try_files $uri $uri/ /index.php?$args;
}
}
Make symbolic link between the virtual host in sites-available directory and sites-enabled directory by running the command:
root@mail:~# ln -s /etc/nginx/sites-available/vpsprof.com.conf /etc/nginx/sites-enabled
Let’s make sure that Nginx has no problems by running the below command:
root@mail:~# nginx -t
4. In case no errors appear, restart Nginx by running the command for the changes to take effect.
root@mail:~# service nginx restart
Now, you can check your website by clicking here: https://vpsprof.com