Back to blog
guides 3 min read

How to Protect a Laravel Application's Source Code

Laravel is one of the most popular frameworks for building self-hosted PHP products — admin panels, SaaS platforms, CRMs, and more. Here's how to protect a Laravel application's source code before shipping it to customers.

What to Protect (and What Not To)

Not every file in a Laravel project needs protection. Here's a practical breakdown:

Protect these:

  • app/Services/ — Your core business logic
  • app/Http/Controllers/ — Request handling and orchestration
  • app/Models/ — Eloquent models with business rules
  • app/Actions/ or app/Jobs/ — Domain-specific operations

Skip these:

  • config/ — Customers need to edit configuration
  • resources/views/ — Blade templates that customers might customize
  • routes/ — Route files that customers might extend
  • database/migrations/ — Need to be readable for troubleshooting
  • public/ — Static assets, no PHP logic

Step 1: Create a CompileLock Project

Sign up at compilelock.com and create a project in the dashboard. Each project gets a unique encryption key — this means different products have different keys, and a license for Product A can't decrypt Product B.

Step 2: Install the CLI

curl -fsSL https://compilelock.com/install.sh | sh
compilelock auth --token="YOUR_API_KEY"

Step 3: Configure Protection

Create a compilelock.json in your Laravel project root:

{
    "project_id": 1,
    "include": [
        "app/Services",
        "app/Http/Controllers",
        "app/Models",
        "app/Actions"
    ],
    "exclude": [
        "app/Http/Controllers/Api/WebhookController.php"
    ],
    "output": "./dist"
}

The exclude array lets you skip specific files — useful for webhook handlers that need to be inspected by payment providers, or controllers that customers should be able to modify.

Step 4: Build the Protected Version

compilelock protect --config=compilelock.json

This creates a dist/ directory with your protected files. Non-PHP files (Blade templates, config, etc.) are copied as-is. PHP files in the include paths are compiled to bytecode and encrypted.

Step 5: Prepare for Distribution

Your distribution package should include:

  • The dist/ output (protected PHP + unmodified non-PHP files)
  • All files not in the include paths (config, views, routes, migrations, etc.)
  • composer.json and composer.lock — so the customer can install dependencies
  • Installation documentation

You do not ship the license file. Each customer gets their own license through your CompileLock dashboard.

Step 6: Customer Installation

On the customer's server:

# 1. Install the CompileLock extension
curl -fsSL https://compilelock.com/install-ext.sh | sh

# 2. Deploy your application normally
composer install --no-dev
php artisan migrate
php artisan config:cache

# 3. First request triggers the activation screen
# Customer enters their license key in the browser

When the customer visits the application for the first time, the CompileLock bootstrap detects that no license file exists and displays an activation screen. The customer enters their license key, the system validates it against your API, and if valid, creates a local license file and starts the application.

Handling Updates

When you release a new version, simply re-run the protection step and distribute the updated files. The customer's existing license continues to work — licenses are tied to the project, not to specific file versions.

CI/CD Integration

You can automate protection in your deployment pipeline:

# In your GitHub Actions / GitLab CI
- name: Protect source
  run: |
    curl -fsSL https://compilelock.com/install.sh | sh
    compilelock auth --token="${{ secrets.COMPILELOCK_TOKEN }}"
    compilelock protect --config=compilelock.json

- name: Package release
  run: |
    tar czf release-v${{ github.ref_name }}.tar.gz dist/
laravel tutorial deployment source-protection

Related articles