Frank serves your Laravel app over HTTPS by default using locally-trusted certificates generated by mkcert.
frank generate(also called byfrank newandfrank setup) runsmkcert localhost 127.0.0.1 ::1- Certificates are written to
.frank/certs/(gitignored automatically) - The web server (Caddy or nginx) terminates TLS using these certificates
- Port 80 redirects to HTTPS (unless a custom port is configured)
Both runtimes support HTTPS:
- FrankenPHP — Caddy handles TLS natively on port 443
- FPM — nginx terminates TLS on port 443, proxies to PHP-FPM
Install mkcert and trust its root CA:
# macOS
brew install mkcert
mkcert -install
# Linux (Fedora/Ubuntu)
sudo dnf install mkcert # or: sudo apt install mkcert
mkcert -install
# Windows
choco install mkcert
mkcert -installmkcert -install adds the CA to your system/browser trust store. Without this step, browsers will show a security warning.
HTTPS is enabled by default. To disable it:
# frank.yaml
server:
https: falseTo use a custom port:
server:
port: 4433With a custom port, the HTTP→HTTPS redirect is suppressed (only the single HTTPS port is mapped).
When running pnpm dev (or npm run dev) with HTTPS enabled, Vite must serve its assets over TLS too — otherwise the browser blocks them as mixed content.
Frank generates .frank/vite-server.js with the correct TLS configuration. Import it in your vite.config.js or vite.config.ts:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import frankServer from './.frank/vite-server.js';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
server: frankServer,
});Why this is needed: Vite must serve over TLS to avoid mixed content errors when your app runs on HTTPS. The generated .frank/vite-server.js configures Vite to use the same mkcert certificates as the web server, bind to 0.0.0.0 (required for Docker port mapping), and set the correct origin so Laravel's @vite Blade directive generates https:// URLs.
When HTTPS is disabled, .frank/vite-server.js exports a minimal config (host: '0.0.0.0' only), so the import works regardless of HTTPS mode.
Note: This is only relevant during development with
pnpm dev. Production builds (pre-compiled assets) work without any Vite configuration.
When creating a new project, pass --http:
frank new myapp --httpFor existing projects, set server.https: false in frank.yaml and regenerate:
frank generate
frank up -- --buildThe app will be served on http://localhost (port 80).
Browser shows "certificate not trusted"
Run mkcert -install to add the CA to your trust store, then restart your browser.
mkcert not found
Install mkcert (see Prerequisites above). Frank will skip cert generation and warn you. The app still runs but without HTTPS.
Vite assets blocked (mixed content)
Add the server block to your Vite config as shown above. Restart pnpm dev after editing.
"SSL_ERROR_INTERNAL_ERROR_ALERT" after upgrading to HTTPS The Docker image has a stale Caddyfile/nginx config baked in. Rebuild:
frank up -- --build