diff --git a/quill/networking-and-dns.mdx b/quill/networking-and-dns.mdx index 1b7b35d668..6ce4e989f8 100644 --- a/quill/networking-and-dns.mdx +++ b/quill/networking-and-dns.mdx @@ -59,7 +59,7 @@ By default, all five resolve to the IP address provided during sign-up: | -------------------- | ---------------------------------------------------------------------------------------- | | `dashboard.` | The operator dashboard, dashboard API requests, and health checks. | | `api.` | Programmatic access to the Quill API and health checks, without the dashboard UI. | -| `public.` | Embedded chat pages and their chat requests. | +| `public.` | Embedded chat pages, widget assets, chat requests, and public channel webhooks. | | `db.` | Direct RavenDB access for applications authenticated with a client certificate. | | `a.` | RavenDB's advertised node URL, which RavenDB.Client may receive through topology discovery. | @@ -120,8 +120,8 @@ Because the records belong to a RavenDB-managed DNS zone: * You do not receive DNS-provider credentials or a DNS console for the instance. * Moving or restarting your Quill does not update the records automatically. -When a record must change, the update is requested through the RavenDB DNS service at `api.ravendb.net`. -The supported update command reads the license file from the activated setup package and uses it to authorize the request for the licensed domain. +When a record must change, run the supported `update-dns` command from the Docker host. +The command reads the licensed domain from the activated server certificate and uses the setup package's `license.json` file to authorize the request to the RavenDB DNS service at `api.ravendb.net`. The exact command and the records it updates are described in [Update the records](#update-the-records). @@ -201,7 +201,7 @@ The Quill domain and the URLs used by operators, chat users, and applications re | Wildcard server certificate | The certificate is issued for `*.`, not for a particular IP address. | | Activated setup package and license | Your Quill continues using the existing activated setup package and its license file. | | Dashboard API key | The key is independent of the host's IP address; supply the same `QUILL_API_KEY` value to a replacement container. | -| Quill configuration and data | Apps, agents, channels, conversations, RavenDB databases, and certificate registrations remain in the `quill-data` volume. | +| Quill configuration and data | Apps, agents, channels, conversations, RavenDB databases, and certificate registrations remain in the persistent Docker volume mounted at `/var/lib/quill`. | Repointing the DNS records therefore does not require a new domain, new URLs, a new wildcard certificate, or a different Dashboard API key. @@ -215,7 +215,7 @@ For information about preserving or replacing the Dashboard API key, see [Operat A DNS update does not copy your Quill's data or container configuration. -When moving your Quill to another host, transfer the `quill-data` volume and preserve the required deployment environment values, +When moving your Quill to another host, transfer the persistent Docker volume mounted at `/var/lib/quill` and preserve the required deployment environment values, including `QUILL_API_KEY` and `QUILL_LICENSE_KEY`, before directing traffic to the new host. If only the existing host's externally reachable IP address changes, no data-volume migration is required. @@ -226,55 +226,32 @@ If only the existing host's externally reachable IP address changes, no data-vol -{/* TODO before publication - See RavenDB-27372: -Do not publish either `docker exec quill update-dns --ip ...` -or the direct `/app/ravendb/rvn dns update ...` command -until the release image is finalized and the supported command is verified. - -The default release image currently has neither the wrapper nor an `rvn` version that supports `dns update`. -Dockerfile.source has them but is planned for removal. -The dashboard currently displays the wrapper command. -*/} - -Run the DNS update from the Docker host after your Quill is available at its new address. +Run the DNS update from the Docker host after the Quill container is running on the host with its new externally reachable address. The container must: * be running and activated; - * contain the activated setup package and its `license.json` file; + * contain the activated setup package, including its server certificate and `license.json` file; * have outbound HTTPS access to `api.ravendb.net`. -The DNS update uses the license file for authorization. -It does not use the Dashboard API key or an authenticated browser session. - ---- - -### Find the base domain - -If you do not know the instance's base domain, read `PublicServerUrl` from the activated setup package: - -```bash -docker exec quill jq -r '.PublicServerUrl' \ - /var/lib/quill/setup/A/settings.json -``` -
- -The value has the form `https://a.`. -Use only the `` portion in the DNS update command, without `https://`, `a.`, or a port number. +The command derives the base domain from the server certificate and uses the license file for authorization. +You do not need to supply the domain, the Dashboard API key, or an authenticated browser session. --- ### Update the five DNS records -Run the following command, replacing `` with the base domain and `` with the host's new address: +In the commands below, `` is the name specified by `docker run --name`. +By default, it matches your Quill name. + +Run the following command, replacing `` with the host's new address: ```bash -docker exec quill /app/ravendb/rvn dns update \ - -l /var/lib/quill/setup/license.json \ - -d \ - -n =a,dashboard,db,public,api +docker exec update-dns --ip ```
+If the container uses the default name, the dashboard's **Settings > IP configuration** page generates this command with the container name filled in after you enter a new IPv4 address. + The command updates all five DNS records in one request: * `dashboard.` @@ -292,13 +269,10 @@ Callers may still receive the previous address from DNS caches, as explained in #### Assigning more than one address -To assign several addresses to each of the five DNS hostnames, list them before the `=` and separate them with commas: +To assign several addresses to each of the five DNS hostnames, separate them with commas in the value passed to `--ip`: ```bash -docker exec quill /app/ravendb/rvn dns update \ - -l /var/lib/quill/setup/license.json \ - -d \ - -n ,=a,dashboard,db,public,api +docker exec update-dns --ip , ```
@@ -362,10 +336,6 @@ Restarting an affected browser or application may clear its local cache, but it After allowing for propagation, confirm the current answers as described in [Verify the change](#verify-the-change). -{/* TTL verified against the live Quill DNS records on 2026-08-17. -Reverify if the DNS service configuration changes before publication. -*/} -
@@ -444,8 +414,8 @@ Use the point at which verification fails to identify the affected layer: | Symptom | Likely cause | Next check | | ------- | ------------ | ---------- | -| The DNS update command exits with an error | The new IP address is invalid, the activated setup package or license file is unavailable, outbound HTTPS failed, or the DNS service rejected the request | Read the returned error, verify the new IP address and setup files, confirm outbound access to `api.ravendb.net`, and verify all five DNS records before retrying | -| A hostname does not resolve | The hostname or base domain is incorrect, or the record was not provisioned | Compare the hostname with the `PublicServerUrl` in the activated setup package | +| The DNS update command exits with an error | The new IP address is invalid, the activated server certificate or license file is unavailable, outbound HTTPS failed, or the DNS service rejected the request | Read the returned error, verify the new IP address and the activated setup package, confirm outbound access to `api.ravendb.net`, and verify all five DNS records before retrying | +| A hostname does not resolve | The hostname or base domain is incorrect, the record was not provisioned, or a resolver cached an earlier "not found" response | Compare the hostname with the `PublicServerUrl` in the activated setup package. If the hostname was recently provisioned, wait up to 15 minutes for the cached response to expire, then resolve it again | | A hostname still resolves to the old address | The answer is cached or the update has not completed | Allow for the TTL, then resolve all five hostnames again | | The hostname resolves correctly, but the connection times out | External TCP port `443` is blocked or does not reach container port `443` | Check the firewall, cloud security rules, NAT or load-balancer forwarding, and Docker port mapping | | The hostname resolves correctly, but the connection is refused | The container is stopped or nothing is accepting the forwarded connection | Check the container state and Docker port mapping | @@ -458,22 +428,24 @@ Use the point at which verification fails to identify the affected layer: ### Check the container and published port +In the commands below, `` is the name specified by `docker run --name`. By default, it matches your Quill name. + Confirm that the container is running: ```bash -docker inspect quill --format "Status={{.State.Status}}" +docker inspect --format "Status={{.State.Status}}" ```
Confirm that the container's HTTPS port is published: ```bash -docker port quill 443/tcp +docker port 443/tcp ```
If the container is stopped, start it before continuing. -If port `443` is not published, review the Docker Compose configuration. +If port `443` is not published, review how the container was started and confirm that container port `443` is published to the host. --- @@ -482,7 +454,7 @@ If port `443` is not published, review the Docker Compose configuration. Bypass external DNS, the host firewall, and nginx by calling the Quill web application directly: ```bash -docker exec quill curl --fail --silent --show-error \ +docker exec curl --fail --silent --show-error \ http://127.0.0.1:5000/healthz ```
@@ -490,7 +462,7 @@ docker exec quill curl --fail --silent --show-error \ Then inspect the activation state: ```bash -docker exec quill curl --silent --show-error \ +docker exec curl --silent --show-error \ http://127.0.0.1:5000/api/bootstrap/status ```
@@ -506,7 +478,7 @@ If the internal health check also fails, investigate the Quill web application a Read the most recent Quill web application messages: ```bash -docker exec quill tail -n 100 \ +docker exec tail -n 100 \ /var/lib/quill/logs/web.log ```
@@ -514,7 +486,7 @@ docker exec quill tail -n 100 \ For nginx routing or TLS-termination failures, read: ```bash -docker exec quill tail -n 100 \ +docker exec tail -n 100 \ /var/lib/quill/logs/proxy.log ```
@@ -522,7 +494,7 @@ docker exec quill tail -n 100 \ For RavenDB startup or direct database failures, read: ```bash -docker exec quill tail -n 100 \ +docker exec tail -n 100 \ /var/lib/quill/logs/ravendb.log ```
@@ -530,7 +502,7 @@ docker exec quill tail -n 100 \ For wildcard-certificate renewal failures, read: ```bash -docker exec quill tail -n 100 \ +docker exec tail -n 100 \ /var/lib/quill/logs/certwatch.log ```
@@ -553,13 +525,13 @@ For client-certificate requirements, see [Direct database access](security-and-a Routing, TLS termination, and authorization are handled by your Quill after the connection reaches the host on port `443`. -* If the host's externally reachable IP address changes, update all five DNS records. - The update uses the activated license file to authorize the request. +* If the host's externally reachable IP address changes, run `docker exec update-dns --ip `. + The command derives the domain from the activated server certificate and uses the activated license to authorize the update of all five DNS records. * Updating DNS does not move your Quill to another host. - Preserve the `quill-data` volume and the required deployment environment values when moving it. + Preserve the persistent Docker volume mounted at `/var/lib/quill` and the required deployment environment values when moving it. * The records have a TTL of 30 minutes. After an update, verify both DNS resolution and HTTPS connectivity. -
\ No newline at end of file + diff --git a/quill/security-and-architecture/network-architecture.mdx b/quill/security-and-architecture/network-architecture.mdx index 5c9fd1e3c9..682e6c2c3a 100644 --- a/quill/security-and-architecture/network-architecture.mdx +++ b/quill/security-and-architecture/network-architecture.mdx @@ -45,7 +45,7 @@ Its three main components are RavenDB, the Quill web application, and nginx. Acts as Quill's reverse proxy and external TLS entry point. It listens on port `443` and uses the requested hostname to route each connection to either the Quill web application or RavenDB. -In the default Docker Compose configuration, only port `443` is published to the host. +The default Quill deployment publishes only port `443` to the host. The internal ports used by the Quill web application and RavenDB are not published, so external connections can only enter through nginx. @@ -247,7 +247,7 @@ You can generate client certificates from the dashboard's Certificates page and #### Publish only port 443 -* The default `docker-compose.yml` publishes only the nginx entry point on port `443`. +* The default Quill deployment publishes only the nginx entry point on port `443`. * RavenDB does not start until the setup package is available. It then starts in secured mode and listens only on the container's loopback interface, at `127.0.0.1:8443`. @@ -258,8 +258,11 @@ You can generate client certificates from the dashboard's Certificates page and * For diagnostics, run commands inside the container instead of publishing an internal port: + In this command, `` is the name specified by `docker run --name`. + By default, it matches your Quill name. + ```bash - docker exec quill curl -s http://127.0.0.1:5000/api/bootstrap/status + docker exec curl -s http://127.0.0.1:5000/api/bootstrap/status ``` @@ -292,9 +295,12 @@ Successful nginx certificate reloads are recorded in `/var/lib/quill/logs/certwa Inspect these logs from the host: +In the commands below, `` is the name specified by `docker run --name`. +By default, it matches your Quill name. + ```bash -docker exec quill tail -n 100 /var/lib/quill/logs/ravendb.log -docker exec quill tail -n 100 /var/lib/quill/logs/certwatch.log +docker exec tail -n 100 /var/lib/quill/logs/ravendb.log +docker exec tail -n 100 /var/lib/quill/logs/certwatch.log ```
@@ -308,7 +314,7 @@ docker exec quill tail -n 100 /var/lib/quill/logs/certwatch.log * This is expected. Check the activation status from inside the container: ```bash - docker exec quill curl -s http://127.0.0.1:5000/api/bootstrap/status + docker exec curl -s http://127.0.0.1:5000/api/bootstrap/status ``` * Once activation reports `Ready`, connect through port `443` normally. @@ -336,7 +342,7 @@ nginx forwards the encrypted TLS connection unchanged. RavenDB then: * The generated RavenDB settings bind the native TCP listener to `tcp://127.0.0.1:38888`, so it is reachable only from inside the container. - RavenDB advertises this listener as `tcp://a.:38888`, but the default Docker Compose configuration publishes only port `443`, + RavenDB advertises this listener as `tcp://a.:38888`, but the default Quill deployment publishes only port `443`, and nginx does not route port `38888`. * Direct access through `db.` therefore uses RavenDB's HTTPS API on port `443`. @@ -374,7 +380,7 @@ Applications that require direct access must use their own client certificate wi -* The default Docker Compose configuration publishes one port, `443`, with nginx as the external entry point. +* The default Quill deployment publishes one port, `443`, with nginx as the external entry point. * Four customer-facing hostnames expose the dashboard, API, public chat, and direct RavenDB surfaces. The additional `a.` hostname is RavenDB's advertised node alias. * The public hostname exposes only embed-link chat routes, which require an active embed-link token. diff --git a/quill/security-and-architecture/operator-authentication.mdx b/quill/security-and-architecture/operator-authentication.mdx index 44b15e43d2..9d7119ad13 100644 --- a/quill/security-and-architecture/operator-authentication.mdx +++ b/quill/security-and-architecture/operator-authentication.mdx @@ -31,19 +31,18 @@ import ContentFrame from '@site/src/components/ContentFrame'; Quill reads its Dashboard API key from the `QUILL_API_KEY` environment variable when the container starts. -In the default Docker Compose configuration, you supply it in the `.env` file next to `docker-compose.yml`. +You supply it through the `-e QUILL_API_KEY=...` option in the `docker run` command. -The key is required: +The key is required for protected operational access: -* The default Docker Compose configuration prevents the container from starting when `QUILL_API_KEY` is missing. -* If Quill is started another way without the key, it rejects all requests to protected operational API endpoints. +* If Quill starts without the key, it rejects all requests to protected operational API endpoints. It does not allow anonymous access or use a default key. * When the key is configured, it can be used to create a browser session or authenticate an API request directly. For validation, Quill stores a salted SHA-256 hash in its configuration database and compares hashes using a constant-time operation. Quill does not expose the original key through its dashboard or API. -The original value remains in your deployment configuration, such as the `.env` file and the container environment. +The original value remains in your deployment configuration or secret store and in the container environment. Protect access to that configuration as you would any other secret. @@ -63,7 +62,7 @@ Using the License key instead results in `401 Unauthorized`. If you replace the signup-issued Dashboard API key with a value of your own, use a high-entropy value. -Quill logs a startup warning when `QUILL_API_KEY` is shorter than 16 characters. +Quill logs a warning the first time it validates a Dashboard API key if `QUILL_API_KEY` is shorter than 16 characters. @@ -158,8 +157,7 @@ By default, you configure each of those Quill instances with the signup-issued k Quill cannot derive the original Dashboard API key from the salted hash in its configuration database, and it does not expose the key through its dashboard or API. -First, check the deployment configuration from which `QUILL_API_KEY` was supplied, -such as the `.env` file or your secret store. +First, check the deployment configuration or secret store from which `QUILL_API_KEY` was supplied. If the Quill instance still uses the signup-issued key, you can also recover it in either of these ways: @@ -184,34 +182,22 @@ and recreate the container. -### Docker Compose - -Edit `QUILL_API_KEY` in the `.env` file next to `docker-compose.yml`, then run: - -```bash -docker compose up -d -``` -
- -Compose detects the changed environment and recreates the container with the new key. - -
- - - ### docker run +In these commands, `` is the name specified after `--name` in your original `docker run` command. +By default, it matches your Quill name. `` is the volume name specified before `:/var/lib/quill` in that command. + Remove the existing container, then rerun it with the new key and the same data volume: ```bash -docker rm -f quill +docker rm -f -docker run -d --name quill \ +docker run -d --name \ --restart unless-stopped \ -p 443:443 \ -e QUILL_LICENSE_KEY="YOUR_EXISTING_LICENSE_KEY" \ -e QUILL_API_KEY="YOUR_NEW_DASHBOARD_API_KEY" \ - -v quill-data:/var/lib/quill \ + -v :/var/lib/quill \ ravendb/quill:latest ```
@@ -226,7 +212,7 @@ preserve those values when recreating the container. #### Recreate the container; do not restart it Quill reads `QUILL_API_KEY` from the container environment when it starts. -Restarting the existing container reuses the same environment, so `docker restart quill` +Restarting the existing container reuses the same environment, so `docker restart ` keeps the exposed key in force. A browser session is not re-checked against the Dashboard API key after login. @@ -234,14 +220,14 @@ Restarting the existing container therefore also leaves previously issued sessio until they expire after eight hours of inactivity. With the default container layout, the cookie-protection keys are stored in the container’s writable layer, -outside the quill-data volume. Recreating the container discards those keys and invalidates previously issued sessions. +outside the persistent volume mounted at `/var/lib/quill`. Recreating the container discards those keys and invalidates previously issued sessions. -Recreating the container preserves the Quill data stored in the `quill-data` volume, +Recreating the container preserves the Quill data stored in the persistent volume mounted at `/var/lib/quill`, including its databases, activated setup package, and configured apps. -Do not delete that volume or run `docker compose down -v`; those operations remove the persisted Quill data. +Do not delete that volume; doing so removes the persisted Quill data. Which Quill instances must be updated depends on which key was exposed: @@ -295,8 +281,7 @@ and recreate those containers. * The Dashboard API key is required for Quill's operational API. - The default Docker Compose configuration prevents startup without it. - If Quill is started another way without the key, all requests to protected operational API endpoints are rejected. + If Quill starts without the key, all requests to protected operational API endpoints are rejected. * Quill stores a salted hash in its configuration database and does not expose the original key through its dashboard or API. Keep the original value in your deployment secret store.