Tất cả bài viết
HTTPSmkcertlocal developmentlocalhost tunneling

HTTPS trên localhost: mkcert vs tunnel, so sánh thẳng thắn

Hai công cụ, một vấn đề: máy chủ dev của bạn cần tiếp cận được qua HTTPS. mkcert cho bạn một chứng chỉ TLS được tin cậy cục bộ để https://localhost:3000 chạy ngay. Một tunnel cho bạn một URL HTTPS công khai được hậu thuẫn bởi chứng chỉ thật từ một CA thật. Chúng không phải đối thủ — giải quyết các vấn đề khác nhau — nhưng người ta cứ coi như vậy.

Câu trả lời ngắn

  • Chỉ cần HTTPS trên máy của bạn, cho trình duyệt của bạn? Dùng mkcert.
  • Cần một dịch vụ bên ngoài (Stripe, GitHub, Auth0, một điện thoại) tiếp cận máy chủ dev? Dùng tunnel.
  • Cả hai? Chạy cả hai. Chúng không xung đột.

Đó là cả bài viết trong ba gạch đầu dòng. Phần còn lại chỉ là lý do.

mkcert: chứng chỉ tin cậy cục bộ trong 30 giây

mkcert cài một tổ chức cấp chứng chỉ cục bộ vào kho tin cậy của hệ điều hành và phát chứng chỉ từ đó. Trình duyệt thấy chứng chỉ là đáng tin vì CA đáng tin. Không cảnh báo kết nối của bạn không riêng tư, không cờ --ignore-certificate-errors, không tự tay tạo chứng chỉ tự ký.

# một lần mỗi máy
mkcert -install

# một lần mỗi dự án
mkcert localhost 127.0.0.1

# giờ bạn có localhost.pem và localhost-key.pem

Gắn chúng vào máy chủ dev (Vite, Next.js, Express, Django runserver_plus đều hỗ trợ tham số TLS) và bạn có https://localhost:3000 với chứng chỉ thật.

Điểm vướng: chỉ máy của bạn tin CA đó. Trình duyệt của đồng nghiệp sẽ cảnh báo. Điện thoại của bạn sẽ không tin nếu không tự cài gốc CA.

Tunnel: HTTPS thật, URL công khai thật

Một tunnel localhost chuyển tiếp lưu lượng từ một URL HTTPS công khai tới cổng cục bộ của bạn. Chứng chỉ do một CA thật (Let's Encrypt hoặc tương tự) phát và mọi trình duyệt trên mọi thiết bị đều tin.

npx portpreview 3000

Tunnel xử lý kết thúc TLS tại cổng gateway đám mây. Máy chủ cục bộ của bạn có thể ở HTTP trơn — URL công khai là HTTPS, và đó là bề mặt mọi dịch vụ bên ngoài chạm tới.

Đặt cạnh nhau

Nhu cầumkcertTunnel
HTTPS trong trình duyệt cục bộCó (qua URL công khai)
Kiểm thử service worker / cookie an toàn trong trình duyệt
Nhà cung cấp bên ngoài tiếp cận được bạnKhông
Điện thoại trên tay tiếp cận được bạnKhông (nếu không cài CA)
Nhà cung cấp OAuth chấp nhận URLĐôi khi (Google: có; nhiều: không)
Stripe / GitHub / Twilio gửi webhook đượcKhông
Thời gian thiết lập30 giây mỗi máyMột lệnh mỗi phiên
Hoạt động offlineKhông
Sống sót chế độ máy bayKhông

Nơi người ta hiểu sai

Cố dùng mkcert để kiểm thử webhook

Stripe không thể tin CA cục bộ của máy bạn. Dù chứng chỉ trông đáng tin đến đâu trong trình duyệt — Stripe ở mạng khác. Bạn cần một tunnel cho bất kỳ lưu lượng đến nào từ internet công khai.

Dùng tunnel cho HTTPS một mình chỉ trong trình duyệt

Nếu bạn chỉ muốn service worker chạy hoặc đặt một cookie an toàn trong trình duyệt của chính mình, mkcert nhanh hơn và chạy offline. Đừng đốt một phiên tunnel cho thứ mà một file chứng chỉ giải quyết.

Chọn một công cụ và ép trường hợp kia qua nó

Chạy cả hai là ổn. Phần lớn thiết lập của chúng tôi dùng mkcert cho công việc phía trình duyệt hằng ngày và tunnel khi kiểm thử webhook hoặc callback OAuth. Chúng sống chung trong package.json không xung đột.

Còn Caddy hay nginx thì sao?

Có, bạn có thể chạy Caddy với HTTPS tự động trước máy chủ dev, và điều đó cũng chạy — về cơ bản là "mkcert với vài bước thêm và một reverse proxy". Với phần lớn dev cục bộ, mkcert đơn giản hơn. Với định tuyến phức tạp hơn cùng nhiều dịch vụ cục bộ, Caddy đáng giá.

Thiết lập thực tế của chúng tôi

Một repo chúng tôi làm việc có mkcert trong script dev cho HTTPS phía localhost, và một script npm tunnel riêng chạy portpreview khi ai đó cần webhook hoặc kiểm thử di động. URL tunnel được truyền qua biến môi trường nên redirect URI của OAuth dễ thay. Mất 20 phút để đấu nối và từ đó không bao giờ phải nghĩ về TLS cục bộ nữa.

Về thiết lập tunnel riêng cho OAuth, xem cách kiểm thử callback OAuth cục bộ. Để chia sẻ bản xem trước với đồng nghiệp hay nhà thiết kế, chia sẻ máy chủ dev cục bộ. Tham gia danh sách chờ của PortPreview để có phần tunnel của thiết lập này.

Câu hỏi thường gặp

Tôi nên dùng mkcert hay tunnel cho HTTPS cục bộ?
Cả hai, cho những việc khác nhau. mkcert cho trình duyệt của chính bạn một chứng chỉ tin cậy trên localhost và chạy offline. Tunnel cho bạn một URL HTTPS công khai mà dịch vụ bên ngoài và thiết bị khác tiếp cận được. Chúng không xung đột — hầu hết các nhóm dùng cả hai.
mkcert có xử lý được kiểm thử webhook từ Stripe hoặc GitHub không?
Không. Chứng chỉ mkcert chỉ được tin trên máy đã cài CA. Nhà cung cấp webhook bên ngoài không thể tiếp cận localhost dù chứng chỉ đáng tin đến đâu trong trình duyệt cục bộ của bạn. Dùng tunnel cho bất kỳ lưu lượng công khai đến nào.
mkcert có dùng được cho callback OAuth trên localhost không?
Một số nhà cung cấp (Google, một số tier dev của Auth0) chấp nhận localhost qua HTTP hoặc HTTPS để phát triển. Nhiều bên thì không. mkcert cho HTTPS với những bên chấp nhận; với bên nghiêm ngặt, cần một tunnel có URL HTTPS công khai.