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

# 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

6. Sandboxing Tools (Required for Security)

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

2. Configure Sandboxing

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

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

Performance Optimization

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: