Add production deployment scripts and quickstart guide
- Add deploy-to-vm.sh script for easy VM deployment - Add systemd service file template - Add Nginx configuration with SSL and rate limiting - Add DEPLOYMENT_QUICKSTART.md for n8ndocumentation.aiservices.pl - Update REMOTE_DEPLOYMENT.md to reference quickstart The deployment process is now streamlined: 1. Copy .env.example to .env 2. Configure for production (domain, auth token) 3. Run ./scripts/deploy-to-vm.sh Tested locally with production configuration - all endpoints working correctly with authentication. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
151
scripts/deploy-to-vm.sh
Executable file
151
scripts/deploy-to-vm.sh
Executable file
@@ -0,0 +1,151 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Deployment script for n8n Documentation MCP Server
|
||||
# Target: n8ndocumentation.aiservices.pl
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 n8n Documentation MCP Server - VM Deployment"
|
||||
echo "=============================================="
|
||||
|
||||
# Configuration
|
||||
SERVER_USER=${SERVER_USER:-root}
|
||||
SERVER_HOST=${SERVER_HOST:-n8ndocumentation.aiservices.pl}
|
||||
APP_DIR="/opt/n8n-mcp"
|
||||
SERVICE_NAME="n8n-docs-mcp"
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Check if .env exists
|
||||
if [ ! -f .env ]; then
|
||||
echo -e "${RED}❌ .env file not found. Please create it from .env.example${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check required environment variables
|
||||
source .env
|
||||
if [ "$MCP_DOMAIN" != "n8ndocumentation.aiservices.pl" ]; then
|
||||
echo -e "${YELLOW}⚠️ Warning: MCP_DOMAIN is not set to n8ndocumentation.aiservices.pl${NC}"
|
||||
read -p "Continue anyway? (y/N) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$MCP_AUTH_TOKEN" ] || [ "$MCP_AUTH_TOKEN" == "your-secure-auth-token-here" ]; then
|
||||
echo -e "${RED}❌ MCP_AUTH_TOKEN not set or using default value${NC}"
|
||||
echo "Generate a secure token with: openssl rand -hex 32"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ Configuration validated${NC}"
|
||||
|
||||
# Build the project locally
|
||||
echo -e "\n${YELLOW}Building project...${NC}"
|
||||
npm run build
|
||||
|
||||
# Create deployment package
|
||||
echo -e "\n${YELLOW}Creating deployment package...${NC}"
|
||||
rm -rf deploy-package
|
||||
mkdir -p deploy-package
|
||||
|
||||
# Copy necessary files
|
||||
cp -r dist deploy-package/
|
||||
cp -r data deploy-package/
|
||||
cp package*.json deploy-package/
|
||||
cp .env deploy-package/
|
||||
cp ecosystem.config.js deploy-package/ 2>/dev/null || true
|
||||
|
||||
# Create tarball
|
||||
tar -czf deploy-package.tar.gz deploy-package
|
||||
|
||||
echo -e "${GREEN}✅ Deployment package created${NC}"
|
||||
|
||||
# Upload to server
|
||||
echo -e "\n${YELLOW}Uploading to server...${NC}"
|
||||
scp deploy-package.tar.gz $SERVER_USER@$SERVER_HOST:/tmp/
|
||||
|
||||
# Deploy on server
|
||||
echo -e "\n${YELLOW}Deploying on server...${NC}"
|
||||
ssh $SERVER_USER@$SERVER_HOST << 'ENDSSH'
|
||||
set -e
|
||||
|
||||
# Create app directory
|
||||
mkdir -p /opt/n8n-mcp
|
||||
cd /opt/n8n-mcp
|
||||
|
||||
# Stop existing service if running
|
||||
pm2 stop n8n-docs-mcp 2>/dev/null || true
|
||||
|
||||
# Extract deployment package
|
||||
tar -xzf /tmp/deploy-package.tar.gz --strip-components=1
|
||||
rm /tmp/deploy-package.tar.gz
|
||||
|
||||
# Install production dependencies
|
||||
npm ci --only=production
|
||||
|
||||
# Create PM2 ecosystem file if not exists
|
||||
if [ ! -f ecosystem.config.js ]; then
|
||||
cat > ecosystem.config.js << 'EOF'
|
||||
module.exports = {
|
||||
apps: [{
|
||||
name: 'n8n-docs-mcp',
|
||||
script: './dist/index-http.js',
|
||||
instances: 1,
|
||||
autorestart: true,
|
||||
watch: false,
|
||||
max_memory_restart: '1G',
|
||||
env: {
|
||||
NODE_ENV: 'production'
|
||||
},
|
||||
error_file: './logs/error.log',
|
||||
out_file: './logs/out.log',
|
||||
log_file: './logs/combined.log',
|
||||
time: true
|
||||
}]
|
||||
};
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Create logs directory
|
||||
mkdir -p logs
|
||||
|
||||
# Start with PM2
|
||||
pm2 start ecosystem.config.js
|
||||
pm2 save
|
||||
|
||||
echo "✅ Deployment complete!"
|
||||
echo ""
|
||||
echo "Service status:"
|
||||
pm2 status n8n-docs-mcp
|
||||
ENDSSH
|
||||
|
||||
# Clean up local files
|
||||
rm -rf deploy-package deploy-package.tar.gz
|
||||
|
||||
echo -e "\n${GREEN}🎉 Deployment successful!${NC}"
|
||||
echo -e "\nServer endpoints:"
|
||||
echo -e " Health: https://$SERVER_HOST/health"
|
||||
echo -e " Stats: https://$SERVER_HOST/stats"
|
||||
echo -e " MCP: https://$SERVER_HOST/mcp"
|
||||
echo -e "\nClaude Desktop configuration:"
|
||||
echo -e " {
|
||||
\"mcpServers\": {
|
||||
\"n8n-nodes-remote\": {
|
||||
\"command\": \"npx\",
|
||||
\"args\": [
|
||||
\"-y\",
|
||||
\"@modelcontextprotocol/client-http\",
|
||||
\"https://$SERVER_HOST/mcp\"
|
||||
],
|
||||
\"env\": {
|
||||
\"MCP_AUTH_TOKEN\": \"$MCP_AUTH_TOKEN\"
|
||||
}
|
||||
}
|
||||
}
|
||||
}"
|
||||
29
scripts/n8n-docs-mcp.service
Normal file
29
scripts/n8n-docs-mcp.service
Normal file
@@ -0,0 +1,29 @@
|
||||
[Unit]
|
||||
Description=n8n Documentation MCP Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nodejs
|
||||
WorkingDirectory=/opt/n8n-mcp
|
||||
ExecStart=/usr/bin/node /opt/n8n-mcp/dist/index-http.js
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
# Environment
|
||||
Environment="NODE_ENV=production"
|
||||
EnvironmentFile=/opt/n8n-mcp/.env
|
||||
|
||||
# Security
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths=/opt/n8n-mcp/data /opt/n8n-mcp/logs /opt/n8n-mcp/temp
|
||||
|
||||
# Logging
|
||||
StandardOutput=append:/opt/n8n-mcp/logs/service.log
|
||||
StandardError=append:/opt/n8n-mcp/logs/service-error.log
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
75
scripts/nginx-n8n-mcp.conf
Normal file
75
scripts/nginx-n8n-mcp.conf
Normal file
@@ -0,0 +1,75 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name n8ndocumentation.aiservices.pl;
|
||||
|
||||
# Redirect HTTP to HTTPS
|
||||
location / {
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name n8ndocumentation.aiservices.pl;
|
||||
|
||||
# SSL configuration (managed by Certbot)
|
||||
ssl_certificate /etc/letsencrypt/live/n8ndocumentation.aiservices.pl/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/n8ndocumentation.aiservices.pl/privkey.pem;
|
||||
|
||||
# SSL security settings
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
# Security headers
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/n8n-mcp-access.log;
|
||||
error_log /var/log/nginx/n8n-mcp-error.log;
|
||||
|
||||
# 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_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_cache_bypass $http_upgrade;
|
||||
|
||||
# Timeouts for MCP operations
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
|
||||
# Increase buffer sizes for large responses
|
||||
proxy_buffer_size 16k;
|
||||
proxy_buffers 8 16k;
|
||||
proxy_busy_buffers_size 32k;
|
||||
}
|
||||
|
||||
# Rate limiting for API endpoints
|
||||
location /mcp {
|
||||
limit_req zone=mcp_limit burst=10 nodelay;
|
||||
proxy_pass http://localhost: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;
|
||||
|
||||
# Larger timeouts for MCP
|
||||
proxy_connect_timeout 120s;
|
||||
proxy_send_timeout 120s;
|
||||
proxy_read_timeout 120s;
|
||||
}
|
||||
}
|
||||
|
||||
# Rate limiting zone
|
||||
limit_req_zone $binary_remote_addr zone=mcp_limit:10m rate=10r/s;
|
||||
Reference in New Issue
Block a user