Installation
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,exifandpcntl. 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
nodejspackage 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, andpg_textsearchfor 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_dumpThe 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:
-
Install pgvector, and pg_textsearch from its releases page.
-
pg_textsearch must be loaded when PostgreSQL starts. Add it to
postgresql.confand restart PostgreSQL:inishared_preload_libraries = 'pg_textsearch' -
Create a user for Chatvia and its three databases:
chatviafor the app, andpulseandspectrafor Pulse (the app's health, at/pulse) and Spectra (the log of AI calls, at/spectra), which keep their data apart.DB_PULSE_DATABASEandDB_SPECTRA_DATABASEin.envname the last two. The first migration runsCREATE EXTENSION, so the user needs the right to create extensions in thechatviadatabase the first time. Step 4 createspulseandspectrawhen the user has theCREATEDBright. 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
git clone https://github.com/chatvia/chatvia.git /var/www/chatvia
cd /var/www/chatvia
composer install --no-dev --optimize-autoloader
npm ci2. Create the .env file
cp .env.example .env
php artisan key:generate.env.example has a short comment on every setting. Change at least these:
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=trueYou 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
npm run build
npm run shakomako:buildshakomako: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
php artisan chatvia:deploy:migrate
php artisan storage:linkchatvia:deploy:migrate prepares the database. It runs these steps, in
order, and stops when one fails:
- Checks that the analytics, Pulse and Spectra databases are there, and
creates any that are missing. That needs the
CREATEDBright. Without it, create them by hand first (see The database). - Creates the tables. The first migration installs the PostgreSQL extensions.
- Checks the embedding settings (see Embedding storage).
- Rebuilds the index for search by meaning when
EMBEDDING_INDEXchanged. - 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
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
-
Open the admin panel at
/adminand sign in with the admin account. -
We recommend you set up two-factor authentication with an authenticator app, under your profile.
-
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:
php artisan chatvia:mcp:sync-builtinIt 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
php artisan config:cache
php artisan event:cache
php artisan view:cacheRun 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:
npm run shakomako:buildTo 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.jscame from. - It uses the
/widgetAPI on the same server. - It gets the live-chat (Reverb) address from the server. The server sends
VITE_REVERB_HOST,VITE_REVERB_PORTandVITE_REVERB_SCHEMEfrom.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:
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.
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 againThen 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
- Embed the widget on a website.
- Messaging channels: WhatsApp, Microsoft Teams, Instagram. The Meta app for Messenger, Instagram and WhatsApp is set up in the admin panel, under Settings → Channels.