Initial Setup
Get your tvaras instance running in under 15 minutes. This guide walks you through bootstrapping a fresh Linux VM, configuring credentials, and connecting your data warehouse.
Prerequisites
- A Linux VM (Ubuntu 22.04+ recommended, amd64 or arm64)
- A domain name pointing to the VM's IP address (for HTTPS)
- A valid license key — start a free 14-day trial (Google BigQuery + dbt) or contact us for a paid plan
- A GCP service account with BigQuery access (JSON key file)
- A dbt repository on GitHub or GitLab
- Google OAuth credentials for user login
Step 1: Bootstrap
SSH into your VM as root and run the bootstrap command with your license key:
curl -sL https://tvaras.ai/api/v1/license/bootstrap/TVARAS-XXXX-XXXX-XXXX-XXXX | sudo bash
This installs Docker (if needed), creates the project directory at /root/data-bot, creates the installation ID, pulls the licensed product image and takes the release files from it:
docker-compose.prod.yml— Docker service definitions (from the image)update.sh— license-gated update script (from the image)searxng/— internal search engine config (from the image).env— environment configuration (pre-filled with auto-generated secrets).env.example— reference for optional settings
Running the command again later refreshes docker-compose.prod.yml and update.sh from the current image and keeps everything else. It never starts or restarts the bot.
Step 2: Configure environment
Edit the .env file and fill in the required values:
cd /root/data-bot
nano .env
Required settings
| Variable | Description |
|---|---|
APP_URL | Your bot's public URL (e.g. https://data-bot.acme.com) |
The placeholder is single-quoted ('https://<your-domain>') — keep the quotes and replace only the text between them.
The following are auto-generated by the bootstrap script — no need to change them:
POSTGRES_PASSWORD— database passwordJWT_SECRET— session signing keyADMIN_SECRET— admin panel access keyREPO_ENCRYPTION_KEY— encryption key for stored repository tokens and credentials (back it up)ENTERPRISE_KEY— your license key (pre-filled)
The Claude API key, Google login and your company domain are collected by the setup wizard on first visit, not in .env. Optional settings are listed in .env.example.
Preparing Google OAuth
- Go to the Google Cloud Console → Credentials
- Create an OAuth 2.0 Client ID (Web application type)
- Add authorized redirect URI:
https://your-domain.com/auth/oauth/google/callback - Keep the Client ID and Client Secret ready for the setup wizard
Step 3: Set up SSL
Install a Let's Encrypt certificate for your domain:
apt-get install -y certbot
certbot certonly --standalone -d data-bot.acme.com
The certificate auto-renews via systemd timer. Nginx is configured to read certificates from /etc/letsencrypt.
Cloudflare users: the certificate request will fail if your DNS record is proxied (orange cloud) — Let's Encrypt must reach the VM directly. Set the record to DNS only (grey cloud), and make sure no zone-level redirect rule covers the subdomain. Run the certbot command before starting the bot — once nginx is running it occupies port 80.
Step 4: Start the bot
cd /root/data-bot
./update.sh
This validates your license, pulls the latest Docker image, and starts all services (PostgreSQL, the app, SearXNG, and Nginx).
Verify everything is running:
docker ps # All 5 containers should be "Up"
cd /root/data-bot && docker compose logs tvaras-backend --tail 20 # Check for startup errors
Visit https://your-domain.com — you should see the login page.
Step 5: Configure via Admin Panel
New installs start with no admin users. Seed the first admin (replace the email with yours), then log in with that Google account:
docker exec -i dbt-postgres psql -U dbt -d dbt_assistant <<'SQL'
INSERT INTO users (id, identifier, metadata, "createdAt")
VALUES (gen_random_uuid()::text, 'you@your-domain.com', '{}',
to_char(now() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'))
ON CONFLICT (identifier) DO NOTHING;
INSERT INTO user_types ("userId", type, "assignedBy", "assignedAt")
SELECT id, 'admin', 'setup', to_char(now() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
FROM users WHERE identifier = 'you@your-domain.com'
ON CONFLICT ("userId") DO UPDATE SET type = 'admin', deleted = FALSE;
SQL
Further admins can then be promoted from the admin panel. After logging in, go to the admin panel to complete setup:
5a. Connect your data warehouse
Navigate to Admin → Warehouse and upload your GCP service account JSON key. The service account needs these BigQuery roles:
- BigQuery Data Viewer — read tables and views
- BigQuery Job User — run queries
- BigQuery Metadata Viewer — list datasets and tables
Click Test Connection to verify. You should see your datasets listed.
5b. Connect your dbt repository
Navigate to Admin → Repositories and connect your dbt repository via GitHub OAuth or a personal access token. Mark it as a dbt repository type.
5c. Enable integrations (optional)
Under Admin → Connectors, enable and configure any integrations you need: Slack, Google Ads, Jira, Lightdash, and more.
Step 6: Set up automatic updates
Add a cron job to check for updates every 30 minutes:
(crontab -l 2>/dev/null; echo "*/30 * * * * cd /root/data-bot && ./update.sh >> /var/log/dbt-update.log 2>&1") | crontab -
The update script validates your license before pulling. If the license expires or is revoked, updates stop automatically. The bot continues running on the last pulled version.
Directory structure
/root/data-bot/
├── .env # Configuration (secrets)
├── .env.example # Optional settings reference (from the image)
├── docker-compose.prod.yml # Docker services (from the image; kept in sync by update.sh)
├── update.sh # License-gated update script (from the image)
├── instance_id.txt # Installation identifier — keep it through backups and rebuilds
└── searxng/
├── settings.yml
└── limiter.toml
No source code on the VM. Warehouse credentials and dbt repositories are stored encrypted in the database and configured via the admin UI.
Troubleshooting
License validation fails
curl -s -X POST https://tvaras.ai/api/v1/license/validate \
-H "Content-Type: application/json" \
-d '{"key": "TVARAS-XXXX-XXXX-XXXX-XXXX", "instance_id": "test", "hostname": "test"}'
Container won't start
cd /root/data-bot && docker compose logs tvaras-backend --tail 50
Common issues:
ENTERPRISE_KEYnot set or invalid — app exits with license errorPOSTGRES_PASSWORDmismatch — database connection fails- Port 80/443 already in use — stop conflicting service
Update script fails
cat /var/log/dbt-update.log