Skip to main content
Glama

VPS Initialize

by oxy-Op
nginx-manager.ts8.45 kB
import { SSHService } from '../services/ssh-service.js'; import { logger } from '../utils/logger.js'; export interface NginxConfig { domain: string; port: number; ssl?: boolean; } export interface NginxResult { success: boolean; message: string; } export class NginxManager { constructor(private sshService: SSHService) {} async setupNginx(config: NginxConfig): Promise<NginxResult> { try { logger.info('Setting up Nginx configuration', { domain: config.domain, port: config.port }); // Create Nginx configuration const nginxConfigResult = await this.createNginxConfig(config); if (!nginxConfigResult.success) { return nginxConfigResult; } // Test and reload Nginx const testResult = await this.sshService.executeCommand('nginx -t'); if (!testResult.success) { return { success: false, message: `Nginx configuration test failed: ${testResult.stderr}`, }; } const reloadResult = await this.sshService.executeCommand('systemctl reload nginx'); if (!reloadResult.success) { return { success: false, message: `Failed to reload Nginx: ${reloadResult.stderr}`, }; } // Setup SSL if requested if (config.ssl) { const sslResult = await this.setupSSL(config.domain); if (!sslResult.success) { return sslResult; } } // Configure firewall await this.configureFirewall(); return { success: true, message: `Nginx configured successfully for ${config.domain}${config.ssl ? ' with SSL' : ''}`, }; } catch (error) { logger.error('Nginx setup failed', { error, config }); return { success: false, message: `Nginx setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } private async createNginxConfig(config: NginxConfig): Promise<NginxResult> { const nginxConfig = this.generateNginxConfig(config); const configPath = `/etc/nginx/sites-available/${config.domain}`; const enabledPath = `/etc/nginx/sites-enabled/${config.domain}`; try { // Write configuration file const writeResult = await this.sshService.executeCommand( `cat > ${configPath} << 'EOF'\n${nginxConfig}\nEOF` ); if (!writeResult.success) { return { success: false, message: `Failed to write Nginx config: ${writeResult.stderr}`, }; } // Enable site const linkResult = await this.sshService.executeCommand( `ln -sf ${configPath} ${enabledPath}` ); if (!linkResult.success) { return { success: false, message: `Failed to enable Nginx site: ${linkResult.stderr}`, }; } // Remove default site if it exists await this.sshService.executeCommand('rm -f /etc/nginx/sites-enabled/default'); return { success: true, message: 'Nginx configuration created successfully', }; } catch (error) { return { success: false, message: `Failed to create Nginx config: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } private generateNginxConfig(config: NginxConfig): string { return `server { listen 80; server_name ${config.domain} www.${config.domain}; # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; # Gzip compression gzip on; gzip_vary on; gzip_min_length 1024; gzip_proxied expired no-cache no-store private must-revalidate auth; gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; location / { proxy_pass http://127.0.0.1:${config.port}; 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; proxy_read_timeout 86400; } # Deny access to hidden files location ~ /\\. { deny all; } # Optimize static file serving location ~* \\.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; try_files $uri @proxy; } location @proxy { proxy_pass http://127.0.0.1:${config.port}; 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; } }`; } private async setupSSL(domain: string): Promise<NginxResult> { try { logger.info('Setting up SSL with Certbot', { domain }); // Install Certbot const installResult = await this.sshService.executeCommand( 'DEBIAN_FRONTEND=noninteractive apt install -y certbot python3-certbot-nginx' ); if (!installResult.success) { return { success: false, message: `Failed to install Certbot: ${installResult.stderr}`, }; } // Obtain SSL certificate const certResult = await this.sshService.executeCommand( `certbot --nginx -d ${domain} -d www.${domain} --non-interactive --agree-tos --email admin@${domain}` ); if (!certResult.success) { // Try without www subdomain const certResultNoWWW = await this.sshService.executeCommand( `certbot --nginx -d ${domain} --non-interactive --agree-tos --email admin@${domain}` ); if (!certResultNoWWW.success) { return { success: false, message: `Failed to obtain SSL certificate: ${certResult.stderr}`, }; } } // Setup auto-renewal const cronResult = await this.sshService.executeCommand( 'echo "0 12 * * * /usr/bin/certbot renew --quiet" | crontab -' ); if (!cronResult.success) { logger.warn('Failed to setup SSL auto-renewal', { error: cronResult.stderr }); } return { success: true, message: 'SSL certificate obtained and configured successfully', }; } catch (error) { logger.error('SSL setup failed', { error, domain }); return { success: false, message: `SSL setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } private async configureFirewall(): Promise<void> { try { // Enable UFW and configure basic rules const commands = [ 'ufw --force enable', 'ufw default deny incoming', 'ufw default allow outgoing', 'ufw allow ssh', 'ufw allow "Nginx Full"', 'ufw --force reload', ]; for (const command of commands) { await this.sshService.executeCommand(command); } logger.info('Firewall configured successfully'); } catch (error) { logger.warn('Firewall configuration failed', { error }); } } async removeConfig(domain: string): Promise<NginxResult> { try { const commands = [ `rm -f /etc/nginx/sites-available/${domain}`, `rm -f /etc/nginx/sites-enabled/${domain}`, 'nginx -t', 'systemctl reload nginx', ]; for (const command of commands) { const result = await this.sshService.executeCommand(command); if (!result.success && command.includes('nginx -t')) { return { success: false, message: `Nginx configuration test failed after removing ${domain}`, }; } } return { success: true, message: `Nginx configuration for ${domain} removed successfully`, }; } catch (error) { return { success: false, message: `Failed to remove Nginx config: ${error instanceof Error ? error.message : 'Unknown error'}`, }; } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/oxy-Op/DevPilot'

If you have feedback or need assistance with the MCP directory API, please join our Discord server