AWS EC2 for Laravel

User
I want to use aws ec2 only for host laravel website backend
Assistant
Great—EC2 is a solid choice for a Laravel backend. Here’s a clean, no‑nonsense setup path tailored to your stack (Ubuntu 22.04, PHP 8.3, Node 21, folder like `/var/www/share`, Reverb on port 6001).

# Two ways to host
**A) Simple & cheapest (single EC2) — good for MVP/small traffic**
– 1 EC2 (Ubuntu 22.04)
– Nginx + PHP‑FPM
– MySQL/PostgreSQL on the same box (or RDS if you want safety)
– Storage: local EBS (and optionally S3 for user uploads)
– Backups: EBS snapshot + DB dump via cron
– SSL via Let’s Encrypt (or use ALB+ACM later)

**B) More production‑ready (still straightforward)**
– EC2 (Nginx + PHP‑FPM)
– RDS (managed DB)
– S3 (user files) + CloudFront (optional)
– ElastiCache Redis (sessions/queues/cache)
– ALB + ACM for HTTPS termination (optional)
– CloudWatch logs + metrics

# Quick start (Option A: single EC2)
## 0) EC2 & network
– Instance: t4g.small or t3.small (start small; add swap if RAM is tight).
– Disk (gp3): 30–50 GB to start.
– Security Group:
– 22 (SSH) from **your IP only**
– 80 (HTTP) from 0.0.0.0/0
– 443 (HTTPS) from 0.0.0.0/0
– 6001 (Reverb) from 0.0.0.0/0 (or proxy via Nginx—see below)
– Attach an **IAM role** with `AmazonSSMManagedInstanceCore` (for SSM) and (optionally) S3 read/write if you’ll use S3.
– Allocate an **Elastic IP** and attach to the instance.

## 1) Base packages

sudo apt update && sudo apt -y upgrade
# PHP 8.3 (ppa:ondrej/php)
sudo apt -y install software-properties-common
sudo add-apt-repository ppa:ondrej/php -y && sudo apt update
sudo apt -y install nginx php8.3-fpm php8.3-cli php8.3-mbstring php8.3-xml php8.3-curl php8.3-zip php8.3-bcmath php8.3-gd php8.3-intl php8.3-mysql unzip git
# Composer
cd /usr/local/bin && sudo curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
# Node (if you build on server; otherwise build locally and deploy artifacts)
curl -fsSL https://deb.nodesource.com/setup_21.x | sudo -E bash - && sudo apt -y install nodejs

## 2) App directory & deploy

sudo mkdir -p /var/www/share
sudo chown -R ubuntu:www-data /var/www/share
cd /var/www/share
# Option 1: Git pull
git clone <your-repo> . 
# Option 2: Upload build/artifacts (rsync / scp)
composer install --no-dev --prefer-dist --optimize-autoloader
cp .env.example .env  # then edit .env
php artisan key:generate
php artisan migrate --force
php artisan storage:link

**Permissions**

sudo chown -R ubuntu:www-data /var/www/share
sudo find /var/www/share/storage -type d -exec chmod 775 {} ;
sudo find /var/www/share/bootstrap/cache -type d -exec chmod 775 {} ;

## 3) Nginx (Laravel server block)
Create `/etc/nginx/sites-available/laravel`:

map $http_upgrade $connection_upgrade { default upgrade; '' close; }

server {
    listen 80;
    server_name your-domain.com;
    root /var/www/share/public;
    index index.php;

    # Laravel
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP-FPM
    location ~ .php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
    }

    # Static cache (optional small boost)
    location ~* .(?:css|js|jpg|jpeg|png|gif|svg|ico|webp|woff2?)$ {
        expires 7d;
        access_log off;
        add_header Cache-Control "public";
        try_files $uri =404;
    }

    # Reverb (WebSocket proxy to 6001) — avoids opening 6001 to the world
    location /app {
        proxy_pass http://127.0.0.1:6001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
    }
}

Enable & reload:

sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/laravel
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

## 4) HTTPS (Let’s Encrypt)

sudo apt -y install certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com --redirect --agree-tos -m you@domain.com

## 5) Scheduler & queues
**Scheduler (cron):**

crontab -e
# add:
* * * * * cd /var/www/share && /usr/bin/php artisan schedule:run >> /dev/null 2>&1

**Queues** (choose one):
– **Horizon** (recommended):

composer require laravel/horizon
  php artisan horizon:install
  php artisan migrate --force

**Supervisor** config: `/etc/supervisor/conf.d/horizon.conf`

[program:horizon]
  process_name=%(program_name)s
  command=php /var/www/share/artisan horizon
  autostart=true
  autorestart=true
  user=ubuntu
  redirect_stderr=true
  stdout_logfile=/var/log/horizon.log
sudo apt -y install supervisor
  sudo supervisorctl reread && sudo supervisorctl update && sudo supervisorctl start horizon

– **Basic queue worker**:
`/etc/supervisor/conf.d/laravel-worker.conf`

[program:laravel-worker]
  command=php /var/www/share/artisan queue:work --sleep=3 --tries=3 --timeout=120
  autostart=true
  autorestart=true
  user=ubuntu
  redirect_stderr=true
  stdout_logfile=/var/log/laravel-worker.log

## 6) Environment & secrets
– Prefer **AWS Systems Manager Parameter Store** (or Secrets Manager) for DB/API keys.
– Give your EC2 role permission to read parameters.
– Load at deploy time (e.g., write into `.env`) or use a library to fetch on boot.

## 7) Logs & monitoring
– Send Nginx/PHP/Laravel logs to **CloudWatch Logs** (install `amazon-cloudwatch-agent`) or keep local & rotate:

sudo apt -y install logrotate

– Alarms: CPU, disk, status checks via **CloudWatch Alarms**.

## 8) Backups
– **DB**: nightly `mysqldump` (or use RDS automated backups).
– **EBS**: set an **EBS snapshot** Lifecycle Policy (daily, keep N days).

## 9) Optional improvements (easy wins)
– Redis (ElastiCache or local) for `CACHE_DRIVER`, `SESSION_DRIVER`, and queues.
– S3 for `FILESYSTEM_DISK=s3` (offload user uploads).
– CloudFront in front of your assets (esp. if global users).
– Swap file for small instances:

sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile
  sudo mkswap /swapfile && sudo swapon /swapfile
  echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# Minimal deploy/update flow
1. `git pull` (or upload artifact) into `/var/www/share`.
2. `composer install –no-dev –prefer-dist`
3. `php artisan migrate –force`
4. `php artisan optimize` (or `config:cache`, `route:cache`)
5. `sudo systemctl reload nginx`
6. `sudo supervisorctl restart all` (if workers changed)

# If you want the DB off the EC2
– Create **RDS** (MySQL/PostgreSQL), put its **SG** to allow inbound from the **EC2 SG** only.
– Update `.env` `DB_HOST`, `DB_USERNAME`, `DB_PASSWORD`.
– Migrate as usual.

If you share your domain and any special requirements (e.g., need HTTP/2, multiple Laravel sites on one EC2, CI/CD), I’ll hand you exact Nginx blocks and a one‑shot setup script tuned to your box.

Leave a Comment

Your email address will not be published. Required fields are marked *