Verified Calls docs
v1.0.0
Live demo Get help
● Start · Production

Installation
your own server, with HTTPS.

A complete production install on an Ubuntu VPS: a system user, the app as a systemd service and Caddy in front for automatic HTTPS. Any Linux host with a persistent disk works the same way.

01What you will set up

  1. Node.js 22, pnpm and build tools.
  2. The app in /opt/verified-calls, run by its own user.
  3. .env with the console key and your public address.
  4. A systemd service that restarts on failure.
  5. Caddy as a reverse proxy with an automatic certificate.
  6. The console owner, the bot and your first chat.
Not tested here

These are standard Ubuntu procedures and were not run on a Linux server while writing these docs. The app commands themselves (pnpm install, pnpm start) were tested.

02Prepare the server

# Node.js 22 (NodeSource), pnpm and build tools
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs build-essential python3 sqlite3
sudo npm install -g pnpm
# a user for the service
sudo useradd --system --create-home --home-dir /opt/verified-calls --shell /usr/sbin/nologin verified-calls

03Install the app

# upload the package, then:
sudo unzip verified-calls.zip -d /opt/verified-calls
sudo chown -R verified-calls:verified-calls /opt/verified-calls
cd /opt/verified-calls
sudo -u verified-calls pnpm install --frozen-lockfile
sudo -u verified-calls cp .env.example .env

Adjust the unzip path so that package.json ends up directly in /opt/verified-calls.

04Fill in .env

Open /opt/verified-calls/.env and set at least:

ADMIN_SECRET_KEY=output of: openssl rand -hex 32
PUBLIC_BASE_URL=https://calls.example.com
HOST=127.0.0.1
PORT=8787
  • HOST=127.0.0.1 keeps the app reachable only through Caddy.
  • Everything else (bot token, name, chats, wallet, RPC, method) is set in the console. See Configuration.
  • Keep .env readable only by the service: sudo chmod 600 .env.

05Run it as a service

# /etc/systemd/system/verified-calls.service
[Unit]
Description=Verified Calls
After=network-online.target

[Service]
WorkingDirectory=/opt/verified-calls
ExecStart=/usr/bin/env pnpm start
Restart=always
User=verified-calls
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now verified-calls
journalctl -u verified-calls -f      # follow the log

On SIGINT or SIGTERM the process stops the bot, finishes the running job, closes the web server and closes the database cleanly. A second signal exits at once.

06HTTPS with Caddy

# /etc/caddy/Caddyfile
calls.example.com {
    reverse_proxy 127.0.0.1:8787
}
sudo systemctl reload caddy

Point the domain's DNS A record at the server first; Caddy then gets the certificate by itself. nginx works too: forward to 127.0.0.1:8787.

07Create the console owner

  1. Find the setup codejournalctl -u verified-calls | grep setupCode. It is printed on every start until an owner exists; a restart prints a new code.
  2. Open the consolehttps://calls.example.com/admin. Enter the code, your email and a password of 12 or more characters.
  3. Turn on two-factorConsole → Security & alerts.
  4. Set the basicsConsole → Get started: product name, accent colour, support email, public address and the bot token (with Test). See Admin console.

08Bot and first chat

Follow Telegram bot → Setup: privacy mode off, add the bot, approve the chat under Monitor → Chats, then switch off "allow groups" in @BotFather so strangers cannot add your bot.

09Go-live checklist

  • Console → Monitor → Status: every check green, "A chat is recording" and "Public address is https" included.
  • A test call appears on the site within about a minute.
  • Seal chats set (Telegram → Chats the seals are posted to) and the first seal posted.
  • Operator wallet set (Proof) and the first seal anchored from Monitor → Seals.
  • Scoring method decided before you publish (Method); /methodology shows it.
  • Daily backups running (how), ADMIN_SECRET_KEY stored safely.