How to Deploy Laravel 11/12 on AWS EC2 using GitHub Actions (CI/CD) from a Private Repository
Introduction
Continuous Integration and Continuous Deployment (CI/CD) have become the backbone of modern web development. They automate deployment pipelines, improve reliability, and reduce human errors.
If you’re running a Laravel 11 or Laravel 12 project and want to deploy it to AWS EC2 — using GitHub Actions CI/CD — this step-by-step guide will help you build a fully automated deployment pipeline directly from a private GitHub repository to your AWS server.
You’ll learn how to automatically deploy every code update to production using GitHub Secrets, SSH keys, and AWS EC2 configuration.
What You’ll Learn
Set up EC2 instance for Laravel
Configure GitHub Actions for CI/CD
Use SSH keys securely with a private repository
Automate Laravel deployment via GitHub pipeline
Manage MySQL, .env, and permissions
Test and verify your deployment
Step 1: Set Up Your AWS EC2 Instance
If you don’t already have one, follow these steps to create your AWS server:
- Log in to AWS Console
- Navigate to EC2 → Launch Instance
- Choose Ubuntu 22.04 LTS
- Instance type:
t2.micro(for testing) ort3.medium(for production) - Add storage: 20–30 GB SSD
- Add security group:
- Allow 22 (SSH), 80 (HTTP), 443 (HTTPS)
- Launch instance and download your key pair (
.pemfile)
Connect to the instance:
ssh -i /path/to/key.pem ubuntu@your-ec2-public-ipStep 2: Install Laravel Dependencies on EC2
Update the system and install required packages:
sudo apt update && sudo apt upgrade -y
sudo apt install nginx git unzip curl -yInstall PHP 8.2 (Laravel 11/12 requires PHP 8.2+):
sudo apt install php8.2 php8.2-fpm php8.2-mbstring php8.2-xml php8.2-curl php8.2-zip php8.2-mysql php8.2-bcmath php8.2-cli -yInstall Composer globally:
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composerStep 3: Set Up MySQL Database
Install and secure MySQL:
sudo apt install mysql-server -y
sudo mysql_secure_installationCreate a database and user for Laravel:
sudo mysql -u root -pCREATE DATABASE laravel_ci_cd;
CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'StrongPassword123';
GRANT ALL PRIVILEGES ON laravel_ci_cd.* TO 'laravel_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;Step 4: Prepare SSH Key for GitHub CI/CD Access
On your local machine or EC2 server:
Generate SSH key for GitHub:
ssh-keygen -t ed25519 -C "your-email@example.com"When prompted for file path, you can use:
/home/ubuntu/.ssh/github_ciDisplay the public key:
cat ~/.ssh/github_ci.pubCopy it, then go to your GitHub repository → Settings → Deploy Keys → Add deploy key
Name: EC2 Deploy Key
Paste the key
Check Allow write access
Step 5: Add Secrets to GitHub Repository
Go to your repository → Settings → Secrets and variables → Actions → New repository secret
Add the following secrets:
| Secret Name | Description |
|---|---|
EC2_HOST | Your EC2 public IP or domain |
EC2_USER | Usually ubuntu |
EC2_SSH_KEY | Your private key (paste contents of github_ci file) |
PROJECT_PATH | /var/www/laravel-ci-cd |
⚠️ Make sure your private key is pasted correctly — no line breaks missing.
Step 6: Configure Nginx for Laravel
sudo nano /etc/nginx/sites-available/laravel.confAdd this configuration:
server {
listen 80;
server_name _;
root /var/www/laravel-ci-cd/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}Enable and restart:
sudo ln -s /etc/nginx/sites-available/laravel.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Step 7: Create GitHub Action Workflow
In your GitHub repository, create the file:
.github/workflows/deploy.ymlPaste this workflow:
name: Deploy Laravel to AWS EC2
on:
push:
branches: [ "main" ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
ssh-key: ${{ secrets.EC2_SSH_KEY }}
- name: Deploy to EC2
uses: appleboy/ssh-action@v0.1.10
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
cd ${{ secrets.PROJECT_PATH }}
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
sudo systemctl restart nginxStep 8: Prepare EC2 Project Folder
sudo mkdir -p /var/www/laravel-ci-cd
cd /var/www/laravel-ci-cd
sudo git init
sudo chown -R ubuntu:www-data /var/www/laravel-ci-cdClone once manually to link your repo:
git clone git@github.com:yourusername/your-private-repo.git .Set permissions:
sudo chmod -R 775 storage bootstrap/cacheStep 9: First CI/CD Run
Now push a commit to your main branch.
git add .
git commit -m "CI/CD test deployment"
git push origin mainGitHub Actions will trigger automatically.
Visit your repository → Actions tab → you’ll see “Deploy Laravel to AWS EC2” running.
After success, visit:
http://your-ec2-public-ipYou should see your Laravel app live
Step 10: Secure with SSL (Let’s Encrypt)
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your-domain.com
sudo systemctl enable certbot.timerStep 11: Optional — Add Staging and Production Environments
You can modify your workflow to include staging and production branches:
on:
push:
branches:
- staging
- productionUse different EC2 hosts for each environment by defining:
EC2_HOST_STAGINGEC2_HOST_PRODUCTION
Troubleshooting Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Permission denied (publickey) | Wrong SSH key format | Regenerate with ssh-keygen -t ed25519 |
| Git pull fails | Missing deploy key | Ensure "Allow write access" is checked |
| 500 error | Cache or .env not updated | Run php artisan config:clear |
| Action fails on deploy | Missing secrets | Verify all GitHub secrets exist |
🏁 Final Thoughts
With this CI/CD setup, every time you push to your main branch, GitHub Actions automatically deploys your Laravel 11/12 application to AWS EC2, runs migrations, clears caches, and restarts Nginx — all without manual intervention.
This modern workflow ensures faster delivery, better reliability, and zero downtime deployment for your Laravel applications.
