Skip to content
Chatvia Docs

Installation

Get in touch: Ahmad Mayahi, creator of Chatvia, Spectra and Shakomako

Chatvia is free to use, and you run it on your own servers. This page explains what you need, how to install it, the most important settings, and how to upgrade.

Where to install

We recommend a VPS: a virtual private server that you control, for example one with Ubuntu. Chatvia needs programs that run all the time next to the web server (Redis, Horizon and the WebSocket server), and a scheduler that runs every minute. On a VPS you can install all of them and keep them running. Shared web hosting cannot run them, so it does not work. Any other host works only if it can keep these programs running too.

Hosting explains what size of server to rent, and which plan to pick at each provider.

  • Install on Ubuntu sets up one VPS, step by step or with one command. This is the install we recommend.
  • Run with Docker runs every part in containers, on a VPS or on your own computer. On a VPS, it can handle HTTPS by itself.
  • Install from source is for your own computer: to try Chatvia, or to work on the code. The rest of this page is about a server that other people use.

Redis and Horizon are required

For now, Chatvia needs Redis and Laravel Horizon. There is no other choice yet:

  • Redis holds the queues, the cache, the sessions, the rate limits and the locks. The live chat history is in the cache too. It uses cache tags, which need Redis.
  • Horizon starts the queue workers and keeps them running. The worker settings in the admin panel (Settings → Platform → Queue workers) and the queue card on the Status page read from Horizon.

Other queue systems (for example a database queue or a cloud queue service) and other cache stores do not work yet. This may change in a later version.

Requirements

Software

  • PHP 8.5.12 or newer With the extensions dom, fileinfo, intl, libxml, openssl, pdo, pdo_pgsql, redis, sodium, mbstring, curl, zip, gd, exif and pcntl. Run the web app with PHP-FPM behind nginx (or another web server).
  • Composer 2 Installs the PHP packages.
  • Node.js 22.18 or newer, with npm Builds the frontend and the chat widget. The widget's build runs TypeScript files directly, which Ubuntu's own nodejs package cannot: get Node.js from NodeSource or nodejs.org.
  • Git Gets the code, and downloads the chat widget when it is built.
  • PostgreSQL 17 or 18 With the vector (pgvector) extension, and pg_textsearch for the best keyword search. See The database.
  • Redis 7 or newer Required for now Queues, cache, sessions, rate limits, locks and the live chat history. See Redis and Horizon are required.
  • Laravel Horizon Required for now Runs the queue workers. It comes with Chatvia: Composer installs it with the other PHP packages, and you keep it running (step 8).
  • A process manager Supervisor or systemd, to keep Horizon, the WebSocket server and Pulse's server stats running.
  • cron Runs the scheduler every minute.

Programs for some file types

All of them are optional. Without one, Chatvia does the work itself, or turns away only the files it cannot read.

  • poppler (pdfinfo, pdftotext) PDF files: counts their pages and finds locked ones.
  • pandoc EPUB books and Word (.docx) files.
  • catdoc (catdoc, catppt) A backup for old Word (.doc) and PowerPoint (.ppt) files.
  • ffmpeg (ffmpeg, ffprobe) Makes audio and video small enough for speech to text.
  • WeasyPrint (weasyprint) Exports a chat as PDF, and makes summaries of office files. Without it, pick another PDF maker under Settings → Platform → PDF maker.
  • pg_dump The built-in database backup.

The programs must be on the PATH of the queue worker, because files are processed in background jobs (WeasyPrint: also the web server). PowerPoint (.pptx) and Excel (.xlsx) files are read by Chatvia itself. If a program is somewhere else, enter its full path in the admin panel, under Settings → Platform → Programs.

Accounts with outside services

You need at least one chat provider and one embedding provider (the service that turns text into search vectors). With the default settings, one Scaleway API key covers both. Everything else is optional: Chatvia can read documents and split text on your own server.

The database

Chatvia searches knowledge in two ways at once: by meaning and by keywords.

  • Search by meaning needs the pgvector extension (vector). It is required.
  • Search by keywords works best with pg_textsearch, which ranks results with BM25. It is optional: without it, Chatvia uses PostgreSQL's built-in full-text search. This is what happens on most managed databases (for example Amazon RDS or Cloud SQL), where you cannot add pg_textsearch.

The easiest way is the ghcr.io/chatvia/postgres Docker image (for example the tag 18-r1). It is PostgreSQL 18 with both extensions, and it loads pg_textsearch when it starts.

If you install PostgreSQL yourself:

  1. Install pgvector, and pg_textsearch from its releases page.

  2. pg_textsearch must be loaded when PostgreSQL starts. Add it to postgresql.conf and restart PostgreSQL:

    ini
    shared_preload_libraries = 'pg_textsearch'
  3. Create a user for Chatvia and its three databases: chatvia for the app, and pulse and spectra for Pulse (the app's health, at /pulse) and Spectra (the log of AI calls, at /spectra), which keep their data apart. DB_PULSE_DATABASE and DB_SPECTRA_DATABASE in .env name the last two. The first migration runs CREATE EXTENSION, so the user needs the right to create extensions in the chatvia database the first time. Step 4 creates pulse and spectra when the user has the CREATEDB right. Without it, create them yourself, owned by the same user.

The first migration adds pg_textsearch when the server has it, and skips it when not. The admin panel's Status page shows which keyword search Chatvia uses. To add pg_textsearch to a database that runs without it, install and load it as in steps 1 and 2. Then, as a superuser, run CREATE EXTENSION pg_textsearch; in the chatvia database, and run php artisan chatvia:search:lexical-indexes.

Two .env settings change keyword search. Run php artisan chatvia:search:lexical-indexes after you change either:

Setting Meaning
SEARCH_LEXICAL_DRIVER auto (the default) uses pg_textsearch when it is there, and the built-in full-text search when not. pg_textsearch or postgres picks one.
SEARCH_TEXT_CONFIG How PostgreSQL splits text into words. The default, simple, works for every language.

Install

On Ubuntu?

Install on Ubuntu walks through every command for one Ubuntu server: PostgreSQL, Redis, nginx, HTTPS, Supervisor and cron. On a fresh Ubuntu 24.04 or 26.04 server, the installer does all of it with one command. Deploy with Deployer then deploys each release without downtime.

These steps install Chatvia in /var/www/chatvia. Run them as the user that runs PHP.

1. Get the code and the packages

bash
git clone https://github.com/chatvia/chatvia.git /var/www/chatvia
cd /var/www/chatvia

composer install --no-dev --optimize-autoloader
npm ci

2. Create the .env file

bash
cp .env.example .env
php artisan key:generate

.env.example has a short comment on every setting. Change at least these:

dotenv
APP_ENV=production
APP_DEBUG=false
APP_URL=https://chat.example.com

DB_HOST=127.0.0.1
DB_DATABASE=chatvia
DB_USERNAME=chatvia
DB_PASSWORD=a-strong-password

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=a-strong-password

REVERB_APP_ID=a-random-value
REVERB_APP_KEY=a-random-value
REVERB_APP_SECRET=a-random-value
REVERB_HOST=chat.example.com
REVERB_PORT=443
REVERB_SCHEME=https

BUILTIN_MCP_SECRET=a-long-random-value
SESSION_SECURE_COOKIE=true

You can make random values with openssl rand -hex 32. See Security settings for the rest.

Decide on the embedding storage now

EMBEDDING_VECTOR_TYPE and EMBEDDING_DIMENSIONS can only be set before step 4 creates the tables. The defaults suit almost every install. See Embedding storage.

E-mail is not set in .env: you set it up in the admin panel (step 6). It must work before other people use the server. People who sign up must confirm their e-mail address, and invitations and sign-in links are sent by e-mail.

API keys are not in .env

API keys and OAuth apps for outside services (AI providers, Firecrawl, social sign-in, Messenger/Instagram/WhatsApp, connectors, Resend, Turnstile, IP2Location) are entered in the admin panel, under Settings. They are stored encrypted in the database. .env only chooses which service to use, its address and its models.

3. Build the frontend

bash
npm run build
npm run shakomako:build

shakomako:build downloads and builds the chat widget (see The chat widget). The build reads the VITE_* values from .env (for example where the browser finds the WebSocket server). Build again after you change one of them.

4. Create the database tables

bash
php artisan chatvia:deploy:migrate
php artisan storage:link

chatvia:deploy:migrate prepares the database. It runs these steps, in order, and stops when one fails:

  1. Checks that the analytics, Pulse and Spectra databases are there, and creates any that are missing. That needs the CREATEDB right. Without it, create them by hand first (see The database).
  2. Creates the tables. The first migration installs the PostgreSQL extensions.
  3. Checks the embedding settings (see Embedding storage).
  4. Rebuilds the index for search by meaning when EMBEDDING_INDEX changed.
  5. Adds the built-in tools to the tool catalog. On a new install, this step only shows a warning: the tools need the embedding API key from step 6.

5. Create the first admin

bash
php artisan chatvia:admin:create-user [email protected] "Your Name"

The command asks for a password, so it does not end up in your shell history. The new account is an admin with its own workspace and team, so it can sign in to the dashboard (/login) and start building agents.

6. Finish the setup in the admin panel

  1. Open the admin panel at /admin and sign in with the admin account.

  2. We recommend you set up two-factor authentication with an authenticator app, under your profile.

  3. The admin panel opens with the setup of a new install. It checks the server, then asks for:

    • AI provider: the main provider and its API key. The key is checked right away.
    • Models: the chat models agents answer with, and the embedding model, which turns text into search vectors.
    • Ingestion, Voice and Storage: optional services for reading PDF and Office files and importing websites, for speech, and for where files are kept.
    • Mailer: how Chatvia sends e-mail.
    • Observability: whether Spectra keeps a log of every AI call.

    Click Finish setup. You can change all of it later under Settings (for example Settings → AI providers and Settings → Email).

7. Add the built-in tools

Finishing the setup adds Chatvia's built-in tools (charts, forms, weather, currency, web search) to the tool catalog. Each upgrade updates them (see Upgrading). If you skipped the setup, add them with:

bash
php artisan chatvia:mcp:sync-builtin

It uses your embedding provider, so it only works after step 6.

8. Start the background processes

Chatvia needs three long-running processes next to the web server, and a cron job for the scheduler:

Process Command What it does
Queue workers (Horizon) php artisan horizon Reads files and web pages, sends replies on messaging channels, analytics, exports.
WebSocket server php artisan reverb:start Live updates in the browser: ingestion progress, human handoff, typing.
Server stats php artisan pulse:check Records the server's CPU, memory and disk for the Servers card at /pulse. Without it, that card stays empty.
Scheduler * * * * * cd /var/www/chatvia && php artisan schedule:run >> /dev/null 2>&1 (cron) Clean-up, conversation analysis, statistics, backups.

Keep horizon, reverb:start and pulse:check running with Supervisor or systemd, and restart them when they stop.

Start the queue workers with Horizon only, not with php artisan queue:work. Horizon starts the workers for every queue, and the worker settings in the admin panel apply only to Horizon.

Your web server must pass WebSocket connections for the REVERB_HOST and REVERB_PORT to the Reverb server (REVERB_SERVER_HOST and REVERB_SERVER_PORT, port 8080 by default).

9. Cache the configuration

bash
php artisan config:cache
php artisan event:cache
php artisan view:cache

Run config:cache again every time you change .env.

Configuration overview

.env.example groups the settings into sections. The table shows what each section is for.

Section What it sets
App Name, URL, environment, logging.
Database PostgreSQL connection, and the names of the Pulse and Spectra databases. Analytics can move to a database of its own.
Redis, cache, sessions and queues Redis connection. Keep CACHE_STORE=redis, SESSION_DRIVER=redis and QUEUE_CONNECTION=redis: other drivers do not work yet (see Redis and Horizon are required).
Mail (local development) Only a preset that sends e-mail to Mailpit on your own computer. On a server, set up e-mail in the admin panel, under Settings → Email.
Broadcasting / Reverb The WebSocket server.
Storage Where files are kept (see Files and storage).
Workspaces Nothing: sign-up, message limits and how long conversations are kept are set in the admin panel (see Workspaces and sign-up).
AI providers Which service does each AI step.
Security Built-in tool secret, trusted proxies, cookies. The content security policy and the tool-call limits are in the admin panel, under Settings → Security. The widget's allowed sites and request limits are under Settings → Widget.
Channels, Connectors and built-in tools, Social login Only addresses and versions. The keys are in the admin panel.
Observability Error reports and the AI request log. Horizon alerts are in the admin panel, under Settings → Platform → Alerts.
Seeding, Misc The demo data for a local database, and a few small settings.
Advanced tuning Search, tools, retention and audit settings. The defaults are fine for most installs.

Workspaces and sign-up

Sign-up, message limits, what owners can do with their account and how long conversations are kept are not set in .env. Set them in the admin panel, under Settings → Workspaces:

Option Default What it does
Open sign-up On Opens the sign-up page at /register. People who sign up must confirm their e-mail address before they can use the app, so e-mail sending (Settings → Email) must work. Turn it off after you have created your accounts. You can still invite teammates.
Monthly message limit of new workspaces 0 How many agent replies a new workspace can get each month. It is applied when someone signs up. 0 means no limit.
Let owners download their data On Shows Download my data in a workspace owner's account settings.
Let owners delete their account On Shows Delete account in a workspace owner's account settings.
Days to keep conversations 366 Older conversations are deleted. With an Enterprise license, a workspace can choose fewer days in its security settings, but never more.

A change applies from the next request. Every workspace can use every feature, except four Enterprise security features that need an Enterprise license key.

To change the limit of one workspace, open Workspaces in the admin panel, open the workspace and click Set message limit. Leave the field empty for no limit. See Message limits for what is counted and what happens when a limit is reached.

Your brand

Hosted chats and widgets show a "Powered by" credit. To turn it off, add a license key in the admin panel, under License → Powered by, and switch off Show the credit. Without a license, the credit stays on.

Embedding storage

Chatvia stores a vector (an embedding) for every chunk of your knowledge, and for every tool and form, to find the ones that match a question. Two settings decide how. They are read when the tables are created and cannot change afterwards:

Setting Default What it does
EMBEDDING_VECTOR_TYPE halfvec halfvec stores 2 bytes per dimension, half the space of vector (4 bytes), with almost the same search quality.
EMBEDDING_DIMENSIONS 1024 The size of each vector. 1024 works with every embedding provider. Other sizes limit your choice.

After the migrations, php artisan chatvia:search:check-embedding-storage compares the settings with the database. It fails, with the columns that differ, when someone changed them after install. Run it after every upgrade (the Docker image does).

A third setting decides what the index for search by meaning holds. Unlike the two above, you can change it later:

Setting Default What it does
EMBEDDING_INDEX binary binary keeps 1 bit per dimension in the index. The index is about 6 times smaller, so it stays in memory longer as your knowledge grows. Search then checks the best matches against the full vectors, so the results are almost the same. full keeps the full vectors in the index. It is the largest index and the most exact.

binary works best with 1024 dimensions or more. To change it, set EMBEDDING_INDEX in .env and restart Chatvia (Docker), or run php artisan chatvia:search:vector-indexes. This rebuilds the index. With a lot of knowledge, that takes a while.

Hybrid search is different: it is a switch in the admin panel (Settings → Search → Finding answers → Hybrid search) that you can change at any time. When it is on (the default), agents search by keywords as well as by meaning.

Files and storage

Chatvia uses three storage disks:

Disk Holds Who can read it
private Knowledge files, chat attachments, images from documents, generated images and videos Only the app. Files open through signed links.
assets Profile photos, agent logos Anyone with the link
backups Database backups Only the app

With no storage settings, all three keep their files on this server, under storage/app. Run php artisan storage:link once so the public images load at /storage.

They can keep their files in S3-compatible buckets instead (AWS S3, Scaleway, Cloudflare R2, MinIO, ...). That is not an .env setting: in the admin panel under Settings → Storage, each disk picks This server or an S3-compatible bucket, with its own address and keys. The public images need a public bucket. The private files and the backups need private ones. The keys are stored encrypted in the database. Switching moves no files, so choose before people add files, or copy the files to the new place first.

Backups

The scheduler backs up the database and Redis once a day and keeps the newest 14 backups. You can change this in Settings → Backups, or make a backup now with php artisan chatvia:backup:create. The backups go on the private disk. With files on this server, the backups stay on the same server. Use S3-compatible storage for the private disk (Settings → Storage), or copy the backups somewhere else.

Hosted chat addresses

Every agent's hosted chat page lives under APP_URL, at /chat/{agent}: for example https://chat.example.com/chat/support when APP_URL is https://chat.example.com. {agent} is the agent's chat address (you can change it with Rename in the agent's sidebar) or its ID. The embed snippets in the dashboard use the ID, so they keep working after a rename. You need no extra DNS records or certificates.

With a license key, an agent can also have a domain of its own, such as help.yourshop.com. That needs a web server that gets certificates for new domains by itself. The installer sets one up: Caddy on the complete install, and on Docker with HTTPS built in. See Custom domains.

The hosted chat has its own sign-in, separate from the dashboard: signing in to a chat never signs you in to the dashboard, and the reverse.

The chat widget

The widget that customers put on their own websites is called Shakomako. It has its own repository and releases. One command downloads the newest release and builds it into public/shakomako:

bash
npm run shakomako:build

To build one chosen release instead, set SHAKOMAKO_VERSION (for example SHAKOMAKO_VERSION=v1.2.0). To build your own checkout of the widget, set SHAKOMAKO_PATH to its folder.

The built widget needs no settings of its own:

  • It loads its other files from the folder its embed.js came from.
  • It uses the /widget API on the same server.
  • It gets the live-chat (Reverb) address from the server. The server sends VITE_REVERB_HOST, VITE_REVERB_PORT and VITE_REVERB_SCHEME from .env, the same values the dashboard is built with. When they are empty, the widget connects to the same server, so your web server must forward /app/ to Reverb.

The embed snippets in the dashboard point to {APP_URL}/shakomako/embed.js. To serve the widget from somewhere else, for example a CDN, enter its address in the admin panel, under Settings → Widget → Sites and limits → Widget script address.

Other websites load these files, and the loader reads version.json with a browser request, so nginx must allow any origin for /shakomako/. A release folder never changes after it is built, so it can stay in caches for a long time:

nginx
location ^~ /shakomako/ {
    add_header Access-Control-Allow-Origin "*" always;
    add_header Cache-Control "public, max-age=31536000, immutable" always;
    try_files $uri =404;
}

location = /shakomako/embed.js {
    add_header Access-Control-Allow-Origin "*" always;
    add_header Cache-Control "public, max-age=300" always;
    try_files $uri =404;
}

location = /shakomako/version.json {
    add_header Access-Control-Allow-Origin "*" always;
    add_header Cache-Control "no-cache" always;
    try_files $uri =404;
}

Each agent has a list of websites where its widget may load. To allow a host for every agent, add it under Settings → Widget → Sites and limits → Sites every widget may load on.

Shakomako also works without Chatvia: see Shakomako, the chat widget and the backend API it expects.

Security settings

Before you open the install to other people, check these settings:

Setting Value
APP_ENV, APP_DEBUG production, false
APP_URL Your https:// address
SESSION_SECURE_COOKIE true
TRUSTED_PROXIES The IP addresses or ranges of your load balancer or CDN. Without it, every visitor has the proxy's IP address and rate limits stop working.
BUILTIN_MCP_SECRET A long random value. The built-in tools stop working while it is empty.
REVERB_APP_SECRET A long random value.
Content Security Policy (admin panel, Settings → Security → Security headers) Starts as Report only. Switch to Enforce when the reports are clean.
DB_SSLMODE require or verify-full when the database is on another server.
Open sign-up (admin panel, Settings → Workspaces) Off once your accounts exist, unless you want open sign-up.

Chat answers stream as server-sent events. Chatvia sends the header X-Accel-Buffering: no. Make sure no proxy between the app and the browser buffers the response. A streaming answer keeps one PHP-FPM worker busy until it ends, so give PHP-FPM enough workers.

Staff tools

Horizon (/horizon), Pulse (the app's health, /pulse) and the AI request log (/spectra) open only for an admin who is signed in to the admin panel. Set up two-factor authentication for every admin account.

An admin can also let the owner of one workspace open /spectra: open the workspace under Workspaces in the admin panel and click Allow Spectra access. The owner then sees the AI calls of every workspace on the install, so allow it only for an owner you trust. The workspace's teammates still cannot open it.

Upgrading

Read CHANGELOG.md of the new version first, and make a backup of the database.

bash
cd /var/www/chatvia
git pull                     # or check out the new release tag

composer install --no-dev --optimize-autoloader
npm ci
npm run build
npm run shakomako:build

php artisan chatvia:deploy:migrate

php artisan config:cache
php artisan event:cache
php artisan view:cache

php artisan horizon:terminate   # your process manager starts Horizon again
php artisan reverb:restart
php artisan pulse:restart       # your process manager starts pulse:check again

Then reload PHP-FPM, so it loads the new code.

From the first release on, migrations only move forward: a released migration is never changed. Queue workers keep running old code until they restart, which is why horizon:terminate is part of every upgrade.

Next steps

Search guides, settings and commands.