Ubuntu Deployment
This guide covers deploying Plugged.in on Ubuntu servers (20.04 LTS or later) for production or staging environments.
System Requirements
Minimum Requirements
Ubuntu 20.04 LTS or later
2 CPU cores
4GB RAM
20GB storage
Node.js v20+
PostgreSQL 15+
Recommended Setup
Ubuntu 22.04 LTS
4+ CPU cores
8GB+ RAM
50GB+ SSD storage
Dedicated database server
Redis for caching
Prerequisites Installation
1. System Updates
# Update package list and upgrade system
sudo apt-get update
sudo apt-get upgrade -y
# Install essential packages
sudo apt-get install -y \
curl \
wget \
git \
build-essential \
nginx \
certbot \
python3-certbot-nginx
2. Node.js Installation
Using NodeSource Using NVM # Install Node.js v20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# Verify installation
node --version # Should be v20+
npm --version # Should be available
npx --version # Should be available
3. PostgreSQL Setup
# Install PostgreSQL 15
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y postgresql-15 postgresql-client-15
# Create database and user
sudo -u postgres psql << EOF
CREATE USER pluggedin WITH PASSWORD 'your_secure_password';
CREATE DATABASE pluggedin_prod OWNER pluggedin;
GRANT ALL PRIVILEGES ON DATABASE pluggedin_prod TO pluggedin;
EOF
4. pnpm Installation
# Install pnpm globally
npm install -g pnpm
# Verify installation
pnpm --version
5. Python and uv (for Python MCP Servers)
# Install Python 3
sudo apt-get install -y python3 python3-pip python3-venv
# Install uv for Python package management
curl -LsSf https://astral.sh/uv/install.sh | sh
# Add to PATH (add to ~/.bashrc)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Sandboxing is critical for secure execution of MCP servers. Install at least one sandboxing tool.
# Install Bubblewrap (preferred sandboxing tool)
sudo apt-get install -y bubblewrap
# Install Firejail (fallback sandboxing tool)
sudo apt-get install -y firejail
# Install FUSE (required for some sandboxed applications)
sudo apt-get install -y fuse3 libfuse3-3
# Verify installations
bwrap --version
firejail --version
fusermount3 --version
Why Sandboxing is Required:
Security Isolation : Prevents MCP servers from accessing sensitive system files
Resource Limits : Controls CPU, memory, and I/O usage
Network Isolation : Optional network restrictions for untrusted servers
Process Containment : Prevents escape from sandbox environment
Application Deployment
1. Clone Repository
# Create application directory
sudo mkdir -p /var/www/pluggedin
sudo chown $USER : $USER /var/www/pluggedin
# Clone repository
cd /var/www/pluggedin
git clone https://github.com/VeriTeknik/pluggedin-app.git .
2. Environment Configuration
Create .env
file:
cp .env.example .env
nano .env
Configure essential variables:
# Database
DATABASE_URL="postgresql://pluggedin:your_secure_password@localhost:5432/pluggedin_prod"
# Authentication
NEXTAUTH_URL="https://your-domain.com"
NEXTAUTH_SECRET="generate-with-openssl-rand-base64-32"
# Application
NODE_ENV="production"
PORT="3000"
# MCP Configuration
MCP_PACKAGE_STORE_DIR="/var/www/pluggedin/.cache/mcp-packages"
MCP_PNPM_STORE_DIR="/var/www/pluggedin/.cache/mcp-packages/pnpm-store"
MCP_UV_CACHE_DIR="/var/www/pluggedin/.cache/mcp-packages/uv-cache"
# Sandboxing Configuration (IMPORTANT for security)
MCP_ISOLATION_TYPE="bubblewrap" # Primary: bubblewrap | firejail | none
MCP_ISOLATION_FALLBACK="firejail" # Fallback if primary not available
MCP_ENABLE_NETWORK_ISOLATION="false" # Set to true for stricter isolation
# API Keys (optional)
PLUGGEDIN_API_KEY="your-api-key"
3. Install Dependencies
# Install Node dependencies
pnpm install
# Build application
pnpm build
# Run database migrations
pnpm db:migrate
4. Create Cache Directories
# Create MCP package cache directories
mkdir -p ~/.cache/mcp-packages/pnpm-store
mkdir -p ~/.cache/mcp-packages/uv-cache
# Set permissions
chmod 755 ~/.cache/mcp-packages
Systemd Service Setup
1. Create Service File
sudo nano /etc/systemd/system/pluggedin.service
[Unit]
Description =Plugged.in Application
After =network.target postgresql.service
[Service]
Type =simple
User =www-data
Group =www-data
WorkingDirectory =/var/www/pluggedin
Environment = "NODE_ENV=production"
Environment = "PATH=/usr/local/bin:/usr/bin:/bin:/home/www-data/.local/bin"
ExecStart =/usr/bin/node .next/standalone/server.js
Restart =always
RestartSec =10
# Security
NoNewPrivileges =true
PrivateTmp =true
ProtectSystem =strict
ProtectHome =true
ReadWritePaths =/var/www/pluggedin
# Resource limits
LimitNOFILE =65536
LimitNPROC =512
[Install]
WantedBy =multi-user.target
2. Enable and Start Service
# Set ownership
sudo chown -R www-data:www-data /var/www/pluggedin
# Reload systemd
sudo systemctl daemon-reload
# Enable service
sudo systemctl enable pluggedin
# Start service
sudo systemctl start pluggedin
# Check status
sudo systemctl status pluggedin
Nginx Configuration
1. Create Nginx Config
sudo nano /etc/nginx/sites-available/pluggedin
server {
listen 80 ;
server_name your-domain.com;
# Redirect to HTTPS
return 301 https://$ server_name $ request_uri ;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL configuration (will be managed by Certbot)
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Proxy settings
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection 'upgrade' ;
proxy_set_header Host $ host ;
proxy_cache_bypass $ http_upgrade ;
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 ;
# Timeouts
proxy_connect_timeout 60s ;
proxy_send_timeout 60s ;
proxy_read_timeout 60s ;
}
# WebSocket support for real-time features
location /api/websocket {
proxy_pass http://localhost:3000;
proxy_http_version 1.1 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection "upgrade" ;
}
# Static file caching
location /_next/static {
proxy_pass http://localhost:3000;
add_header Cache-Control "public, max-age=31536000, immutable" ;
}
}
2. Enable Site
# Enable site
sudo ln -s /etc/nginx/sites-available/pluggedin /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginx
3. SSL Certificate
# Obtain Let's Encrypt certificate
sudo certbot --nginx -d your-domain.com
# Auto-renewal
sudo systemctl enable certbot.timer
Security Hardening
1. Firewall Configuration
# Install UFW
sudo apt-get install -y ufw
# Configure firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable firewall
sudo ufw --force enable
Sandboxing is enabled by default for all STDIO MCP servers. Ensure tools are properly installed.
# Verify sandboxing tools are installed
which bwrap || sudo apt-get install -y bubblewrap
which firejail || sudo apt-get install -y firejail
# Test sandboxing functionality
bwrap --version
firejail --version
# Configure sandboxing in .env
cat >> .env << EOF
MCP_ISOLATION_TYPE="bubblewrap"
MCP_ISOLATION_FALLBACK="firejail"
MCP_ENABLE_NETWORK_ISOLATION="false"
EOF
# Set appropriate permissions for sandbox directories
sudo chown -R www-data:www-data /var/www/pluggedin/.cache
sudo chmod -R 755 /var/www/pluggedin/.cache
Sandboxing Modes:
bubblewrap : Lightweight, user-namespace based isolation (recommended)
firejail : SUID-based sandboxing with extensive security profiles
none : Disable sandboxing (NOT recommended for production)
3. Database Security
# Secure PostgreSQL
sudo nano /etc/postgresql/15/main/postgresql.conf
# Add/modify:
# listen_addresses = 'localhost'
# ssl = on
# Restart PostgreSQL
sudo systemctl restart postgresql
Monitoring & Maintenance
1. Log Management
# View application logs
sudo journalctl -u pluggedin -f
# View Nginx logs
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
2. Health Checks
Create health check script:
#!/bin/bash
# /usr/local/bin/pluggedin-health
curl -f http://localhost:3000/api/health || exit 1
chmod +x /usr/local/bin/pluggedin-health
# Add to crontab
* /5 * * * * /usr/local/bin/pluggedin-health || systemctl restart pluggedin
3. Backup Strategy
# Database backup script
#!/bin/bash
# /usr/local/bin/backup-pluggedin
BACKUP_DIR = "/var/backups/pluggedin"
DATE = $( date +%Y%m%d_%H%M%S )
mkdir -p $BACKUP_DIR
pg_dump pluggedin_prod | gzip > " $BACKUP_DIR /db_ $DATE .sql.gz"
# Keep only last 30 days
find $BACKUP_DIR -name "db_*.sql.gz" -mtime +30 -delete
Add to crontab:
0 2 * * * /usr/local/bin/backup-pluggedin
Troubleshooting
Common Issues
Solution : Install npm globally or ensure Node.js installation includes npm
Solution : Install uv and add to PATHcurl -LsSf https://astral.sh/uv/install.sh | sh
export PATH = " $HOME /.local/bin: $PATH "
EACCES: permission denied
Solution : Check file ownership and permissionssudo chown -R www-data:www-data /var/www/pluggedin
sudo chmod -R 755 /var/www/pluggedin
Database connection failed
Solution : Verify PostgreSQL is running and credentials are correctsudo systemctl status postgresql
sudo -u postgres psql -c "\l"
Debug Mode
Enable debug logging:
# Add to .env
DEBUG = mcp:*
# Restart service
sudo systemctl restart pluggedin
Check logs for:
[MCP Wrapper] Environment info
[MCP Wrapper] Command not found
[MCP Wrapper] Current PATH
1. Node.js Tuning
# Add to service file
Environment = "NODE_OPTIONS=--max-old-space-size=4096"
2. PostgreSQL Tuning
# Edit postgresql.conf
sudo nano /etc/postgresql/15/main/postgresql.conf
# Adjust based on available RAM:
shared_buffers = 1GB
effective_cache_size = 3GB
maintenance_work_mem = 256MB
3. Redis Cache (Optional)
# Install Redis
sudo apt-get install -y redis-server
# Enable and start
sudo systemctl enable redis-server
sudo systemctl start redis-server
# Add to .env
REDIS_URL = "redis://localhost:6379"
Support
For deployment issues: