Skip to content

Instantly share code, notes, and snippets.

@Maxiviper117
Last active July 30, 2025 12:23
Show Gist options
  • Save Maxiviper117/2aa7da73b2089f8abbdc45fdb8f2c6bb to your computer and use it in GitHub Desktop.
Save Maxiviper117/2aa7da73b2089f8abbdc45fdb8f2c6bb to your computer and use it in GitHub Desktop.
HTTPS for `php artisan serve` on WSL2 via Caddy reverse proxy with auto‑trusted certs.

Prerequisites

  • Windows 10/11 with WSL 2 and your Laravel project working under WSL.
  • Chocolatey installed on Windows (for easy Caddy install).
  • A .test (or similar) hostname mapped to 127.0.0.1 (we’ll set that up below).

1. Install Caddy on Windows

Open an elevated PowerShell (Run as Administrator) and install Caddy via Chocolatey:

choco install caddy -y

Caddy comes with automatic HTTPS out of the box and will manage certs for you (Caddy Web Server).


2. Add a hosts entry for your dev domain

Still in Windows, edit your hosts file (C:\Windows\System32\drivers\etc\hosts) and add:

127.0.0.1    laravel.test

This makes https://laravel.test resolve to your local machine.


3. Run Laravel’s built‑in server in WSL

In your WSL shell, from your Laravel project directory:

php artisan serve --host 127.0.0.1 --port 8000

This starts the HTTP server at http://127.0.0.1:8000.


4. Start Caddy as a reverse proxy with internal TLS

Back in Windows PowerShell (no admin needed now), run:

caddy reverse-proxy `
  --from https://laravel.test `
  --to   http://127.0.0.1:8000 `
  --internal-certs
  • --from https://laravel.test → listens on port 443, expects TLS.
  • --to http://127.0.0.1:8000 → proxies decrypted traffic to Laravel.
  • --internal-certs → uses Caddy’s built‑in CA to issue a locally‑trusted cert, automatically added to your Windows trust store (GitHub).

Note

Running caddy like this means that the server will only run as long as the terminal session is alive, ctrl+c will stop the server.


5. Tell Laravel it’s behind HTTPS

In app/Providers/AppServiceProvider.php add under boot():

<?php

namespace App\Providers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        if ($this->app->environment('local')) {
            Request::setTrustedProxies(
                ['127.0.0.1'],
                Request::HEADER_X_FORWARDED_PROTO
            );
            URL::forceScheme('https');
        }
    }
}

Then clear config cache:

php artisan config:clear

This ensures url() and asset() generate https:// links.


6. Verify in your browser

  • Navigate to https://laravel.test.
  • You should see the Laravel welcome page with a valid lock icon—no browser warnings.

(Optional) Persist with a Caddyfile

If you prefer a config file, create a Caddyfile in Windows (e.g. C:\caddy\Caddyfile) with:

https://laravel.test {
    reverse_proxy 127.0.0.1:8000
    tls internal
}

And run:

caddy run --config C:\caddy\Caddyfile

7. Stopping Caddy

If you started Caddy manually in your PowerShell session with:

caddy reverse-proxy --from https://laravel.test --to http://127.0.0.1:8000 --internal-certs

then Caddy is just a foreground process. To stop it:

  • Press Ctrl +C in that same PowerShell window—it sends SIGINT and cleanly shuts Caddy down (Caddy Community).
  • Or simply close the PowerShell window, which also kills the process.

If you instead set Caddy up as a Windows service (e.g. via caddy service install or another wrapper), then it’s running in the background. In that case:

# stop the Caddy service
sc stop caddy
# (or equivalently)
net stop caddy

That frees port 443 and halts the proxy.

Once stopped, https://laravel.test will no longer answer over TLS until you restart Caddy.


Why this works

  1. PHP’s built‑in server (php artisan serve) only speaks HTTP.
  2. Caddy terminates TLS (HTTPS) for you, then forwards requests over HTTP to Laravel.
  3. Automatic certs: Caddy’s internal CA issues and trusts a certificate for laravel.test—no manual mkcert steps required (Caddy Web Server, GitHub).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment