Don’t want to read all this?
Just drop a link to https://xedant.com/agents/crm/install.md or to https://xedant.com/llms.txt into any AI chat (Claude, ChatGPT, etc.) and ask it to generate the config files and commands. It will read the docs, ask you a few questions about your setup, and hand you a ready-to-use configuration. Save time — let the model do the reading for you.
You can also reach me on Telegram — I’m always glad to help. And that’s not just politeness — I genuinely enjoy talking to like-minded people, especially if you love coding as much as I do.
CRM Agent is a CRM on your server in which an AI agent keeps the data while you watch and give commands. It deploys as a single Docker container, and a separate database is optional: by default an embedded one is already inside. Next to it, optionally, sits your Xedant Agent — then you can run the CRM by talking in chat, and without it everything except the chat with the agent works as usual.
What you will need
- A server or computer with Docker — Windows, Linux or macOS all work, and an inexpensive server is enough for permanent use.
- One free port for the interface (3990 in the examples below). A separate database is not needed: if you do not set a connection string, the product starts an embedded database by itself.
- The login and password for the first sign-in. You can set them in advance with the
CRMAGENT_LOGINandCRMAGENT_PASSWORDvariables; if you leave them unset, the administrator is the first person who registers in the interface. - A management key for the agent (
CRMAGENT_MANAGEMENT_KEY) — if you want your AI agent to change the data itself instead of you doing it by hand. Until the key is set, changes are refused, while viewing in the interface keeps working. - Optionally, the address and key of your Xedant Agent. Without them everything works except the chat with the AI agent inside the product.
Installing with Docker Compose
Create a compose.yml file with this content. There is one service here: it needs no database, so the whole product fits into a single container.
services:
crmagent:
image: xedant/crm-agent:min-latest
container_name: crmagent
ports:
- "3990:80"
volumes:
- crmagent-data:/data
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://+:80
- CRMAGENT_DATA=/data
# CRMAGENT_BASE_PATH=/crm # serve from a first-level subfolder (see ../subfolder-hosting.md)
restart: unless-stopped
sysctls:
fs.inotify.max_user_watches: "524288"
fs.inotify.max_user_instances: "512"
volumes:
crmagent-data:
Line by line, what this says and why:
image— the English build of the product with an English interface and the name “CRM Agent”.ports— the address the interface opens on:3990outside,80inside the container. The outside number can be any free port.volumes— the persistent folder/data. The database and all the data live in it, so without the volume everything disappears when the container is recreated.CRMAGENT_DATA— that same persistent folder inside the container, where the product keeps everything of its own; it is the folder mounted as the volume above.CRMAGENT_BASE_PATH— the commented line for hosting in a subfolder of the site: uncomment it if you want to open the CRM at an address likeyour-site/crm.restart— restarting after a server reboot, so the CRM comes back up by itself.sysctls— two Linux kernel settings raising the file-watching limit: without them the product notices changes in its folders worse at scale.
Then start it:
docker compose up -d
The interface appears on port 3990: http://<server-address>:3990.
Running with one command
If you would rather not keep a settings file, the same thing is done with one docker run command:
docker run -d \
--name crmagent \
-p 3990:80 \
-v crmagent-data:/data \
-e ASPNETCORE_ENVIRONMENT=Production \
-e ASPNETCORE_URLS=http://+:80 \
-e CRMAGENT_DATA=/data \
--sysctl fs.inotify.max_user_watches=524288 \
--sysctl fs.inotify.max_user_instances=512 \
--restart unless-stopped \
xedant/crm-agent:min-latest
The remaining variables are convenient to pass in a file with the --env-file .env flag — easier to change them without rewriting the long command.
Environment variables
Settings are passed through environment variables — you write them once into compose.yml and change them without touching the code. Almost all names start with CRMAGENT_; for the chat with the agent, the names are the familiar ones — without the prefix.
| Variable | What it sets |
CRMAGENT_DB | database choice. Not set — the product runs on the embedded database in the file /data/data.db; set to a connection string — it runs on PostgreSQL |
CRMAGENT_DATA | persistent data folder: the database, sign-in keys, brand settings. Default /data |
CRMAGENT_BRAND | build brand: xedant is the English build (the default), pastukhov the Russian one with the Russian product name and interface |
CRMAGENT_BASE_PATH | hosting in a subfolder of the site, for example /crm; not set — runs at the domain root |
CRMAGENT_MANAGEMENT_KEY | hash of the key your AI agent uses to manage the data over the API (these are the management addresses the agent calls). Stored as an irreversible SHA-256 sum; without it changes are refused, while viewing keeps working |
CRMAGENT_LOGIN, CRMAGENT_PASSWORD | the administrator account created at startup. If you leave them unset, the administrator is the first person who registers in the interface |
CRMAGENT_INTAKE_ALLOW_ORIGIN | the list of sites intake requests are accepted from. Not set — requests are accepted from any site; set — only from the listed ones |
CRMAGENT_COMPRESSION | server response compression. Enabled by default, =0 disables it |
CRMAGENT_JOB_KEEP_DAYS | how many days to keep finished background jobs. Default 30 |
CRMAGENT_BOOT_FULL | =1 — a full check of the database layout at startup. Useful for diagnostics, normally not needed |
CRMAGENT_SSL | issuing an HTTPS certificate for a direct address like crm.your-domain. If your proxy stands in front of the product, this variable does not need to be enabled |
AGENT_API_URL, AGENT_API_KEY | address and key of your Xedant Agent: with them the chat with the AI agent appears inside the CRM. Not set — the chat is hidden, everything else works |
Hosting in a subfolder
The product can be served not from the domain root but from a subfolder — for example, https://your-site/crm. There are two ways, and they do not mix.
- Just name the folder. Set
CRMAGENT_BASE_PATH=/crm— the product strips the prefix itself and redirects the old addresses to the new form. The domain-check service addresses (/.well-known/) stay at the root. - Hand the folder to your proxy. In this case nothing needs changing inside the container: the proxy tells the product the prefix in the
X-Forwarded-Prefixheader. This is more convenient when you already have nginx or a similar server configured.
In the second case, do not forget the live updates: they need the WebSocket upgrade headers. Two update channels work inside — the general one and the one for the chat with the agent — and both need this upgrade, otherwise the updates quietly turn into rare polling.
# WebSocket upgrade (in the common http {} block)
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name host.tld;
client_max_body_size 100m; # file uploads and pasted pictures
location /crm/ {
proxy_pass http://crmagent:80/; # the trailing slash strips the subfolder prefix
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Prefix /crm;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # live updates: /appHub and /agentChatHub
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s; # long chat answers
proxy_send_timeout 3600s;
proxy_buffering off; # streaming answers
}
}
Both ways, and the isolation check between folders, are described in the install/subfolder-hosting.md file next to the product.
First sign-in
Open the interface in a browser. If you set CRMAGENT_LOGIN and CRMAGENT_PASSWORD, sign in with those; otherwise the first person to register becomes the administrator, after which open registration closes — an outsider can no longer get into your installation. A sign-in session lives 90 days, so you will not have to log in every day. If the product stands behind your organization’s single sign-on (when an external system checks the login), users are created automatically on first visit.
Installing through Xedant MultiAgent
If you have several servers, it is more convenient to install the product from Xedant MultiAgent: it raises the container itself, provides a permanent address and HTTPS, and connects the database. CRM Agent is in the product catalogue (port 6080); the variables used are CRMAGENT_SSL, CRMAGENT_DB, CRMAGENT_BASE_URL and CRMAGENT_API_KEY, and a linked Xedant Agent connects to the chat. More about MultiAgent itself is on the MultiAgent page.
License and updates
The trial period is 30 days free, with no limits inside. Prices are the same as the neighboring products: personal
Next, take a look at Getting Started — a short tour of how the product is built and where to begin.