Deploying a Laravel AI Project on a VPS

(Apache VirtualHost + SSL + GitHub SSH Setup)

In this guide, we'll launch a subdomain like ai.kitmote.com from scratch.

The structure we will establish:

  • Apache VirtualHost
  • SSL (Let's Encrypt)
  • GitHub SSH deploy
  • Laravel folder structure compatible operation.

1️⃣ Apache VirtualHost Installation

📁 Project directory

First, make sure the project is in the right place:

cd /var/www
mkdir -p ai.kitmote.com
cd ai.kitmote.com

The Laravel project will be here.


📄 Create a VirtualHost file

sudo nano /etc/apache2/sites-available/ai.kitmote.com.conf

Write this inside:

<VirtualHost *:80>
ServerName ai.kitmote.com
ServerAlias www.ai.kitmote.com

DocumentRoot /var/www/ai.kitmote.com/public

<Directory /var/www/ai.kitmote.com/public>
AllowOverride All
Require all granted
</Directory>

ErrorLog ${APACHE_LOG_DIR}/ai_error.log
CustomLog ${APACHE_LOG_DIR}/ai_access.log combined
</VirtualHost>

🔧 Enable Apache modules

sudo a2enmod rewrite

🔗 Activate the site

sudo a2ensite ai.kitmote.com.conf

If it's available, disable it by default:

sudo a2dissite 000 -default .conf

🔄 Apache restart

sudo systemctl restart apache2

✅ Test

From the browser:

http://ai.kitmote.com

It should open if you have Laravel.


2️⃣ SSL Setup (Let's Encrypt)

📦 Certbot setup

sudo apt update
sudo apt install certbot python3-certbot-apache -y

🔐 Get SSL

sudo certbot --apache -d ai.kitmote.com

Questions:

  • Email → Log in
  • Redirect HTTP → Select YES (important)

🔁 Auto-renew control

sudo certbot renew --dry-run

✅ Test

https://ai.kitmote.com

3️⃣ GitHub SSH Key Setup

The most reliable method for production deployment is SSH.


🔑 Generate SSH key

ssh-keygen -t ed25519 -C "server@kitmote"

Enter → Enter → Enter


🔍 Get public key

cat ~/.ssh/id_ed25519
Get all the values in this section.

Copy what comes up.


🔗 Add to GitHub

GitHub →
👉 Settings → SSH and GPG Keys → New SSH Key


🔌 Test

ssh -T git@github.com

Output:

Hi username! You've successfully authenticated

4️⃣ Uploading the Project to the Server

An example .github/workflows/deploy.yml
name: Deploy AI Kitmote

on:
push:
branches:
- master

concurrency:
group: deploy-ai-kitmote-${{ github.ref }}
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: mbstring, xml, ctype, iconv, intl, pdo_mysql, bcmath, zip, curl
tools: composer

- name: Install Composer dependencies
run: composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction --no-progress

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: npm

- name: Install Node dependencies
run: npm ci

- name: Build assets
run: npm run build

- name: Start SSH agent (deploy key)
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.VPS_SSH_KEY }}

- name: Trust VPS host key
env:
VPS_HOST: ${{ secrets.VPS_HOST }}
run: |
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keyscan -H "$VPS_HOST" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts

- name: Rsync project to VPS
env:
VPS_USER: ${{ secrets.VPS_USER }}
VPS_HOST: ${{ secrets.VPS_HOST }}
run: |
export RSYNC_RSH="ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=$HOME/.ssh/known_hosts"
rsync -avz --delete \
--exclude=".git" \
--exclude=".github" \
--exclude=".env" \
--exclude=".env.*" \
--exclude="node_modules" \
--exclude="storage/logs" \
--filter="protect .env" \
--filter="protect .env.*" \
./ "${VPS_USER}@${VPS_HOST}:/var/www/ai.kitmote.com/"

- name: Run deploy commands on VPS
env:
VPS_USER: ${{ secrets.VPS_USER }}
VPS_HOST: ${{ secrets.VPS_HOST }}
run: |
ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile="$HOME/.ssh/known_hosts" \
"${VPS_USER}@${VPS_HOST}" bash -s << 'REMOTE'
set -euo pipefail
cd /var/www/ai.kitmote.com

# storage/framework Git'te yoksa rsync taşımaz; artisan down / view:clear patlar
mkdir -p storage/framework/cache/data
mkdir -p storage/framework/sessions
mkdir -p storage/framework/testing
mkdir -p storage/framework/views
mkdir -p storage/logs
mkdir -p bootstrap/cache

export COMPOSER_ALLOW_SUPERUSER=1

php artisan down || true

composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction --no-progress

php artisan migrate --force
php artisan optimize:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan storage:link || true
php artisan queue:restart || true

chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache

php artisan up
REMOTE
 VPS_HOST = ip adresi

VPS_USER = kullanıcı

VPS_SSH_KEY = cat ~/.ssh/id_ed25519 gelen bütün değer.
Enter these values on GitHub under Repository Settings -> Secrets and Variables -> Action, by clicking the New repository secret button.
After you submit your project with Git, it automatically connects to the GitHub server and performs the installation.
git commit -m "deploy"
git push
Permissions may be requested in this section.

Add public key to authorized_keys

example :

sudo -u kitmotedeploy ssh-keygen -t ed25519 -C “gh-actions@kitmotedeploy” -f /home/kitmote/.ssh/gh_actions -N “”
sudo chown kitmotedeploy:kitmote /home/kitmote/.ssh/authorized_keys
sudo chmod 600 /home/kitmote/.ssh/authorized_keys
sudo chmod 700 /home/kitmote/.ssh


⚠️ Correct permissions

There might be an error with the permissions. Edit the permissions for the user performing the deployment.
sudo chown -R www-data:www-data /var/www/ai.kitmote.com
sudo chmod -R 755 /var/www/ai.kitmote.com

Laravel exclusive:

chmod -R 775 storage bootstrap/cache

5️⃣ Laravel Installation Steps

📦 Addictions

composer install --no-dev --optimize-autoloader

⚙️ ENV

cp .env.example .env
nano .env

🔑 Generate Key

php artisan key:generate

🗄️ Migration

php artisan migrate

⚡ Cache optimization

php artisan config:cache
php artisan route:cache
php artisan view:cache

6️⃣ Production Recommendations

🔥 Queue (optional)

php artisan queue:work

Recommended with a supervisor.


🔍 Log check

tail -f storage/logs/laravel.log

🔄 Post-deployment update

git pull origin main
composer install --no-dev
php artisan migrate --force
PHP Artisan Optimize

7️⃣ Common Mistakes

❌ 403 Forbidden

Is AllowOverride enabled?
Is Apache rewrite active?


❌ 500 Error

.env error
→ storage permissions


❌ 502 / blank page

Is Apache running?

sudo systemctl status apache2

🎯 Result

With this structure:

  • ✅ Domain → VPS connected
  • ✅ Apache → Laravel is running
  • ✅ SSL → active
  • ✅ GitHub → Automatic deployment ready

Keywords: VPS, SSH_KEY, github CI/CD

Comments

Log in or sign up to write a comment
Giriş
Sign Up