Advanced

Self-Hosting

Deploy and run your own Trunx instance with Docker, Postgres, and Redis.

Prerequisites

  • Node.js 22+
  • PostgreSQL 15+
  • Redis 7+
  • pnpm

You will also need credentials for at least one telecom provider (Twilio is the default).

Environment Setup

Create a .env file with the required variables. See the Configuration guide for the full list.

At minimum, you need:

DATABASE_URL=postgresql://user:pass@localhost:5432/trunx
REDIS_URL=redis://localhost:6379
TWILIO_ACCOUNT_SID=your_sid
TWILIO_AUTH_TOKEN=your_token
PORT=3000
BASE_URL=http://localhost:3000

For SMS, you also need TWILIO_SMS_FROM set to a Twilio phone number. For voice AI, set ULTRAVOX_API_KEY.

Installation

Clone the repository

git clone https://github.com/your-org/trunx.git
cd trunx

Set up environment variables

cp .env.example .env
# Edit .env with your credentials

Run database migrations

pnpm drizzle-kit push

This creates all required tables in your Postgres database.

Verify

curl http://localhost:3000/health

You should see a 200 OK response with the server status.

Production Deployment

The production server runs as a systemd service. A typical deploy looks like this:

# Copy files to server
scp -r . root@your-server:/root/trunx/

# Build on server
ssh root@your-server "cd /root/trunx && pnpm install && pnpm build"

# Restart the service
ssh root@your-server "systemctl restart trunx"

Verify the deployment:

# Check logs
ssh root@your-server "journalctl -u trunx -f"

# Health check
curl https://your-server.com/health

Always check logs after a restart. The service will fail to start if required environment variables are missing or if Postgres/Redis are unreachable.

Systemd Service File

If you are setting up a new server, create /etc/systemd/system/trunx.service:

[Unit]
Description=Trunx Telecom Hub
After=network.target postgresql.service redis.service

[Service]
Type=simple
User=root
WorkingDirectory=/root/trunx
ExecStart=/usr/bin/node dist/index.js
Restart=always
RestartSec=5
EnvironmentFile=/root/trunx/.env

[Install]
WantedBy=multi-user.target

Then enable and start:

systemctl daemon-reload
systemctl enable trunx
systemctl start trunx

Capacity Planning

Estimates for sustained workloads on a single server:

WorkloadCalls/DaySustained RatePeak Concurrent ChannelsRecommended Server
Low10K~0.12/sec~82 vCPU, 4 GB RAM
Medium50K~0.6/sec~424 vCPU, 16 GB RAM
High100K~2.3/sec~838 vCPU, 32 GB RAM

The bottleneck is usually SIP trunk capacity, not server resources. Postgres and Redis can handle far more throughput than a single SIP trunk provides.

For high-volume deployments (200K+ calls/day), consider splitting Asterisk onto a dedicated server and running multiple Trunx instances behind a load balancer. Redis pub/sub ensures events are shared across instances.

Monitoring

Health Endpoint

curl https://your-server.com/health

Returns 200 OK when the server is running and connected to Postgres and Redis.

Logs

journalctl -u trunx -f

Logs include request traces, provider responses, job execution, and error details.

Real-Time Events

Connect to the SSE endpoint for real-time visibility into all system activity:

curl -N -H "Authorization: Bearer tk_live_..." \
  https://your-server.com/events

Key Metrics to Watch

  • Health endpoint response time -- should be under 50ms.
  • DID health scores -- scores below 50 indicate potential spam flagging.
  • Campaign completion rate -- compare prospects attempted vs. completed.
  • Redis memory usage -- event replay and IVR cache are the main consumers.
  • Postgres connection count -- Drizzle uses a connection pool; watch for exhaustion under load.

On this page