@@ -162,3 +162,119 @@ MIROTALK_ADMIN_DIR=/root/mirotalk-admin
162162> Regularly review and update your ` .env` settings to keep your MiroTalk instance secure and manageable.
163163
164164---
165+
166+ # ## 🔒 TLS / HTTPS in Production
167+
168+ The dashboard listens on a single HTTPS port (` ADMIN_PORT` ) via the
169+ Node.js stdlib ` https` module, plaintext HTTP requests on this port are
170+ rejected at the TLS layer and cannot reach the application.
171+
172+ - Defense-in-depth: when ` NODE_ENV=production` , any request whose
173+ ` req.secure` is false (e.g. arriving through a misconfigured reverse
174+ proxy that did not set ` X-Forwarded-Proto: https` ) is 301-redirected
175+ to HTTPS for ` GET` /` HEAD` and rejected with ` 403` for any other
176+ method. Plaintext ` ws://` socket upgrades are likewise refused.
177+ - The bundled certificate in [backend/ssl/](backend/ssl/) is ** self-signed**
178+ and intended for first-boot / local development only. For production,
179+ either:
180+ - replace ` backend/ssl/key.pem` and ` backend/ssl/cert.pem` with a
181+ certificate issued by a trusted CA (e.g. Let' s Encrypt), or
182+ - put the dashboard behind a TLS-terminating reverse proxy
183+ (nginx, Caddy, Traefik, an ALB, etc.) and bind the dashboard to
184+ `127.0.0.1`. When doing so, set `TRUST_PROXY=true` so the
185+ `X-Forwarded-Proto` and `X-Forwarded-For` headers are honored.
186+ - Responses include `Strict-Transport-Security: max-age=63072000; includeSubDomains`
187+ to pin compliant browsers to HTTPS.
188+
189+ #### Local development with a trusted cert
190+
191+ The bundled `backend/ssl/cert.pem` is self-signed, so on the first visit
192+ your browser will show a "Not secure / self-signed certificate" warning.
193+ Click through it once (Chrome: type `thisisunsafe` on the warning page,
194+ or **Advanced → Proceed**; Firefox: **Accept the Risk and Continue**) and
195+ the dashboard at <https://localhost:9999/admin> will load.
196+
197+ To remove the warning entirely in development, install
198+ [`mkcert`](https://github.com/FiloSottile/mkcert) and issue a cert that
199+ your OS / browsers actually trust. Place the dev cert in
200+ `backend/ssl/dev/`, the server auto-detects it when `NODE_ENV` is not
201+ `production` and falls back to `backend/ssl/` otherwise:
202+
203+ <details>
204+ <summary>🍎 macOS</summary>
205+
206+ <br/>
207+
208+ ```bash
209+ brew install mkcert nss
210+ mkcert -install
211+
212+ mkdir -p backend/ssl/dev
213+ cd backend/ssl/dev
214+ mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1
215+ ```
216+
217+ </details>
218+
219+ <details>
220+ <summary>🐧 Linux (Debian / Ubuntu)</summary>
221+
222+ <br/>
223+
224+ ```bash
225+ sudo apt update
226+ sudo apt install -y libnss3-tools
227+ # install the mkcert binary (pick the latest release for your arch)
228+ curl -fsSLo /tmp/mkcert "https://dl.filippo.io/mkcert/latest?for=linux/amd64"
229+ sudo install -m 0755 /tmp/mkcert /usr/local/bin/mkcert
230+ mkcert -install
231+
232+ mkdir -p backend/ssl/dev
233+ cd backend/ssl/dev
234+ mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1
235+ ```
236+
237+ > On Fedora/RHEL use `sudo dnf install nss-tools`; on Arch use
238+ > `sudo pacman -S nss mkcert`. For Firefox to trust the cert, make sure
239+ > `libnss3-tools` (or `nss-tools`) is installed **before** running
240+ > `mkcert -install`.
241+
242+ </details>
243+
244+ <details>
245+ <summary>🪟 Windows (PowerShell, run as Administrator)</summary>
246+
247+ <br/>
248+
249+ ```powershell
250+ # Easiest path: Chocolatey
251+ choco install mkcert
252+ # …or Scoop:
253+ # scoop bucket add extras; scoop install mkcert
254+ mkcert -install
255+
256+ mkdir backend\ssl\dev
257+ cd backend\ssl\dev
258+ mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1
259+ ```
260+
261+ > Firefox on Windows uses its own trust store. After `mkcert -install`,
262+ > restart Firefox so it picks up the new local CA. Chrome / Edge use the
263+ > Windows trust store and work immediately.
264+
265+ </details>
266+
267+ <br/>
268+
269+ `backend/ssl/dev/` is gitignored, so the locally-trusted cert never
270+ ships with the repo. In production the server always uses
271+ `backend/ssl/key.pem` + `backend/ssl/cert.pem`, which should hold a
272+ CA-issued cert (or be replaced by a TLS-terminating reverse proxy as
273+ described above).
274+
275+ Restart the server and the lock icon will be green. The dev workflow is
276+ otherwise unchanged, the dashboard is HTTPS-only in every environment
277+ so behavior in dev matches production (`Secure` cookies, HSTS, mixed
278+ content, `wss://` upgrades, etc.).
279+
280+ ---
0 commit comments