Skip to content

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.

RequirementDetails
Nexadata license keySupplied by Nexadata; used to fetch registry credentials for the Nexadata image
DockerDocker Engine or Docker Desktop
PostgresVersion 13 or newer; host, port, database, user, and password
S3-compatible storageAWS S3, MinIO, or another S3-compatible service, plus bucket names and credentials
SMTP endpointHost, port, and credentials used to send account confirmation and password reset emails
Nexadata imageLocated at docker.nexadata.com/nexadata-enterprise:latest, see below for steps to pull
HostnameA 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.

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:latest

Option 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.

  1. To start, use the following as an example .env file. You can save it as .env.selfhost:

    PUBLIC_URL=https://nexadata.example.com
    SECRET_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.com
    AWS_REGION=us-east-1
    # Set to true if using MinIO or another alternative to S3
    S3_FORCE_PATH_STYLE=true
    AWS_ACCESS_KEY_ID=<access key>
    AWS_SECRET_ACCESS_KEY=<secret key>
    FILE_MANAGER_BUCKET=nexadata-files
    STATIC_FILES_BUCKET=nexadata-static
    MAILER_ADAPTER=smtp
    SMTP_HOST=smtp.example.com
    SMTP_PORT=587
    SMTP_USERNAME=<username>
    SMTP_PASSWORD=<password>
    SMTP_TLS=always
    SMTP_AUTH=always
    MAILER_FROM_EMAIL=noreply@example.com
    INLINE_WORKER=true
    APP_NAME=Nexadata
    BUSINESS_NAME=Nexadata

    Update the values according to the configuration reference below.

  2. Set NEXADATA_IMAGE to docker.nexadata.com/nexadata-enterprise:latest and run docker login first 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.

  3. Start the stack:

    Terminal window
    docker compose --env-file .env.selfhost -f docker-compose.selfhost.yml up -d
  4. 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
  5. 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'
  6. Open http://localhost:4000 (or whatever the value you set for PUBLIC_URL if using it) and sign in with that email and password. Note that if not using PUBLIC_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:

Terminal window
docker compose --env-file .env.selfhost -f docker-compose.selfhost.yml down

Add -v to delete the database and object storage volumes as well.

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:

Terminal window
docker run -d --name nexadata \
--env-file .env.selfhost \
-p 80:4000 \
docker.nexadata.com/nexadata-enterprise:latest

The 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:

Terminal window
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.

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.

VariableRequiredDescription
PUBLIC_URLyesPublic base url for the application, including port (if not 80 or 443)
SECRET_KEY_BASEyesRandom session signing key, at least 64 bytes; openssl rand -base64 64
VAULT_KEYyesExactly 32 bytes, used to encrypt stored credentials; openssl rand -hex 16
RELEASE_COOKIEyesRandom value used by the container; openssl rand -base64 32
INLINE_WORKERyesSet to true for single-container mode
PORTnoInternal HTTP port (port inside Docker container); default 4000
POOL_SIZEnoDatabase connections per container; default 10
CSP_EXTRA_SOURCESnoComma-separated additional Content Security Policy sources, added to default-src and img-src
APP_NAMEnoSet to Nexadata by default, configurable
BUSINESS_NAMEnoSet to Nexadata by default, configurable
SUPPORT_EMAILnoSupport address shown in the application
LOGO_URLnoAbsolute URL for the email logo
MAILER_FROM_NAMEnoDefault sender name
MAILER_FROM_EMAILnoDefault sender address

Use either DATABASE_URL or the individual variables.

VariableRequiredDescription
DATABASE_URLone formpostgres://user:password@host:5432/database
DATABASE_HOSTone formDatabase hostname
DATABASE_PORTnoDefault 5432
DATABASE_USERone formDatabase user
DATABASE_PASSWORDone formDatabase password
DATABASE_NAMEone formDatabase name
DATABASE_SSLnotrue to enable TLS for individual-variable configuration

DATABASE_URL takes precedence. Add ?sslmode=require to the URL to enable TLS.

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.

VariableRequiredDescription
FILE_MANAGER_BUCKETyesPrivate bucket for uploaded files and workflow outputs
STATIC_FILES_BUCKETfor profile imagesPublicly readable bucket for profile images
AWS_ACCESS_KEY_IDyes, with caveat (see above)Access key for S3-compatible storage; omit to use an instance/task role on AWS
AWS_SECRET_ACCESS_KEYyes, with caveat (see above)Secret key for S3-compatible storage; omit to use an instance/task role on AWS
S3_ENDPOINTyes, for non-AWS storageEndpoint reachable by both the container and the user’s browser
AWS_REGIONyesStorage region, relevant for S3-compatible storage even if not on AWS
S3_FORCE_PATH_STYLEnotrue 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.

VariableDescription
LLM_PROVIDERanthropic (requires LLM_API_KEY) or bedrock (AWS credentials)
LLM_API_KEYAnthropic API key; organizations can also configure their own key in the application
LLM_MODEL, ADVANCED_LLM_MODEL, LLM_BASE_URLOptional model and gateway overrides
VariableRequiredDescription
MAILER_ADAPTERyesSet to smtp
SMTP_HOSTyesSMTP server hostname
SMTP_PORTnoDefault 587
SMTP_USERNAMEnoSMTP username
SMTP_PASSWORDnoSMTP password
SMTP_SSLnotrue for implicit TLS, usually port 465
SMTP_TLSnoalways, never, or if_available
SMTP_AUTHnoalways, never, or if_available
VariableDescription
OCR_PROVIDERnone by default in the example; textract requires AWS S3 and Textract
OTEL_EXPORTER_OTLP_ENDPOINTOptional OpenTelemetry collector endpoint

Single-container mode is not for multiple hosts. For multiple hosts, see Nexadata Production Deployment.