MY WEBCAM TEST GUIDE

How to Configure an HTTPS Site in Nginx for Camera and Microphone Access

Configure HTTPS in Nginx so browsers treat your site as a secure context and allow webcam and microphone access. Covers prerequisites, a server block example and checks.

The short answer

To serve a site over HTTPS in Nginx, you need a TLS certificate and private key for your domain, plus a server block that listens on port 443 with ssl enabled and points to those two files. After that, you test the configuration, reload Nginx and, ideally, redirect plain HTTP traffic to HTTPS.

This matters for webcams and microphones because modern browsers only expose camera and microphone capture to pages loaded in a secure context. In practice that means a page served over HTTPS, or a page loaded from the local machine (localhost) during development. If your page is served over plain HTTP from a real hostname, the browser typically does not offer the media capture API at all, so no permission prompt appears and no device can be selected.

One condition changes the answer: if your web page is embedded in another page through an iframe, both the embedding page and the frame need to be secure, and the embedding page must explicitly allow camera and microphone use for that frame. HTTPS alone is not enough in that case.

Why HTTPS is the first thing to check

Camera and microphone problems on a website usually fall into three separate stages, and HTTPS affects the very first one:

  • Availability: the browser decides whether the page may use media capture at all. On an insecure page, the capture API is commonly missing, so scripts fail before any device is involved.
  • Permission: on a secure page, the browser asks the visitor whether to allow the camera, the microphone or both. Camera (video capture) and microphone (audio capture) permissions are granted separately.
  • Input selection: once permission is granted, the page or the visitor chooses which specific webcam or microphone to use when more than one is connected.

Setting up HTTPS in Nginx resolves the availability stage. It does not grant permission on the visitor's behalf and it does not choose a device; those steps still happen in the browser.

Prerequisites

  • Nginx installed on the server, with its SSL module available (standard distribution packages normally include it, but this varies by build).
  • A registered domain name whose DNS record points to the server.
  • A TLS certificate and its matching private key for that domain. A free certificate authority such as Let's Encrypt, used through a client like Certbot, is a common option; a commercial certificate also works.
  • Administrative (root or sudo) access to the server.
  • Port 443 open in any firewall or cloud security group in front of the server, and port 80 open if you plan to redirect HTTP or use HTTP-based certificate validation.

Step 1: Obtain a certificate

If you use Certbot with its Nginx plugin, it can request a certificate and edit your Nginx configuration automatically. If you prefer to manage the configuration yourself, request the certificate only and note the paths it reports for the full certificate chain and the private key. Exact commands and file locations depend on your operating system and Certbot version, so follow the instructions for your platform.

Self-signed certificates encrypt the connection, but browsers show a warning for them and visitors must accept it manually. They are suitable for private testing, not for a public site where people are expected to use their camera or microphone.

Step 2: Write the HTTPS server block

Nginx configuration is often kept in a site file under the sites-available directory (Debian and Ubuntu style) or in the conf.d directory (common on other distributions). The example below uses placeholders in angle brackets; replace them with your own hostname and file paths.

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name <your-hostname>;

    ssl_certificate     /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;

    root  /var/www/<your-site>;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

The ssl_certificate directive should point to the full chain (your certificate plus intermediate certificates), not only the leaf certificate; an incomplete chain can cause trust errors in some browsers and clients. Keep the private key file readable only by the root user or the account Nginx starts as.

Depending on your Nginx version, HTTP/2 is enabled either by adding http2 to the listen line or with a separate http2 directive. Check the documentation for your installed version before adding it.

Step 3: Redirect HTTP to HTTPS

Visitors who type your address without a scheme, or follow an old link, may land on the HTTP version, where camera and microphone capture is unavailable. A separate server block on port 80 sends them to the secure version:

server {
    listen 80;
    listen [::]:80;
    server_name <your-hostname>;

    return 301 https://$host$request_uri;
}

Step 4: Allow camera and microphone where needed

If your site sends a Permissions-Policy header, make sure it does not block the features you need. A policy that disables camera or microphone overrides the secure context and the capture request fails. To allow your own pages to use both, you can add this inside the HTTPS server block:

add_header Permissions-Policy "camera=(self), microphone=(self)" always;

If the capture page is loaded in an iframe from another origin, the parent page must also delegate access on the iframe element itself, using its allow attribute with camera and microphone listed. Only include the features you actually use: a page that needs audio only does not need camera access.

Step 5: Test and reload Nginx

sudo nginx -t
sudo systemctl reload nginx

The first command checks the configuration for syntax errors and missing files, such as a wrong certificate path. Reload only if it reports that the test is successful. The reload command shown applies to systems that use systemd; on other init systems, use the equivalent service command or run nginx with the reload signal.

How to confirm it worked

  • Open your site with the https scheme. The browser should load it without a certificate warning, and the address bar should show a secure connection indicator.
  • Open the plain HTTP version. It should redirect to the HTTPS version.
  • On the page that uses the camera or microphone, open the browser's developer console and evaluate window.isSecureContext. It should return true.
  • In the same console, check that navigator.mediaDevices is defined. If it is undefined on an HTTPS page, look for an iframe without delegated permissions or a restrictive Permissions-Policy header.
  • Trigger your camera or microphone feature. The browser should now show its permission prompt. After the visitor allows access, the page can list and select specific input devices.
window.isSecureContext
navigator.mediaDevices

Common causes when the camera or microphone still does not work

  • Mixed setup: the main page loads over HTTPS, but the capture page or frame is still served over HTTP.
  • A proxy or load balancer in front of Nginx terminates TLS and forwards plain HTTP; the browser still sees HTTPS, but your application may generate HTTP links or redirects. Check the forwarded protocol headers your application relies on.
  • The permission was previously denied. Browsers remember this per site, so the visitor must reset it in the site settings; HTTPS does not reset it.
  • No device is detected. This is a hardware, driver or operating system privacy setting issue, separate from HTTPS and from browser permission.
  • The wrong input is active. Permission is granted but the page uses a different webcam or microphone than intended; the device choice needs to be changed in the page or browser settings.

What this guide does not cover

No specific evidence was supplied about particular Nginx versions, browser versions, certificate providers or hosting platforms, so the commands and file paths above are general. Directive names, default file locations and the exact way browsers report insecure contexts can differ by version and platform. Verify against the documentation for the versions you run before applying the configuration to a production server.