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:3000For 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 trunxInstall dependencies
pnpm installSet up environment variables
cp .env.example .env
# Edit .env with your credentialsRun database migrations
pnpm drizzle-kit pushThis creates all required tables in your Postgres database.
Start the server
pnpm devProduction 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/healthAlways 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.targetThen enable and start:
systemctl daemon-reload
systemctl enable trunx
systemctl start trunxCapacity Planning
Estimates for sustained workloads on a single server:
| Workload | Calls/Day | Sustained Rate | Peak Concurrent Channels | Recommended Server |
|---|---|---|---|---|
| Low | 10K | ~0.12/sec | ~8 | 2 vCPU, 4 GB RAM |
| Medium | 50K | ~0.6/sec | ~42 | 4 vCPU, 16 GB RAM |
| High | 100K | ~2.3/sec | ~83 | 8 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/healthReturns 200 OK when the server is running and connected to Postgres and Redis.
Logs
journalctl -u trunx -fLogs 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/eventsKey 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.
Campaigns & Bulk Calling/SMS
How the campaign dialer works internally — job queues, rate limiting, DID selection, guardrails, health feedback, SMS drip pacing, and where things break at scale.
Compliance
TCPA, DNC, 10DLC, STIR/SHAKEN, CNAM, caller registry, and answering machine detection -- how Trunx enforces compliance and maximizes answer rates.