LessonsBuild a Blog → Part 10

Deploy to Production

Laravel
⏱ 30 min read🏗️ ProjectNot completed

Your blog is complete! Now let's deploy it to a real server so the world can read it. We'll cover deployment to both Railway (cheap/easy) and AWS EC2 (production-grade).

Pre-deployment Checklist

Terminal — Final checks
# Run all tests
php artisan test

# Check for any issues
php artisan about

# Optimize for production
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache

# Make sure storage is linked
php artisan storage:link

Option 1: Deploy to Railway (Easiest)

Steps
1. Push code to GitLab/GitHub

2. Go to railway.app → New Project
   → Deploy from GitHub repo

3. Add MySQL database service
   → Railway provides connection string

4. Set environment variables:
   APP_ENV=production
   APP_DEBUG=false
   APP_KEY=(generate with: php artisan key:generate --show)
   DB_CONNECTION=mysql
   DB_HOST=${{MySQL.MYSQL_HOST}}
   DB_PORT=${{MySQL.MYSQL_PORT}}
   DB_DATABASE=${{MySQL.MYSQL_DATABASE}}
   DB_USERNAME=${{MySQL.MYSQL_USER}}
   DB_PASSWORD=${{MySQL.MYSQL_PASSWORD}}

5. Add start command:
   php artisan migrate --force && php artisan serve --host=0.0.0.0 --port=$PORT

Option 2: Deploy to AWS EC2

SSH Commands
# 1. Clone your repo
cd /var/www
sudo git clone https://gitlab.com/yourname/laravel-blog.git html
cd html

# 2. Install dependencies
sudo composer install --optimize-autoloader --no-dev

# 3. Setup environment
sudo cp .env.example .env
sudo nano .env  # Edit with your production values
sudo php artisan key:generate

# 4. Run migrations
sudo php artisan migrate --force
sudo php artisan db:seed --force

# 5. Set permissions
sudo chown -R nginx:nginx /var/www/html
sudo chmod -R 755 /var/www/html/storage
sudo chmod -R 755 /var/www/html/bootstrap/cache

# 6. Create storage link
sudo php artisan storage:link

# 7. Optimize
sudo php artisan config:cache
sudo php artisan route:cache
sudo php artisan view:cache

# 8. Start services
sudo systemctl restart php-fpm nginx

Auto-Deploy Script

deploy.sh
#!/bin/bash
# Save as deploy.sh — run after every update

echo "Deploying Laravel Blog..."

# Pull latest code
git pull origin main

# Install/update dependencies
composer install --optimize-autoloader --no-dev

# Run migrations
php artisan migrate --force

# Clear and rebuild cache
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan queue:restart  # Restart queue workers

# Set permissions
sudo chown -R nginx:nginx storage bootstrap/cache

echo "Deploy complete!"

SEO Setup

resources/views/layouts/app.blade.php (head section)
<!-- Basic SEO -->
<title>@yield('title', config('app.name'))</title>
<meta name="description" content="@yield('description', 'A Laravel blog')" />

<!-- Open Graph (for social sharing) -->
<meta property="og:title" content="@yield('title')" />
<meta property="og:description" content="@yield('description')" />
<meta property="og:image" content="@yield('og_image', asset('images/default.jpg'))" />
<meta property="og:url" content="{{ url()->current() }}" />

<!-- Canonical URL -->
<link rel="canonical" href="{{ url()->current() }}" />

Sitemap for SEO

routes/web.php
<?php
Route::get('/sitemap.xml', function () {
    $posts = Post::published()->latest()->get();
    $categories = Category::all();

    return response()->view('sitemap', compact('posts', 'categories'))
        ->header('Content-Type', 'application/xml');
})->name('sitemap');
🎉
Congratulations! Your blog is complete! You've built a full-stack Laravel application with authentication, admin panel, CRUD, file uploads, comments, search, pagination, and deployment. This is a real production-ready project you can put on your portfolio!
💡
Next steps to improve your blog: Add RSS feed, newsletter subscription, post scheduling, image optimization, Redis caching, and analytics. Each of these is a great learning exercise!
← Previous 🎉 Complete!
💡

Stuck? Need help?

Review the previous lessons or check the Laravel documentation.

Laravel Docs →