Automatic website deployment setup

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    815

Configuring Automatic Website Deployment

Automatic deployment is a process where code changes automatically reach the server after passing CI checks. It eliminates manual operations, reduces human error risk, and accelerates change delivery.

Automatic Deployment Variants

Push-based — the CI/CD system connects to the server and performs deployment itself. Pull-based — the server periodically checks and pulls changes (GitOps approach).

GitHub Actions → SSH Deployment

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build
        run: npm ci && npm run build

      - name: Deploy via SSH
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: deploy
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/myapp
            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
            php artisan queue:restart
            sudo systemctl reload php8.3-fpm

Deployer (PHP)

Deployer is a tool for atomic deployment with rollback capability:

// deploy.php
namespace Deployer;

require 'recipe/laravel.php';

host('production')
    ->set('hostname', 'your-server.com')
    ->set('remote_user', 'deploy')
    ->set('deploy_path', '/var/www/myapp')
    ->set('branch', 'main');

host('staging')
    ->set('hostname', 'staging.example.com')
    ->set('remote_user', 'deploy')
    ->set('deploy_path', '/var/www/staging')
    ->set('branch', 'develop');

set('shared_files', ['.env']);
set('shared_dirs', ['storage']);
set('writable_dirs', ['bootstrap/cache', 'storage']);
set('keep_releases', 5);

after('deploy:failed', 'deploy:unlock');

task('deploy:migrate', function () {
    run('cd {{release_path}} && php artisan migrate --force');
});

after('deploy:vendors', 'deploy:migrate');
# Deploy
dep deploy production

# Rollback
dep rollback production

Webhook Deployment

For simple cases, use a webhook on the server:

// deploy.php (on server)
<?php
$secret = getenv('DEPLOY_SECRET');
$signature = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '';

if (!hash_equals("sha256=" . hash_hmac('sha256', file_get_contents('php://input'), $secret), $signature)) {
    http_response_code(403);
    exit;
}

$output = shell_exec('cd /var/www/myapp && git pull && composer install --no-dev && php artisan migrate --force 2>&1');
echo $output;

GitHub → Repository Settings → Webhooks → Add webhook → URL of your deploy.php.

Zero-Downtime Deployment via Symlink

# Directory structure
/var/www/myapp/
├── current -> releases/20241115143022  # symlink to active release
├── releases/
│   ├── 20241115143022/   # current
│   ├── 20241115120000/   # previous
│   └── 20241114090000/   # old
├── shared/
│   ├── .env
│   └── storage/
#!/bin/bash
# deploy.sh
DEPLOY_DIR=/var/www/myapp
RELEASE_DIR=$DEPLOY_DIR/releases/$(date +%Y%m%d%H%M%S)

# 1. Download new code
git clone --depth=1 https://github.com/user/repo.git $RELEASE_DIR

# 2. Link shared resources
ln -s $DEPLOY_DIR/shared/.env $RELEASE_DIR/.env
ln -s $DEPLOY_DIR/shared/storage $RELEASE_DIR/storage

# 3. Install dependencies
cd $RELEASE_DIR && composer install --no-dev --optimize-autoloader

# 4. Switch symlink (atomic)
ln -sfn $RELEASE_DIR $DEPLOY_DIR/current

# 5. Reload services
sudo systemctl reload php8.3-fpm

# 6. Remove old releases (keep 5)
ls -t $DEPLOY_DIR/releases | tail -n +6 | xargs -I{} rm -rf $DEPLOY_DIR/releases/{}

Deployment Notifications

# GitHub Actions — Slack notification
- name: Notify Slack
  if: always()
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    text: "Deploy to production: ${{ job.status }}"
    webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Implementation Timeline

Basic auto-deployment via SSH/GitHub Actions: 1 day. Deployer with zero-downtime and rollback: 2–3 days.