2025/12/27

Setting Up Trusted SSL for Laravel Sail and Docker Environments

平常在本機開發時對應的通常是 http,但如果某些特殊原因,想要使用 https 的話,沒有憑證會看到令人礙眼的警告內容,今天紀錄一下怎麼可以在本地使用自簽憑證讓討厭的 ssl 警告消失,有兩種我目前開發的常用情境:

  1. 用 docker 自架 php + nginx
  2. 使用 laravel sail

安裝使用 mkcert

1. 安裝 mkcert

我們使用 Scoop 作為 Windows 的套件管理工具,打開 PowerShell,執行以下指令:

scoop install mkcert

2. 建立本地 CA (憑證授權單位)

這一步最為關鍵,它會讓你的 Windows 系統信任由 mkcert 簽發的憑證:

mkcert -install

注意:若彈出安全性警告,請點擊「是」。

套用自簽憑證

自架範例

1. 專案結構

.
├── docker/
│   ├── conf.d/
│   │   └── default.conf  # Nginx 設定
│   └── ssl/              # 存放 mkcert 憑證
├── public/
│   └── index.php             # 測試檔案
└── compose.yml           # Docker 配置

2. 產生憑證

# 建立目錄
mkdir -p docker/nginx/ssl

# 使用 mkcert 生成針對 demo.test 的憑證
# 檔案會直接產生在 docker/nginx/ssl 內
cd docker/nginx/ssl
mkcert demo.test

3. default.conf 配置

server {
    listen 80;
    server_name demo.test;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name demo.test;

    ssl_certificate /etc/nginx/ssl/demo.test.pem;
    ssl_certificate_key /etc/nginx/ssl/demo.test-key.pem;

    root /var/www/html/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

4. compose.yml

services:
  php:
    image: php:8.4-fpm
    volumes:
      - .:/var/www/html

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - .:/var/www/html
      - ./docker/conf.d:/etc/nginx/conf.d
      - ./docker/nginx/ssl:/etc/nginx/ssl
    depends_on:
      - php

sail 範例

1. 生成專屬憑證

切換到你的 Laravel 專案根目錄,建立存放憑證的資料夾並產生檔案:

mkdir -p docker/ssl
cd docker/ssl
mkcert demo.test

2. 配置 Docker 環境

我們將使用 Caddy 作為反向代理伺服器。
修改 docker-compose.yml
找到 services 區塊,加入 caddy 服務,並調整 laravel.test 的埠號對應:

services:
    laravel.test:
        # ... (其餘配置保持不變)
        ports:
            - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' # 移除 80 埠映射,改由 Caddy 處理
        networks:
            - sail

    caddy:
        image: caddy:latest
        restart: unless-stopped
        ports:
            - "80:80"
            - "443:443"
        volumes:
            - ./Caddyfile:/etc/caddy/Caddyfile
            - ./docker/ssl:/etc/caddy/certs
            - sail-caddy-data:/data
            - sail-caddy-config:/config
        networks:
            - sail
        depends_on:
            - laravel.test

# 記得在最下方的 volumes 區塊新增
volumes:
    sail-caddy-data:
        driver: local
    sail-caddy-config:
        driver: local

3. 建立 Caddyfile

在專案根目錄建立 Caddyfile

demo.test {
    reverse_proxy laravel.test:80
    tls /etc/caddy/certs/demo.test.pem /etc/caddy/certs/demo.test-key.pem
}

4. 調整應用程式設定

1. 更新 .env

確保 Laravel 知道目前的通訊協定:

APP_URL=https://demo.test
2. 讓 Laravel 信任 Proxy

修改 bootstrap/app.php,讓 route() 函式能正確生成 https 連結:

->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(at: '*');
})
3. 配置 Vite (若有使用)

修改 vite.config.js 以支援 HMR (熱重載) 透過 HTTPS 運作:

import fs from 'fs';

export default defineConfig({
    server: {
        host: '0.0.0.0',
        hmr: { host: 'demo.test' },
        https: {
            key: fs.readFileSync('./docker/ssl/demo.test-key.pem'),
            cert: fs.readFileSync('./docker/ssl/demo.test.pem'),
        },
    },
    // ...
});

沒有留言: