-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
Complete configuration reference for the Dissensus AI Debate Engine.
Create a .env file in the dissensus-engine/ directory. The engine reads these at startup.
| Variable | Description | Default | Required |
|---|---|---|---|
PORT |
HTTP port the server listens on | 3000 |
No |
NODE_ENV |
Environment mode (production or development) |
development |
No |
TRUST_PROXY |
Trust reverse proxy (nginx). Set to 0 only if Node listens directly on public internet |
1 |
No |
TRUST_PROXY_HOPS |
Number of proxy hops to trust | 1 |
No |
DEBATE_OF_THE_DAY_TZ |
Timezone for "Debate of the Day" feature | UTC |
No |
At least one API key is required for the server to function. When server-side keys are configured, visitors can use the app without providing their own keys.
| Variable | Description | Required |
|---|---|---|
DEEPSEEK_API_KEY |
DeepSeek API key (cheapest, ~$0.008/debate) | At least one |
OPENAI_API_KEY |
OpenAI API key (~$0.02-0.15/debate) | At least one |
GEMINI_API_KEY or GOOGLE_API_KEY
|
Google Gemini API key (free tier available) | At least one |
# Server Configuration
PORT=3000
NODE_ENV=production
# Trust proxy (nginx) - keep enabled for VPS deployments
TRUST_PROXY=1
TRUST_PROXY_HOPS=1
# Timezone for "Debate of the Day"
DEBATE_OF_THE_DAY_TZ=America/New_York
# API Keys - Add any providers you want
DEEPSEEK_API_KEY=sk-your-deepseek-key
OPENAI_API_KEY=sk-your-openai-key
GEMINI_API_KEY=AIza-your-gemini-keyThe /api/debate/stream endpoint requires special configuration to disable buffering:
location /api/debate/stream {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
proxy_set_header Connection '';
# CRITICAL for SSE streaming — disable all buffering
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding off;
# Long timeout for debates (they can take 5+ minutes)
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
⚠️ Warning: Withoutproxy_buffering off, Nginx will buffer SSE responses and the debate won't stream in real-time.
| Directive | Value | Purpose |
|---|---|---|
proxy_read_timeout |
600s |
Time to wait for data from upstream |
proxy_send_timeout |
600s |
Time to wait for client to receive data |
proxy_connect_timeout |
60s |
Time to establish connection |
Add these to all server blocks:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;Serve static files directly from Nginx for better performance:
location /css/ {
alias /home/dissensus/dissensus-engine/public/css/;
expires 7d;
add_header Cache-Control "public, immutable";
}
location /js/ {
alias /home/dissensus/dissensus-engine/public/js/;
expires 7d;
add_header Cache-Control "public, immutable";
}
location /images/ {
alias /home/dissensus/dissensus-engine/public/images/;
expires 30d;
add_header Cache-Control "public, immutable";
}Enable compression for text-based responses:
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml;After running Certbot, your config will include:
server {
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/app.dissensus.fun/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.dissensus.fun/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = app.dissensus.fun) {
return 301 https://$host$request_uri;
}
listen 80;
listen [::]:80;
server_name app.dissensus.fun;
return 404;
}Rate limits are configured in server/index.js:
const debateLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute window
max: isProd ? 10 : 100, // 10 debates/min in prod, 100 in dev
message: { error: 'Too many debates. Please wait a minute and try again.' },
standardHeaders: true, // Send RateLimit-* headers
legacyHeaders: false // Disable X-RateLimit-* headers
});| Endpoint | Production | Development |
|---|---|---|
| Debate streaming | 10/min | 100/min |
| Card generation | 20/min | 100/min |
| Metrics | 120/min | 300/min |
For rate limiting to work correctly behind Nginx, enable trust proxy:
TRUST_PROXY=1
TRUST_PROXY_HOPS=1If running without a reverse proxy (not recommended for production):
TRUST_PROXY=0| Provider | Default Model | Cost per Debate |
|---|---|---|
| DeepSeek | deepseek-chat |
~$0.008 |
| OpenAI | gpt-4o |
~$0.15 |
| OpenAI | gpt-4o-mini |
~$0.02 |
| Gemini | gemini-2.0-flash |
~$0.006 (free tier available) |
| Gemini | gemini-2.5-flash |
~$0.03 |
DeepSeek:
-
deepseek-chat- DeepSeek V3.2
OpenAI:
-
gpt-4o- GPT-4o (best quality) -
gpt-4o-mini- GPT-4o Mini (faster, cheaper)
Gemini:
-
gemini-2.0-flash- Gemini 2.0 Flash (fastest) -
gemini-2.5-flash- Gemini 2.5 Flash (enhanced) -
gemini-2.5-flash-lite- Gemini 2.5 Flash-Lite (lightweight)
Via query parameter:
GET /api/debate/stream?topic=...&provider=deepseek&model=deepseek-chat
If no provider is specified, defaults to:
-
deepseekwithdeepseek-chat -
geminiwithgemini-2.0-flash -
openaiwithgpt-4o
For advanced PM2 configuration, create ecosystem.config.js:
module.exports = {
apps: [{
name: 'dissensus',
script: './server/index.js',
cwd: '/home/dissensus/dissensus-engine',
instances: 1,
exec_mode: 'fork',
env: {
NODE_ENV: 'production',
PORT: 3000
},
error_file: './logs/err.log',
out_file: './logs/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
max_memory_restart: '500M',
restart_delay: 3000,
max_restarts: 5,
min_uptime: '10s',
watch: false,
kill_timeout: 5000,
listen_timeout: 10000
}]
};Start with:
pm2 start ecosystem.config.jsNODE_ENV=development
PORT=3000
TRUST_PROXY=0In development mode:
- Rate limits are relaxed (100/min vs 10/min)
- More verbose error messages
- No helmet CSP enforcement
NODE_ENV=production
PORT=3000
TRUST_PROXY=1
TRUST_PROXY_HOPS=1In production mode:
- Strict rate limiting
- Helmet security headers enabled
- Trust proxy enabled for accurate client IPs
The DEBATE_OF_THE_DAY_TZ variable controls which timezone is used for determining the "current" debate topic.
Common values:
-
UTC- Coordinated Universal Time (default) -
America/New_York- US Eastern Time -
America/Los_Angeles- US Pacific Time -
Europe/London- GMT/BST -
Europe/Paris- Central European Time -
Asia/Tokyo- Japan Standard Time
List all available timezones:
timedatectl list-timezonesEnsure correct ownership for the application directory:
# Set ownership to the dissensus user
sudo chown -R dissensus:dissensus /home/dissensus/dissensus-engine
# Set appropriate permissions
sudo chmod -R 755 /home/dissensus/dissensus-engine
# Ensure .env is readable only by owner
chmod 600 /home/dissensus/dissensus-engine/.envDefault log locations:
- Output:
~/.pm2/logs/dissensus-out.log - Errors:
~/.pm2/logs/dissensus-error.log
View logs:
pm2 logs dissensus
pm2 logs dissensus --lines 100
pm2 logs dissensus --err# Access log
sudo tail -f /var/log/nginx/access.log
# Error log
sudo tail -f /var/log/nginx/error.logThe engine logs to stdout/stderr which PM2 captures:
⚡ DISSENSUS Engine running on http://localhost:3000
🧠 Providers: OpenAI, DeepSeek, Google Gemini
🔑 Server-side keys configured for: deepseek, openai
🔥 Ready to debate.