Skip to main content

Installation Hardening Guide

scripts/install.sh installs Quixa with secure defaults. This page lists what those defaults are and what you should configure for your environment.

Defaults you get

  • Pinned images: every container image has an exact version; Quixa images use the release tag you install (never latest). The air-gap bundle contains SHA256SUMS (optionally GPG-signed) and the image digests.
  • Non-root containers with a read-only root file system (read_only, no-new-privileges) for the API, web app and script sandbox.
  • Only ports 3002 and 5001 (and 3003 when Metabase is installed) are published. SQL Server and the script sandbox are not.
  • Least-privilege database logins: the API uses quixa_app (Quixa database only: read, write, schema changes); Metabase uses quixa_reporting (read-only).
  • Generated secrets in /opt/quixa/.env (root only, chmod 600): SQL passwords, JWT signing key (48 random bytes), resolver token, Metabase admin password, backup key.
  • Production mode: Swagger and the Hangfire dashboard are off; internal error details are not returned; CORS allows only your web app origin.
  • Sign-in: 15-minute access tokens with rotating refresh tokens; sessions end after 60 minutes idle or 12 hours; accounts lock for 15 minutes after 5 wrong passwords. Users normally sign in through your directory (LDAP / Entra ID), which also enforces MFA; an authenticator app for local (break-glass) administrators can be switched on (see the settings reference).

Before production

1. TLS in front of Quixa

Put Quixa behind your reverse proxy or load balancer (nginx, F5, HAProxy) and terminate HTTPS there. Forward X-Forwarded-Proto. Set FRONTEND_ORIGIN and API_BASE_URL in .env to the HTTPS addresses. Allow only TLS 1.2+.

2. Firewall

Block everything else outbound from the VM.

3. Which internal APIs flows may call

Private addresses are blocked by default. Set the range of the APIs under test:
Cloud metadata (169.254.169.254), link-local, loopback and the Docker network stay blocked whatever you set. Workspace administrators can further restrict destinations (deny lists, allow-list-only mode) in Backoffice → Security & Audit and test a URL there. If your internal APIs use certificates from a private CA, answer yes to the CA question in the installer (or set Security__Outbound__TrustedCaCertificatesPath to a PEM file). Host names are still checked; there is no “accept any certificate” option.

4. SQL Server certificate

The bundled SQL Server uses a self-signed certificate (connections are encrypted, DB_TRUST_SERVER_CERTIFICATE=True). To use a CA-issued certificate, mount it into the quixa-db container (/var/opt/mssql/certs), configure mssql.conf (tlscert, tlskey, forceencryption = 1) and set DB_TRUST_SERVER_CERTIFICATE=False.

5. Key protection

Credentials are encrypted with ASP.NET Data Protection; the key ring is stored in the database. Encrypt the key ring itself with a certificate or Azure Key Vault:
Back up the certificate separately: without it, stored credentials cannot be decrypted.

6. SIEM

Each event is one JSON document (timestamp, tenantId, category, action, outcome, actor, target, client, details). Administrators can also export the audit log as JSON lines or CSV in the Backoffice.

7. Backups

Store backup.key offline (and the Data Protection certificate, if used). Test a restore on a separate VM at least once per quarter.

8. Rotating secrets

JWT_SECRET: change it in .env and run quixa-ctl restart (everyone signs in again). SA_PASSWORD: change it in SQL Server (ALTER LOGIN sa WITH PASSWORD = ...), then in .env.

9. Retention

Executions (with request and response data) are deleted after 90 days and audit events after 365 days by default. Workspace administrators can change this in Security & Audit (audit events: at least 90 days). DataRetention__ExecutionRetentionDays / DataRetention__AuditRetentionDays set the installation defaults. Deleting a tenant in the Backoffice removes all of its data.

Upgrading Metabase from v0.51

Releases from October 2026 ship Metabase v0.64.4 (v0.51 has critical vulnerabilities). Metabase’s H2 database from v0.51 does not migrate to v0.64 in place. Metabase holds no Quixa data (only its own users and the dashboards that quixa-metabase-setup creates), so start it on a new volume:
Export custom dashboards you built yourself before upgrading and import them afterwards.

Settings reference