To deploy applications with eda, you need an active Explita Deploy host server. This guide covers how to provision a fresh Linux VPS (Ubuntu, Debian, Fedora, or Rocky Linux) using either our automated one-line installer or a detailed manual step-by-step installation, followed by configuring your local developer machine.
The automated script configures Docker Engine, Node.js 24 LTS, pnpm, PM2, Caddy, managed PostgreSQL, persistent storage directories, and generates secure cryptographic keys. It is completely idempotent—safe to run on fresh servers or rerun anytime to pull updates without touching existing databases.
You can customize the installation directory, branch, or repository by passing environment variables:
# Example: Deploying from a specific branch or custom install directoryINSTALL_DIR=/opt/explita/deploy BRANCH=main sudo -E bash -c \ "$(curl -fsSL https://raw.githubusercontent.com/explita/deploy-server/main/scripts/setup.sh)"
System Packages: Updates package repos and installs curl, git, openssl, tar, and gzip.
Docker Engine: Installs official Docker Engine, enables the docker service, adds your user to the docker group, and creates the internal bridge network explita-net.
Node.js & Tooling: Installs Node.js 24 LTS, pnpm 12, and the PM2 process manager globally.
Storage Hierarchy: Creates persistent host directories under /var/lib/explita/ with locked-down permissions:
/var/lib/explita/postgres (database data)
/var/lib/explita/redis (in-memory state)
/var/lib/explita/caddy/apps & /var/lib/explita/caddy/data (reverse proxy configs and TLS certificates)
/var/lib/explita/deployments (source archives and active releases)
Infrastructure Containers:
Launches explita-caddy with dynamic API enabled on http://127.0.0.1:2019.
Launches explita-postgres on explita-net with persistent storage.
Configuration (.env): Generates random cryptographically secure keys:
APP_ENCRYPTION_KEY: 64-character hex key for encrypting environment variables.
DEPLOY_TOKEN: Secret authentication bearer token required by the CLI.
POSTGRES_ROOT_PASSWORD: Secure root credentials for the managed database.
(See .env.example for all optional server settings).
Database Sync & Build: Runs prisma db push to initialize SQLite/PostgreSQL internal schemas, builds the TypeScript server, and launches it under PM2 with system boot persistence.
Once completed, the script prints your DEPLOY_TOKEN and instructions on how to bind your local CLI.
Install Docker using the official automated installer:
curl -fsSL https://get.docker.com | sudo shsudo systemctl enable --now docker# Add your current user to the docker groupsudo usermod -aG docker $USER# Activate docker group in current shell (or reconnect via SSH)newgrp docker# Create the dedicated Docker bridge network for Explitadocker network create explita-net
Generate production cryptographic keys and create .env:
if [ -f .env ]; then echo "Error: .env file already exists. Aborting to protect existing keys and data!"else ENCRYPTION_KEY=$(openssl rand -hex 32) DEPLOY_TOKEN=$(openssl rand -hex 24) POSTGRES_PASS=$(openssl rand -hex 24) cat <<EOF > .envAPP_ENCRYPTION_KEY=${ENCRYPTION_KEY}DATA_DIR=/var/lib/explitaPOSTGRES_ROOT_PASSWORD=${POSTGRES_PASS}PORT=39756HOST=0.0.0.0DEPLOY_TOKEN=${DEPLOY_TOKEN}LOG_INFO=falseMAX_REQUEST_BODY_SIZE=100MBIMAGE_RETENTION_LIMIT=3CRON_HISTORY_LIMIT=50REDIS_ENABLED=falseTUNNEL_ENABLED=trueEOF chmod 600 .env echo ".env created successfully."fi
[!NOTE]
Save your DEPLOY_TOKEN and POSTGRES_ROOT_PASSWORD in a secure password manager. The DEPLOY_TOKEN is required by developers to authenticate their CLI with this host.
[!CAUTION]
Do NOT re-generate or overwrite .env after initial setup.
Changing APP_ENCRYPTION_KEY will permanently prevent decryption of existing secrets and credentials stored in the database.
Changing POSTGRES_ROOT_PASSWORD will cause database connection failures because PostgreSQL's data volume (/var/lib/explita/postgres) is initialized once with the original password.
Changing DEPLOY_TOKEN will immediately invalidate all developer CLI connections and CI/CD pipelines.
[!TIP]
Full Environment Variable Reference:
For the complete list of server options—including optional 2FA (DEPLOY_2FA_SECRET), static PINs (DEPLOY_PASSCODE), server-wide S3 off-site backups (GLOBAL_S3_*), custom ports, and Redis authentication—see the fully annotated .env.example file in the repository.
Install dependencies and compile the TypeScript control plane:
# Install dependenciespnpm install# Build TypeScript serverpnpm build# Optional: Auto-provision preview tunnel token (for branch preview URLs)sudo bash scripts/setup-tunnel.sh --auto# Launch server with PM2 using production ecosystem configpm2 start ecosystem.config.cjspm2 save# Configure PM2 systemd startup for reboot persistencesudo env PATH=$PATH:/usr/bin pm2 startup systemd -u $USER --hp $HOME
[!IMPORTANT]
Automatic Infrastructure Provisioning: When the control plane boots, it automatically provisions the explita-caddy reverse proxy container on ports 80 and 443, initializes the managed postgres container on explita-net, synchronizes internal database schemas, and starts background schedulers. You do not need to run docker run for Caddy or PostgreSQL manually.
Opening host ports is not enough if your cloud provider enforces an external virtual firewall (Security Groups / VCN Security Lists). Ensure inbound rules allow:
39756/tcp: Explita Deploy control plane API
80/tcp: HTTP and automatic ACME SSL certificate challenges
443/tcp: HTTPS traffic for deployed applications
[!TIP]
On Oracle Cloud (OCI), navigate to: Networking > Virtual Cloud Networks > [Your VCN] > Security Lists > Default Security List > Add Ingress Rules
Add an ingress rule with Source CIDR: 0.0.0.0/0, IP Protocol: TCP, and Destination Port Range: 39756, 80, 443.
[!NOTE]
First Run Startup Delay (30–90 seconds):
On the very first startup, Explita Deploy pulls the required caddy:2-alpine and postgres:17-alpine Docker images, waits for PostgreSQL to become fully ready, and automatically applies Prisma database migrations.
If curl does not respond immediately, monitor initialization progress in real time:
pm2 logs explita-deploy
Verify that the Explita Deploy control plane is healthy and responding:
Configure your server endpoint and deployment token:
# Set your server address (IP with port 39756 or custom reverse-proxy domain)eda config set server http://<your-server-ip>:39756# Set your authentication token (the DEPLOY_TOKEN from your server's .env)eda config set token <your-deploy-token>
If you configured DEPLOY_PASSCODE in your server /opt/explita/deploy/.env for two-factor protection, passcodes are strictly forbidden from being saved to configuration files (you only know them in your head).
When running sensitive or administrative commands, the CLI interactively prompts for your PIN:
🔑 Enter deploy passcode / PIN:
Or you can pass it inline in memory for that single command invocation without saving it to disk: