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
- Node.js 22, pnpm and build tools.
- The app in
/opt/verified-calls, run by its own user. .envwith the console key and your public address.- A systemd service that restarts on failure.
- Caddy as a reverse proxy with an automatic certificate.
- The console owner, the bot and your first chat.
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.1keeps the app reachable only through Caddy.- Everything else (bot token, name, chats, wallet, RPC, method) is set in the console. See Configuration.
- Keep
.envreadable 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
- Find the setup code
journalctl -u verified-calls | grep setupCode. It is printed on every start until an owner exists; a restart prints a new code. - Open the console
https://calls.example.com/admin. Enter the code, your email and a password of 12 or more characters. - Turn on two-factorConsole → Security & alerts.
- 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);
/methodologyshows it. - Daily backups running (how),
ADMIN_SECRET_KEYstored safely.