IPv4 & IPv6 Leasing - Any RIR, Any LocationOrder Now
Hostperl

Host AI Support Bots with pgvector on a Hostperl VPS

By Raman Kumar

Share:

Updated on Jul 30, 2026

Host AI Support Bots with pgvector on a Hostperl VPS

Start with the right VPS for the bot, not the buzzwords

If you want to host AI support bots with pgvector, start with the workload, not the model name. A support bot that answers product questions, deflects tickets, and hands off to humans needs low latency, steady memory, and one place to keep customer content.

For most teams, that points to a VPS with enough room for Node.js, PostgreSQL with pgvector, and a background worker. Hostperl’s VPS hosting is a practical fit when you want direct control over data residency, API keys, backups, and deployment timing. If you want a broader setup first, the private AI app hosting guide pairs well with this tutorial.

This walkthrough assumes a fresh server and a single public domain. You’ll install PostgreSQL, enable pgvector, run a small Node.js bot service, put Nginx in front, add SSL, and finish with smoke tests and rollback checks.

Assumptions and placeholders

Use these placeholders throughout:

  • SERVER_IP: your VPS public IP, for example 203.0.113.10
  • DOMAIN_NAME: your bot domain, for example bot.example.com
  • ADMIN_USER: your non-root sudo user, for example hostperladmin
  • APP_USER: the service account for the app, for example aiapp
  • APP_DIR: the app directory, for example /srv/ai-support-bot
  • APP_PORT: the local app port, for example 3000

You’ll use your own LLM, embedding, and ticketing API keys. Keep them in environment files, not in the repository.

Connect to the server and check the OS

On your local computer, start with SSH. If your provider gives you root access, use this form first.

ssh root@203.0.113.10

If your server already has a default non-root user, use that instead.

ssh ADMIN_USER@203.0.113.10

After you log in, check the distribution before you run package commands.

cat /etc/os-release

You should see either Ubuntu/Debian or AlmaLinux/Rocky Linux details. The next steps are split so you do not mix package managers or firewall tools.

Create a non-root admin user

If you logged in as root, create a sudo-capable admin account and keep the root session open until the new login works. That avoids lockout.

Ubuntu and Debian

On the VPS as root, create the account, add it to sudo, and prepare SSH access.

adduser ADMIN_USER
usermod -aG sudo ADMIN_USER
mkdir -p /home/ADMIN_USER/.ssh
chmod 700 /home/ADMIN_USER/.ssh
cp /root/.ssh/authorized_keys /home/ADMIN_USER/.ssh/authorized_keys
chown -R ADMIN_USER:ADMIN_USER /home/ADMIN_USER/.ssh
chmod 600 /home/ADMIN_USER/.ssh/authorized_keys

Replace ADMIN_USER with your chosen name. The account should now be able to log in with the same SSH key.

AlmaLinux and Rocky Linux

On the VPS as root, create the account, add wheel access, and copy the SSH key.

useradd -m ADMIN_USER
passwd ADMIN_USER
usermod -aG wheel ADMIN_USER
mkdir -p /home/ADMIN_USER/.ssh
chmod 700 /home/ADMIN_USER/.ssh
cp /root/.ssh/authorized_keys /home/ADMIN_USER/.ssh/authorized_keys
chown -R ADMIN_USER:ADMIN_USER /home/ADMIN_USER/.ssh
chmod 600 /home/ADMIN_USER/.ssh/authorized_keys

Open a second terminal on your computer and test the new account before you change any root-login settings.

ssh ADMIN_USER@203.0.113.10
sudo -v

Once that works, stay in the new session and use it for the rest of the installation. Keep the original root session open as a fallback.

Install PostgreSQL and pgvector for the knowledge base

Your bot needs a place to store embeddings, source chunks, and ticket metadata. PostgreSQL with pgvector is the simplest choice for audit-friendly deployments because the data stays in one database and one backup stream.

For schema planning and backup habits, Hostperl customers often cross-check the private RAG stack tutorial and the VPS backup testing guide.

Ubuntu and Debian

On the VPS as the non-root sudo user, install PostgreSQL and the extension package. Package names vary by release, so use the repo version shipped for your OS.

sudo apt update
sudo apt install -y postgresql postgresql-contrib postgresql-16-pgvector

Confirm PostgreSQL is running.

systemctl status postgresql --no-pager
psql --version

AlmaLinux and Rocky Linux

On the VPS as the non-root sudo user, install PostgreSQL and the extension package from the available repositories.

sudo dnf install -y postgresql-server postgresql-contrib pgvector
sudo postgresql-setup --initdb

Start and enable the database service, then confirm the version.

sudo systemctl enable --now postgresql
sudo systemctl status postgresql --no-pager
psql --version

Create the app database and extension

On the VPS as the non-root sudo user, create a database and a dedicated role. The app should not use the default superuser account.

sudo -iu postgres psql

Inside the PostgreSQL prompt, run the following SQL. Replace the password with a long random value.

CREATE USER aiapp WITH PASSWORD 'REPLACE_WITH_STRONG_PASSWORD';
CREATE DATABASE aisupport OWNER aiapp;
\c aisupport
CREATE EXTENSION IF NOT EXISTS vector;
\q

Back on the shell, check that the database responds.

psql "postgresql://aiapp:REPLACE_WITH_STRONG_PASSWORD@localhost:5432/aisupport" -c "SELECT extname FROM pg_extension;"

You should see vector in the output.

Install Node.js and prepare the app user

Support bots usually sit behind a Node.js API because it handles webhooks, browser traffic, and worker jobs cleanly. That fits common stacks such as Next.js front ends, NestJS APIs, and background queue processors.

If your bot will also answer site visitors or power a dashboard, the Next.js deployment guide is a useful companion.

Ubuntu and Debian

sudo apt install -y curl ca-certificates gnupg
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs build-essential
node -v
npm -v

AlmaLinux and Rocky Linux

sudo dnf install -y curl ca-certificates gcc-c++ make
curl -fsSL https://rpm.nodesource.com/setup_22.x | sudo bash -
sudo dnf install -y nodejs
node -v
npm -v

Next, create a locked-down service account and application directory.

sudo useradd --system --create-home --home-dir /home/aiapp --shell /bin/bash aiapp
sudo mkdir -p /srv/ai-support-bot
sudo chown -R aiapp:aiapp /srv/ai-support-bot

That account will own the code, the environment file, and any uploaded documents or cache files.

Build the bot service

The example below uses a small Node.js service that loads embeddings, asks your model provider for answers, and logs every request. You can swap the LLM provider later without changing the host layout.

On the VPS as the non-root sudo user, switch into the app account and initialize the project.

sudo -iu aiapp
cd /srv/ai-support-bot
npm init -y
npm install express pg dotenv openai

Create the environment file. Keep it private.

cat > /srv/ai-support-bot/.env <<'EOF'
NODE_ENV=production
APP_PORT=3000
DATABASE_URL=postgresql://aiapp:REPLACE_WITH_STRONG_PASSWORD@localhost:5432/aisupport
OPENAI_API_KEY=REPLACE_WITH_YOUR_KEY
SUPPORT_EMAIL=support@example.com
EOF
chmod 600 /srv/ai-support-bot/.env

Create the app entry file.

cat > /srv/ai-support-bot/server.js <<'EOF'
const express = require('express');
const { Pool } = require('pg');
require('dotenv').config();

const app = express();
app.use(express.json());

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

app.get('/health', async (_req, res) => {
  const result = await pool.query('SELECT NOW() AS now');
  res.json({ ok: true, database: result.rows[0].now });
});

app.post('/webhook/ticket', async (req, res) => {
  const { ticket_id, message } = req.body;
  await pool.query(
    'INSERT INTO ticket_events(ticket_id, message, created_at) VALUES ($1, $2, NOW())',
    [ticket_id, message]
  );
  res.json({ stored: true });
});

app.listen(process.env.APP_PORT || 3000, () => {
  console.log(`AI support bot listening on ${process.env.APP_PORT || 3000}`);
});
EOF

Build the table used by the webhook and smoke test it.

sudo -iu postgres psql -d aisupport -c "CREATE TABLE IF NOT EXISTS ticket_events (id bigserial PRIMARY KEY, ticket_id text NOT NULL, message text NOT NULL, created_at timestamptz NOT NULL DEFAULT NOW());"
node server.js &
sleep 3
curl -fsS http://127.0.0.1:3000/health
pkill -f 'node server.js'

If the health check returns JSON, the app can connect to PostgreSQL and serve requests.

Run it with systemd so it survives reboots

Agent workloads should start automatically after maintenance or a VPS reboot. Systemd is enough for most small and mid-sized AI hosts.

On the VPS as the non-root sudo user, create the service unit. Use the exact app directory you created above.

sudo tee /etc/systemd/system/ai-support-bot.service > /dev/null <<'EOF'
[Unit]
Description=AI Support Bot
After=network.target postgresql.service

[Service]
Type=simple
User=aiapp
WorkingDirectory=/srv/ai-support-bot
EnvironmentFile=/srv/ai-support-bot/.env
ExecStart=/usr/bin/node /srv/ai-support-bot/server.js
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

Check the unit file before you load it.

sudo systemd-analyze verify /etc/systemd/system/ai-support-bot.service
sudo systemctl daemon-reload
sudo systemctl enable --now ai-support-bot
sudo systemctl status ai-support-bot --no-pager

If the service starts cleanly, you should see an active status and no obvious environment errors.

Put Nginx in front and add TLS

Nginx gives you a stable entry point for the bot API, ticket webhooks, and any dashboard you add later. It also lets you keep the app on localhost while exposing only 80 and 443.

For customers comparing hosting paths, this is often where OpenClaw hosting and direct VPS deployment diverge: open-source PaaS is convenient, but a VPS gives you tighter control over logs, backups, and regional latency.

Install Nginx

On the VPS as the non-root sudo user, install the reverse proxy.

sudo apt install -y nginx || sudo dnf install -y nginx
nginx -v

Start and enable it.

sudo systemctl enable --now nginx
sudo systemctl status nginx --no-pager

Ubuntu and Debian firewall

sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

AlmaLinux and Rocky Linux firewall

sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Now create the site configuration.

sudo tee /etc/nginx/conf.d/ai-support-bot.conf > /dev/null <<'EOF'
server {
    listen 80;
    server_name DOMAIN_NAME;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF

Test syntax before reload.

sudo nginx -t
sudo systemctl reload nginx

Replace DOMAIN_NAME with your real hostname. A successful test means the configuration is valid.

Issue SSL with Let’s Encrypt

On the VPS as the non-root sudo user, install Certbot and request a certificate after DNS points to the VPS.

sudo apt install -y certbot python3-certbot-nginx || sudo dnf install -y certbot python3-certbot-nginx
sudo certbot --nginx -d DOMAIN_NAME

Accept the redirect prompt so HTTPS becomes the default. Then verify renewal.

sudo certbot renew --dry-run

Add pgvector-backed retrieval and cost controls

Support bots become useful when they answer from your own source material first. Store embeddings for FAQs, policy pages, and product docs in pgvector, then fetch the most relevant chunks before you call the model.

A practical way to keep spend under control is to cache repeated prompts, cap context size, and route simple FAQ lookups to a small language model. That keeps token usage visible and predictable, which matters on a VPS where you may also be paying for database storage and backups.

If you want a deeper walkthrough of a secure retrieval stack, the pgvector RAG deployment guide and the cost and latency article are the best next reads.

Verification from server and client

Finish with checks from both sides. You want to see the service running, the proxy listening, the database reachable, and the HTTPS endpoint answering.

On the VPS as the non-root sudo user, run:

sudo systemctl status ai-support-bot --no-pager
sudo ss -tulpn | grep -E ':(80|443|3000)\b'
sudo journalctl -u ai-support-bot -n 50 --no-pager
psql "$DATABASE_URL" -c "SELECT count(*) FROM ticket_events;"

On your local computer, check the public endpoint and test the webhook.

curl -fsS https://DOMAIN_NAME/health
curl -fsS -X POST https://DOMAIN_NAME/webhook/ticket \
  -H 'Content-Type: application/json' \
  -d '{"ticket_id":"TCK-1001","message":"Customer asks about reset steps"}'

Then confirm the row was stored on the server.

sudo -iu postgres psql -d aisupport -c "SELECT ticket_id, message, created_at FROM ticket_events ORDER BY created_at DESC LIMIT 1;"

Finally, reboot the VPS and check that the bot returns after boot.

sudo reboot

After reconnecting, repeat the service status and HTTPS checks. If they pass, your deployment is persistent.

Troubleshooting the most common failures

  • 502 Bad Gateway: run sudo systemctl status ai-support-bot --no-pager and sudo journalctl -u ai-support-bot -n 50 --no-pager. If the app crashed on startup, fix the .env file or the Node.js path, then restart with sudo systemctl restart ai-support-bot.
  • Nginx syntax error: run sudo nginx -t. The output shows the exact file and line number. Edit the config, then test again before reloading.
  • Database connection refused: run sudo ss -tulpn | grep 5432 and sudo systemctl status postgresql --no-pager. If PostgreSQL is down, start it with sudo systemctl start postgresql.
  • Certbot cannot issue a certificate: confirm DNS with dig DOMAIN_NAME +short and ensure ports 80 and 443 are open. Then rerun the Certbot command.
  • Webhook posts but nothing is stored: check the table with sudo -iu postgres psql -d aisupport -c "\d ticket_events". If the table is missing, recreate it and retest the POST request.

Hostperl is a sensible place to run private support bots, retrieval apps, and webhook-driven automations when you need control over cost, latency, and data placement. If you want a VPS you can grow into, start with Hostperl VPS hosting and keep your bot stack close to your customers.

For teams comparing a managed workflow, the secure AI workflow setup guide is a good follow-up.

FAQ

Can I host an AI support bot without Docker?
Yes. This tutorial uses systemd and Node.js directly, which is often simpler for small production teams that want fewer moving parts.

Is pgvector enough for a support bot knowledge base?
For many teams, yes. It keeps embeddings close to the rest of your customer data and avoids another database to patch and back up.

Should I use a VPS or a serverless platform?
Use serverless for short-lived jobs and low-ops prototypes. Use a VPS when you need persistent processes, local PostgreSQL, predictable latency, and easier audit trails.

How do I keep token spend under control?
Cache common answers, trim context aggressively, store high-confidence FAQ content in pgvector, and log every request with prompt length and model name.

What if my team also wants a dashboard?
Add a separate Next.js app or admin route behind the same Nginx server block, then keep webhook and worker traffic isolated in the app code.