ssh_deploy
Deploy files to remote servers with automatic permission adjustments, set file ownership, manage backups, and trigger service restarts for efficient file distribution.
Instructions
Deploy files to remote server with automatic permission handling
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| files | Yes | Array of files to deploy | |
| options | No | Deployment options | |
| server | Yes | Server name or alias |
Implementation Reference
- src/tool-registry.js:57-72 (registration)Registration of the 'ssh_deploy' tool in the advanced tool group. This list is used for conditional tool registration and validation based on user configuration.advanced: [ 'ssh_deploy', 'ssh_execute_sudo', 'ssh_alias', 'ssh_command_alias', 'ssh_hooks', 'ssh_profile', 'ssh_connection_status', 'ssh_tunnel_create', 'ssh_tunnel_list', 'ssh_tunnel_close', 'ssh_key_manage', 'ssh_execute_group', 'ssh_group_manage', 'ssh_history' ]
- src/deploy-helper.js:22-105 (helper)Primary helper function for building safe deployment strategies, handling backups, sudo requirements, ownership, permissions, and service restarts. Critical for ssh_deploy tool implementation.export function buildDeploymentStrategy(remotePath, options = {}) { const { sudoPassword = null, owner = null, permissions = null, backup = true, restart = null } = options; const strategy = { steps: [], requiresSudo: false }; // Step 1: Backup existing file if requested if (backup) { strategy.steps.push({ type: 'backup', command: `if [ -f "${remotePath}" ]; then cp "${remotePath}" "${remotePath}.bak.$(date +%Y%m%d_%H%M%S)"; fi` }); } // Step 2: Determine if we need sudo const needsSudo = remotePath.startsWith('/etc/') || remotePath.startsWith('/var/') || remotePath.startsWith('/usr/') || owner || permissions; if (needsSudo) { strategy.requiresSudo = true; } // Step 3: Copy from temp to final location const copyCmd = needsSudo && sudoPassword ? `echo "${sudoPassword}" | sudo -S cp {{tempFile}} "${remotePath}"` : needsSudo ? `sudo cp {{tempFile}} "${remotePath}"` : `cp {{tempFile}} "${remotePath}"`; strategy.steps.push({ type: 'copy', command: copyCmd }); // Step 4: Set ownership if specified if (owner) { const chownCmd = sudoPassword ? `echo "${sudoPassword}" | sudo -S chown ${owner} "${remotePath}"` : `sudo chown ${owner} "${remotePath}"`; strategy.steps.push({ type: 'chown', command: chownCmd }); } // Step 5: Set permissions if specified if (permissions) { const chmodCmd = sudoPassword ? `echo "${sudoPassword}" | sudo -S chmod ${permissions} "${remotePath}"` : `sudo chmod ${permissions} "${remotePath}"`; strategy.steps.push({ type: 'chmod', command: chmodCmd }); } // Step 6: Restart service if specified if (restart) { strategy.steps.push({ type: 'restart', command: restart }); } // Step 7: Cleanup temp file strategy.steps.push({ type: 'cleanup', command: 'rm -f {{tempFile}}' }); return strategy; }
- src/deploy-helper.js:114-146 (helper)Detects deployment requirements based on remote path patterns (sudo needs, suggested ownership/permissions for common paths like /etc, /var/www). Used by ssh_deploy for automatic configuration.export function detectDeploymentNeeds(remotePath) { const needs = { sudo: false, suggestedOwner: null, suggestedPerms: null }; // System directories that typically need sudo if (remotePath.startsWith('/etc/')) { needs.sudo = true; needs.suggestedOwner = 'root:root'; needs.suggestedPerms = '644'; } else if (remotePath.startsWith('/var/www/')) { needs.sudo = true; needs.suggestedOwner = 'www-data:www-data'; needs.suggestedPerms = '644'; } else if (remotePath.includes('/nginx/')) { needs.sudo = true; needs.suggestedOwner = 'root:root'; needs.suggestedPerms = '644'; } else if (remotePath.includes('/apache/') || remotePath.includes('/httpd/')) { needs.sudo = true; needs.suggestedOwner = 'www-data:www-data'; needs.suggestedPerms = '644'; } else if (remotePath.includes('/frappe-bench/')) { // For ERPNext/Frappe deployments needs.sudo = false; needs.suggestedOwner = null; // Will be handled by the app needs.suggestedPerms = '644'; } return needs; }