# HTTPS/TLS

CrossWatch can serve the web UI over **HTTP** or **HTTPS**.

When you enable HTTPS, you have two options:

* **Self-signed** (generated by CrossWatch)
* **Custom cert + key** (mounted into the container)

{% hint style="warning" %}

### Support scope note

Reverse proxy setups and HTTPS/TLS configuration are **not in the supported scope**.

Issues around proxies, certificates, and the TLS manager get **lower priority**.

I can’t spend much time debugging these setups. Sorry.
{% endhint %}

{% hint style="warning" %}
**Media-server webhooks can fail with self-signed TLS certificates.**

If your media server needs to `POST` to CrossWatch over `https://...`, it may reject self-signed certificates.

This affects:

* **Plex**: rejects self-signed certificates for webhook delivery.
* **Emby/Jellyfin**: webhook plugins commonly reject self-signed certs unless the CA is trusted.

Use a reverse proxy with a publicly trusted certificate (example: Let’s Encrypt). Keep CrossWatch on HTTP behind the proxy. See [Reverse proxies](/related-information/reverse-proxies.md).
{% endhint %}

### Enable HTTPS (UI)

1. Open **Settings → User Interface**
2. Set **Protocol** to **HTTPS**
3. Click **Save**
4. Restart CrossWatch (container restart required).

Then open:

* `https://<host>:<port>/`

{% hint style="info" %}
Self-signed certificates encrypt traffic. Browsers still warn until you trust the certificate. See [Trust the self-signed certificate](#trust-the-self-signed-certificate).
{% endhint %}

{% hint style="warning" %}

### After switching HTTP ↔ HTTPS

Anything that points at your CrossWatch URL must be updated.

This usually includes:

* **Webhook URLs** configured in Plex/Jellyfin/Emby (or any reverse proxy rewrite rules).
* **OAuth redirect/callback URLs** configured in provider dev apps.
  * AniList: see [AniList](/crosswatch/providers/authentication/auth-trackers/auth-anilist.md)
  * SIMKL: see [SIMKL](/crosswatch/providers/authentication/auth-trackers/auth-simkl.md)

If the URL doesn’t match exactly (scheme + host + port + path), auth or webhooks will fail.
{% endhint %}

### TLS manager (Advanced)

Next to **Protocol**, click **Advanced**.

You can:

* Check current TLS status (paths, expiry, SANs, fingerprint)
* Switch between **Self-signed** and **Custom**
* Regenerate the self-signed certificate
* Download the generated `.crt` file
* Validate that custom cert/key paths exist

<figure><img src="/files/47SGNJ4I8PHus4qtD0go" alt=""><figcaption></figcaption></figure>

#### Restart required

Restart is required after:

* HTTP ↔ HTTPS switch
* Self-signed regeneration
* Changing cert/key paths
* Changing hostname/SAN inputs

### Certificate files and persistence

Default generated files:

* Cert: `/config/tls/crosswatch.crt`
* Key: `/config/tls/crosswatch.key`

{% hint style="warning" %}
Mount `/config` as a persistent volume. Otherwise certificates reset on container re-creation.
{% endhint %}

Related: [Docker setup](/getting-started/docker-setup.md).

### Trust the self-signed certificate

Download `crosswatch.crt` from **Advanced**. Install it into your OS or browser trust store.

<figure><img src="/files/DIJPzy91jTwoqoWihnzT" alt=""><figcaption></figcaption></figure>

{% tabs %}
{% tab title="Windows (Chrome/Edge)" %}

1. Run `mmc`
2. **File → Add/Remove Snap-in → Certificates → Computer account**
3. Import into **Trusted Root Certification Authorities**
4. Restart the browser
   {% endtab %}

{% tab title="macOS" %}

1. Open **Keychain Access**
2. Import into the **System** keychain
3. Open the cert and set **Trust → Always Trust**
4. Restart the browser
   {% endtab %}

{% tab title="Linux" %}
Browser-only trust is often enough.

System trust examples:

* Debian/Ubuntu: copy to `/usr/local/share/ca-certificates/` then run `update-ca-certificates`
* Fedora: run `update-ca-trust`
  {% endtab %}
  {% endtabs %}

### Trusted certificates (recommended)

Put a reverse proxy in front of CrossWatch. Terminate TLS there with Let’s Encrypt.

* CrossWatch stays on **HTTP** internally
* The proxy handles renewals

Typical choices: Caddy, Nginx, Traefik.

### Custom certificates in CrossWatch

1. Mount your PEM files into the container.
2. Set the cert and key paths in **Advanced** (or `config.json`).
3. Switch **Protocol** to **HTTPS**.
4. Restart CrossWatch.

<figure><img src="/files/xQAD1CFD86G2IWYZOWfh" alt=""><figcaption></figcaption></figure>

Example paths:

* `/config/tls/fullchain.pem`
* `/config/tls/privkey.pem`

### config.json reference

Related: [Configuration (config.json)](/crosswatch/configuration-config-json.md).

```json
"ui": {
  "protocol": "https",
  "tls": {
    "self_signed": true,
    "hostname": "localhost",
    "valid_days": 825,
    "cert_file": "",
    "key_file": ""
  }
}
```

Key fields:

* `ui.protocol`: `"http"` or `"https"`
* `ui.tls.self_signed`
  * `true`: generate `/config/tls/crosswatch.crt` + `/config/tls/crosswatch.key` if missing
  * `false`: use `cert_file` + `key_file`
* `ui.tls.hostname`: used for CN and included in SAN
* `ui.tls.valid_days`: validity for generated self-signed certs
* `ui.tls.cert_file`: absolute path to cert PEM (custom mode)
* `ui.tls.key_file`: absolute path to key PEM (custom mode)

{% hint style="warning" %}
If HTTPS is enabled but cert/key can’t be loaded, CrossWatch will fail to start. Check logs for the exact path it tried.
{% endhint %}

### Troubleshooting

#### HTTPS enabled, but UI won’t load

* Restart CrossWatch
* Use `https://...` in the URL
* Confirm your exposed port matches the container port mapping

#### Advanced modal shows missing files

* Confirm `/config` is mounted
* Check container paths under `/config/tls/`

#### Browser still warns after installing the cert

* Install into the correct trust store (System / Trusted Root)
* Fully restart the browser process


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.crosswatch.app/crosswatch/navigation/ui-settings/user-interface/https-tls.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
