Recent Posts
Archives
Categories
Deploying Laravel-Vue.JS on AWS EC2 Instance (Ubuntu)
Nowadays, developers don’t only code, they also need knowledge of server configuration, deployment, CI/CD etc. As a Full Stack Developer, I also had to learn some basics of server configuration. In this article I will discuss and mainly write necessary linux commands that I used to configure and deploy my Laravel-Vue.js project. I have divided the whole thing in 12 steps:
Create EC2 Instance
Install Nginx web server
Install PHP
Install Composer
Install Node
Install MySQL
Install PHPMyAdmin
Clone GitHub
Setup Domain/Subdomains and configure nginx
Prepare Laravel Project
Prepare Vuejs Project
Setup SSL
1. Create EC2 Instance
At first lets create EC2 instance for Ubuntu. Also create .pem key pair file while creating instance. Allow ssl, http, https traffic in network settings.
To connect instance from any ssh client, use following command:
ssh -i \"\<filename\>.pem@\<public ip or public dns\>
If public IP doesn’t load in browser, it is better to use elastic ip.
2. Install Nginx web server
sudo apt upgrade
sudo apt install nginx
3. Install PHP
Execute the following commands to a install a few prerequisites and Ondrej PHP repository
software-properties-common
sudo add-apt-repository ppa:ondrej/php
Then install PHP
sudo apt update
sudo apt upgrade
sudo apt install php8.1 -y
Finally install required PHP extensions
sudo apt install php8.1-fpm php8.1-mysql php8.1-mbstring php8.1-xml
php8.1-bcmath php8.1-zip php8.1-curl unzip php8.1-gd
sudo systemctl restart nginx.service
4. Install Composer
Install latest version of composer using curl
curl -sS https://getcomposer.org/installer -o composer-setup.php
sudo php composer-setup.php \--install-dir=/usr/local/bin
\--filename=composer
5. Install Node
Also install latest version of node.js
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh
\| bash
. \~/.nvm/nvm.sh
nvm install \--lts
6. Install MySQL
sudo apt update
sudo apt install mysql-server
Then run mysql command and use following query to change root password
sudo mysql
ALTER USER \'root\'@\'localhost\' IDENTIFIED WITH mysql_native_password BY \'your password\';
7. Install PHPMyAdmin
sudo apt update
sudo apt install phpmyadmin
sudo ln -s /usr/share/phpmyadmin /var/www/html/phpmyadmin
– Check Permissions:
sudo chown -R www-data:www-data /var/www/html/phpmyadmin
sudo chmod -R 755 /var/www/html/phpmyadmin
sudo chown -R www-data:www-data /var/www/html
Add following lines to load phpmyadmin from browser (mydomain.com/phpmyadmin)
cd /etc/nginx/sites-available/
sudo nano default
Add these lines:
location /phpmyadmin {
root /var/www/html;
index index.php index.html index.htm;
location ~ ^/phpmyadmin/(.+\.php)$ {
try_files $uri =404;
root /var/www/html;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
root /var/www/html;
}
}
8. Clone GitHub
At first create SSH key so that github can be used in this server using ssh.
sudo apt update
sudo apt install openssh-client
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub
Use the SSH key in github account. Alternatively you can create a personal access token and use it as password while cloning the app through https. After cloning the app, lets rename the folder as our domain name. It will be easier to identify the folders when we have multiple domains.
cd /var/www/vhosts
sudo git clone \<git url\>
sudo mv \<git folder name\> mydomain.com
sudo chown ubuntu:ubuntu -R mydomain.com
9. Setup Domain and Subdomains and change nginx config
Setup cname, A record for domain name and also create a subdomain for backend using another A record. Eg. backend.mydomain.com. As my project has a backend part that will mainly work as API, I will setup the project (laravel) with this subdomain.
Then in ssh terminal, run these commands
cd /etc/nginx/sites-available/
sudo nano backend
On backend file, paste these lines:
server {
listen 80;
listen [::]:80;
server_name backend.mydomain.com;
root /var/www/vhosts/mydomain.com/backend/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;
}
}
Then run following commands to create symbolic link
cd ../sites-enabled/
sudo ln -s ../sites-available/backend .
ls -l
Also change default so that it loads vuejs frontend
sudo nano default
Change rooth path like this:
root /var/www/vhosts/mydomain.com/frontend/dist;
sudo service nginx restart
10. Prepare Laravel Project
Prepare Laravel project as usual. My github project has two main folders – 1. backend 2. frontend. I kept the Laravel part in backend folder.
cd /var/www/vhosts/mydomain.com/backend
sudo chown www-data:www-data -R storage
sudo chown www-data:www-data -R bootstrap/cache
composer update
Then create .env file and configure as usual. You can also create an empty database using phpmyadmin that we installed earlier.
sudo cp .env.example .env
sudo nano .env
sudo php artisan key:generate
php artisan migrate
11. Prepare Vue.js Project
It is better to build project locally using npm run build or vite build command (if using vite). Compiled files are kept in ‘dist’ folder. I have set nginx root folder path to ‘dist’ folder in step 9 above. It should be enough to load the site.
12. Setup SSL
Finally lets configure SSL. We will use certbot which is free of cost.
sudo snap install core;
sudo snap refresh core
sudo snap install \--classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot \--nginx -d mydomain.com -d www.mydomain.com -d
backend.mydomain.com
We can run certbot timer which will check twice a day and automatically renew the certificate if it is about to expire
sudo systemctl status certbot.timer
We can also simulate the renewal process to see if it works correctly:
sudo certbot renew \--dry-run