Nexadata Self-Hosted Quickstart
This guide runs Nexadata as a single container. The container applies database migrations and then starts the application. Use this mode for evaluation while you get familiar with running Nexadata in your environment.
For larger deployments, see Nexadata Production Deployment.
What You Need
Section titled “What You Need”| Requirement | Details |
|---|---|
| Nexadata license key | Supplied by Nexadata; used to fetch registry credentials for the Nexadata image |
| Docker | Docker Engine or Docker Desktop |
| Postgres | Version 13 or newer; host, port, database, user, and password |
| S3-compatible storage | AWS S3, MinIO, or another S3-compatible service, plus bucket names and credentials |
| SMTP endpoint | Host, port, and credentials used to send account confirmation and password reset emails |
| Nexadata image | Located at docker.nexadata.com/nexadata-enterprise:latest, see below for steps to pull |
| Hostname | A public or private hostname for the application; use TLS for production |
The application never reads or writes email directly. It requires an SMTP endpoint for platform email.
Nexadata Docker Image
Section titled “Nexadata Docker Image”First, you must use your Nexadata license key to fetch credentials to be able to download the Nexadata Docker image.
curl -s -X POST https://license.nexadata.com/ \ -H "x-license-key: YOUR_LICENSE_KEY" \ -H "Content-Type: application/json"Your response will look something like this:
{ "username": "AWS", "password": "<12h token>", "registry": "<registry>", "expires_at": 1730000000, "docker_config_json": { "auths": { "<registry>": { "auth": "..." } } }}Next, you will need to perform a docker command to login with the supplied credentials:
docker login docker.nexadata.com \ -u AWS \ -p <password-from-response>From here, you may now pull the latest Nexadata Docker image:
docker pull docker.nexadata.com/nexadata-enterprise:latestOption 1: Docker Compose (Fastest Evaluation)
Section titled “Option 1: Docker Compose (Fastest Evaluation)”The supplied Compose file runs Nexadata, Postgres, and MinIO on one host. It is intended for evaluation; you still need to supply SMTP settings.
-
To start, use the following as an example
.envfile. You can save it as.env.selfhost:PUBLIC_URL=https://nexadata.example.comSECRET_KEY_BASE=<random 64-byte value>VAULT_KEY=<random 32-byte value>RELEASE_COOKIE=<random value>DATABASE_URL=postgres://user:password@db.example.com:5432/nexadata# Omit S3_ENDPOINT for AWS S3.S3_ENDPOINT=https://s3.example.comAWS_REGION=us-east-1# Set to true if using MinIO or another alternative to S3S3_FORCE_PATH_STYLE=trueAWS_ACCESS_KEY_ID=<access key>AWS_SECRET_ACCESS_KEY=<secret key>FILE_MANAGER_BUCKET=nexadata-filesSTATIC_FILES_BUCKET=nexadata-staticMAILER_ADAPTER=smtpSMTP_HOST=smtp.example.comSMTP_PORT=587SMTP_USERNAME=<username>SMTP_PASSWORD=<password>SMTP_TLS=alwaysSMTP_AUTH=alwaysMAILER_FROM_EMAIL=noreply@example.comINLINE_WORKER=trueAPP_NAME=NexadataBUSINESS_NAME=NexadataUpdate the values according to the configuration reference below.
-
Set
NEXADATA_IMAGEtodocker.nexadata.com/nexadata-enterprise:latestand rundocker loginfirst if the image is in a private registry. Replace the example secrets and, if using your own services, the Postgres, S3-compatible storage (such as MinIO), and SMTP values. -
Start the stack:
Terminal window docker compose --env-file .env.selfhost -f docker-compose.selfhost.yml up -d -
Follow the application log until it reports that it is running:
Terminal window docker compose --env-file .env.selfhost -f docker-compose.selfhost.yml logs -f nexadata -
Create the initial organization and admin user:
Terminal window docker compose --env-file .env.selfhost -f docker-compose.selfhost.yml \exec nexadata ./bootstrap \--email admin@example.com \--password 'ChangeMe123!' \--org 'Your Organization' -
Open http://localhost:4000 (or whatever the value you set for
PUBLIC_URLif using it) and sign in with that email and password. Note that if not usingPUBLIC_URL, the relevant port here is the port that your docker container is listening on.
The bootstrap command creates the database and loads the schema when needed, applies migrations, and is idempotent. It does not reset an existing admin password.
To stop the stack:
docker compose --env-file .env.selfhost -f docker-compose.selfhost.yml downAdd -v to delete the database and object storage volumes as well.
Option 2: Run the Standalone Container
Section titled “Option 2: Run the Standalone Container”If you want to run the container without Docker Compose, you’ll also need to run the required services separately (a Postgres database and an S3-compatible storage backend like MinIO).
Create an environment file using the above .env.selfhost example as a starting template. Configure those values accordingly.
Then start the container:
docker run -d --name nexadata \ --env-file .env.selfhost \ -p 80:4000 \ docker.nexadata.com/nexadata-enterprise:latestThe container applies database migrations before starting the application. The bootstrap command can also create the database and load the schema if you run it before the application starts. Create the initial admin with:
docker exec nexadata ./bootstrap \ --email admin@example.com \ --password 'ChangeMe123!' \ --org 'Your Organization'You can pass settings with -e KEY=value instead of an environment file.
Configuration
Section titled “Configuration”The most common settings are below. Blank values are treated as unset. Invalid or missing required values are reported in the container log at startup.
Application
Section titled “Application”| Variable | Required | Description |
|---|---|---|
PUBLIC_URL | yes | Public base url for the application, including port (if not 80 or 443) |
SECRET_KEY_BASE | yes | Random session signing key, at least 64 bytes; openssl rand -base64 64 |
VAULT_KEY | yes | Exactly 32 bytes, used to encrypt stored credentials; openssl rand -hex 16 |
RELEASE_COOKIE | yes | Random value used by the container; openssl rand -base64 32 |
INLINE_WORKER | yes | Set to true for single-container mode |
PORT | no | Internal HTTP port (port inside Docker container); default 4000 |
POOL_SIZE | no | Database connections per container; default 10 |
CSP_EXTRA_SOURCES | no | Comma-separated additional Content Security Policy sources, added to default-src and img-src |
APP_NAME | no | Set to Nexadata by default, configurable |
BUSINESS_NAME | no | Set to Nexadata by default, configurable |
SUPPORT_EMAIL | no | Support address shown in the application |
LOGO_URL | no | Absolute URL for the email logo |
MAILER_FROM_NAME | no | Default sender name |
MAILER_FROM_EMAIL | no | Default sender address |
Postgres
Section titled “Postgres”Use either DATABASE_URL or the individual variables.
| Variable | Required | Description |
|---|---|---|
DATABASE_URL | one form | postgres://user:password@host:5432/database |
DATABASE_HOST | one form | Database hostname |
DATABASE_PORT | no | Default 5432 |
DATABASE_USER | one form | Database user |
DATABASE_PASSWORD | one form | Database password |
DATABASE_NAME | one form | Database name |
DATABASE_SSL | no | true to enable TLS for individual-variable configuration |
DATABASE_URL takes precedence. Add ?sslmode=require to the URL to enable TLS.
S3-Compatible Storage
Section titled “S3-Compatible Storage”Two variables of particular importance are AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. When not running the application on AWS, these variables are still required, as they serve as keys for most S3-compatible storage options that you would run yourself (i.e. MinIO). These variables are required unless you are running on AWS and use instance role authentication.
| Variable | Required | Description |
|---|---|---|
FILE_MANAGER_BUCKET | yes | Private bucket for uploaded files and workflow outputs |
STATIC_FILES_BUCKET | for profile images | Publicly readable bucket for profile images |
AWS_ACCESS_KEY_ID | yes, with caveat (see above) | Access key for S3-compatible storage; omit to use an instance/task role on AWS |
AWS_SECRET_ACCESS_KEY | yes, with caveat (see above) | Secret key for S3-compatible storage; omit to use an instance/task role on AWS |
S3_ENDPOINT | yes, for non-AWS storage | Endpoint reachable by both the container and the user’s browser |
AWS_REGION | yes | Storage region, relevant for S3-compatible storage even if not on AWS |
S3_FORCE_PATH_STYLE | no | true for MinIO and most S3-compatible services |
The Docker Compose stack creates the buckets for you. Otherwise, the buckets must already exist. The S3-compatible endpoint must be reachable by both the container and the browser because workflow downloads and profile-image uploads use URLs generated by the application. Browser uploads require the static bucket to allow POST from the application origin.
AI and LLM Features
Section titled “AI and LLM Features”| Variable | Description |
|---|---|
LLM_PROVIDER | anthropic (requires LLM_API_KEY) or bedrock (AWS credentials) |
LLM_API_KEY | Anthropic API key; organizations can also configure their own key in the application |
LLM_MODEL, ADVANCED_LLM_MODEL, LLM_BASE_URL | Optional model and gateway overrides |
| Variable | Required | Description |
|---|---|---|
MAILER_ADAPTER | yes | Set to smtp |
SMTP_HOST | yes | SMTP server hostname |
SMTP_PORT | no | Default 587 |
SMTP_USERNAME | no | SMTP username |
SMTP_PASSWORD | no | SMTP password |
SMTP_SSL | no | true for implicit TLS, usually port 465 |
SMTP_TLS | no | always, never, or if_available |
SMTP_AUTH | no | always, never, or if_available |
Optional Features
Section titled “Optional Features”| Variable | Description |
|---|---|
OCR_PROVIDER | none by default in the example; textract requires AWS S3 and Textract |
OTEL_EXPORTER_OTLP_ENDPOINT | Optional OpenTelemetry collector endpoint |
Single-container mode is not for multiple hosts. For multiple hosts, see Nexadata Production Deployment.