Replit Deployment Guide
Complete guide for deploying ElizaOS on Replit, including VM setup, troubleshooting, and best practices
This guide addresses the challenge that "Deploying a VM on Replit is not as easy as one would think" by providing step-by-step instructions for successfully deploying ElizaOS on Replit.
Developer Experience: While Replit can be tricky for complex deployments, this guide makes it straightforward with proven solutions for common issues.
Replit Deployment Options
Replit offers several ways to deploy ElizaOS:
Method | Best For | Complexity | Limitations |
---|---|---|---|
Replit Core | Quick prototyping | Low | No persistence |
Replit Deployments | Production apps | Medium | Some resource limits |
Replit VMs | Full control | High | Requires VM management |
Replit Ghostwriter | AI-assisted development | Low | Limited to development |
Quick Start (Replit Core)
Create a New Repl
- Go to replit.com
- Click "Create Repl"
- Choose "Node.js" template
- Name your repl "eliza-agent"
Install ElizaOS
In the Replit shell:
# Install ElizaOS CLI
npm install -g @elizaos/cli
# Create a new project
npx create-eliza my-agent
cd my-agent
# Install dependencies
npm install
Configure for Replit
Create a .replit
file:
run = "npm start"
entrypoint = "src/index.js"
modules = ["nodejs-20"]
[env]
PATH = "/home/runner/$REPL_SLUG/node_modules/.bin:$PATH"
NODE_ENV = "production"
[packager]
language = "nodejs"
[packager.features]
packageSearch = true
guessImports = true
enabledForHosting = false
[languages.javascript]
pattern = "**/{*.js,*.jsx,*.ts,*.tsx}"
syntax = "javascript"
[languages.javascript.languageServer]
start = "typescript-language-server --stdio"
[deployment]
run = ["sh", "-c", "npm start"]
deploymentTarget = "cloudrun"
Create Character File
{
"name": "ReplitBot",
"bio": [
"I'm an AI assistant running on Replit",
"I help with coding, debugging, and general questions",
"I'm designed to work well in the Replit environment"
],
"plugins": [
"@elizaos/plugin-bootstrap"
],
"settings": {
"model": "gpt-4",
"temperature": 0.7
}
}
Run Your Agent
# Start the agent
npm start -- --character character.json
# Or with environment variables
OPENAI_API_KEY=your-key npm start -- --character character.json
Your agent should now be running! The Replit interface will show the output and provide a URL.
Replit Deployments (Recommended)
For production deployments, use Replit Deployments:
Prepare for Deployment
Update your package.json
:
{
"name": "eliza-replit",
"version": "1.0.0",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js",
"build": "echo 'No build step required'"
},
"dependencies": {
"@elizaos/core": "^1.0.19",
"@elizaos/plugin-bootstrap": "^1.0.19"
}
}
Configure Environment Variables
In your Replit project:
- Go to the "Secrets" tab
- Add these environment variables:
OPENAI_API_KEY=your-openai-key
ANTHROPIC_API_KEY=your-anthropic-key
NODE_ENV=production
PORT=3000
Create Deployment Configuration
version: 1
name: eliza-agent
run: node src/index.js
entrypoint: src/index.js
deployment:
target: cloudrun
env:
NODE_ENV: production
PORT: 3000
health_check:
path: /health
port: 3000
timeout: 30
scaling:
min_instances: 1
max_instances: 10
resources:
cpu: 1
memory: 1Gi
Deploy
- Click the "Deploy" button in Replit
- Choose "Replit Deployments"
- Configure your deployment settings
- Click "Deploy"
Your agent will be deployed to a public URL!
Advanced VM Setup
For full control, use Replit VMs:
Create a VM Repl
- Create a new Repl
- Choose "Blank Repl"
- Select "VM" as the runtime
- Choose Ubuntu or another Linux distribution
Install Dependencies
# Update system
sudo apt update && sudo apt upgrade -y
# Install Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install build tools
sudo apt-get install -y build-essential git curl
# Install Bun (recommended)
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
Clone and Setup ElizaOS
# Clone the repository
git clone https://github.com/elizaOS/eliza.git
cd eliza
# Install dependencies
bun install
# Build the project
bun run build
Configure for VM
Create a systemd service:
[Unit]
Description=ElizaOS Agent
After=network.target
[Service]
Type=simple
User=runner
WorkingDirectory=/home/runner/eliza
ExecStart=/home/runner/.bun/bin/bun start --character /home/runner/eliza/character.json
Restart=always
RestartSec=10
Environment=NODE_ENV=production
EnvironmentFile=/home/runner/eliza/.env
[Install]
WantedBy=multi-user.target
Start and Enable Service
# Reload systemd
sudo systemctl daemon-reload
# Start the service
sudo systemctl start eliza
# Enable on boot
sudo systemctl enable eliza
# Check status
sudo systemctl status eliza
Troubleshooting Common Issues
Issue 1: "Module not found" errors
Problem: Node modules aren't found in Replit
Solution:
# Clear npm cache
npm cache clean --force
# Delete node_modules and reinstall
rm -rf node_modules package-lock.json
npm install
# Or use yarn
yarn install --force
Issue 2: Memory limits exceeded
Problem: Agent crashes with "JavaScript heap out of memory"
Solution:
# Increase memory limit
NODE_OPTIONS="--max-old-space-size=2048" npm start
# Or configure in package.json
{
"scripts": {
"start": "NODE_OPTIONS='--max-old-space-size=2048' node src/index.js"
}
}
Issue 3: Port binding issues
Problem: "Port already in use" or "EADDRINUSE"
Solution:
# Kill existing processes
pkill -f node
# Use PORT environment variable
PORT=3000 npm start
# Or configure in code
const port = process.env.PORT || 3000;
Issue 4: File system permissions
Problem: Permission denied when writing files
Solution:
# Fix permissions
chmod +x src/index.js
chmod -R 755 src/
# Use proper paths
const dataPath = process.env.REPL_SLUG ?
`/home/runner/${process.env.REPL_SLUG}/data` :
'./data';
Issue 5: Environment variables not loading
Problem: API keys not accessible
Solution:
// Use process.env in Replit
const config = {
openaiKey: process.env.OPENAI_API_KEY,
anthropicKey: process.env.ANTHROPIC_API_KEY
};
// Check for missing variables
if (!config.openaiKey) {
console.error('OPENAI_API_KEY not found in environment');
process.exit(1);
}
Replit-Specific Optimizations
1. Database Configuration
Use SQLite for simplicity:
import sqlite3 from 'sqlite3';
import path from 'path';
// Use persistent storage path
const dbPath = process.env.REPL_SLUG ?
`/home/runner/${process.env.REPL_SLUG}/data/eliza.db` :
'./data/eliza.db';
const db = new sqlite3.Database(dbPath);
export { db };
2. File Upload Handling
import multer from 'multer';
import path from 'path';
const storage = multer.diskStorage({
destination: (req, file, cb) => {
// Use Replit's persistent storage
const uploadPath = process.env.REPL_SLUG ?
`/home/runner/${process.env.REPL_SLUG}/uploads` :
'./uploads';
cb(null, uploadPath);
},
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`);
}
});
export const upload = multer({ storage });
3. Logging Configuration
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.Console(),
new winston.transports.File({
filename: process.env.REPL_SLUG ?
`/home/runner/${process.env.REPL_SLUG}/logs/eliza.log` :
'./logs/eliza.log'
})
]
});
export { logger };
Performance Optimization
1. Reduce Memory Usage
// Limit message history
const MAX_MESSAGE_HISTORY = 50;
class MessageManager {
constructor() {
this.messages = [];
}
addMessage(message) {
this.messages.push(message);
// Keep only recent messages
if (this.messages.length > MAX_MESSAGE_HISTORY) {
this.messages.shift();
}
}
}
// Use garbage collection
setInterval(() => {
if (global.gc) {
global.gc();
}
}, 60000); // Every minute
2. Optimize Plugin Loading
// Lazy load plugins
const loadPlugin = async (pluginName) => {
try {
const plugin = await import(pluginName);
return plugin.default || plugin;
} catch (error) {
console.warn(`Failed to load plugin ${pluginName}:`, error);
return null;
}
};
// Load only essential plugins
const essentialPlugins = [
'@elizaos/plugin-bootstrap'
];
const plugins = await Promise.all(
essentialPlugins.map(loadPlugin)
);
Deployment Best Practices
1. Health Checks
import express from 'express';
const app = express();
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage()
});
});
app.get('/ready', (req, res) => {
// Check if agent is ready
res.json({ ready: true });
});
export { app };
2. Graceful Shutdown
process.on('SIGTERM', async () => {
console.log('Received SIGTERM, shutting down gracefully...');
// Close connections
await closeDatabase();
await stopAgent();
process.exit(0);
});
process.on('SIGINT', async () => {
console.log('Received SIGINT, shutting down gracefully...');
// Close connections
await closeDatabase();
await stopAgent();
process.exit(0);
});
3. Error Handling
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
// Log the error
logger.error('Uncaught Exception', { error: error.message, stack: error.stack });
// Graceful shutdown
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// Log the error
logger.error('Unhandled Rejection', { reason, promise });
});
Monitoring and Debugging
1. Real-time Monitoring
import { EventEmitter } from 'events';
class Monitor extends EventEmitter {
constructor() {
super();
this.metrics = {
requests: 0,
errors: 0,
startTime: Date.now()
};
}
trackRequest() {
this.metrics.requests++;
this.emit('request');
}
trackError() {
this.metrics.errors++;
this.emit('error');
}
getMetrics() {
return {
...this.metrics,
uptime: Date.now() - this.metrics.startTime
};
}
}
export const monitor = new Monitor();
2. Debug Mode
const DEBUG = process.env.NODE_ENV === 'development';
export const debug = (message, ...args) => {
if (DEBUG) {
console.log(`[DEBUG] ${message}`, ...args);
}
};
export const debugRequest = (req, res, next) => {
if (DEBUG) {
console.log(`[DEBUG] ${req.method} ${req.url}`);
}
next();
};
Sample Complete Setup
Here's a complete working example:
import { AgentRuntime } from '@elizaos/core';
import { bootstrapPlugin } from '@elizaos/plugin-bootstrap';
import express from 'express';
import { logger } from './logger.js';
import { monitor } from './monitoring.js';
const app = express();
const port = process.env.PORT || 3000;
// Middleware
app.use(express.json());
app.use((req, res, next) => {
monitor.trackRequest();
next();
});
// Health check
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
metrics: monitor.getMetrics()
});
});
// Initialize agent
const character = {
name: "ReplitBot",
bio: ["I'm running on Replit!"],
plugins: [bootstrapPlugin]
};
const runtime = new AgentRuntime(character);
// Chat endpoint
app.post('/chat', async (req, res) => {
try {
const { message } = req.body;
const response = await runtime.processMessage(message);
res.json({ response });
} catch (error) {
logger.error('Chat error:', error);
monitor.trackError();
res.status(500).json({ error: 'Internal server error' });
}
});
// Start server
app.listen(port, () => {
logger.info(`ElizaOS agent running on port ${port}`);
});
Next Steps
Replit Community
Join Replit's community for help
Cloud Platform Guide
Alternative deployment options
Troubleshooting
Common issues and solutions
Performance Optimization
Optimize your agent for production
Remember: While deploying VMs on Replit can be complex, start with Replit Deployments for most use cases. Only use VMs when you need full system control.