Skip to content

DarUlHasnat/Server-Deployer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Server Manager - Secure Local Deployment Automation Tool

A production-grade, local-only deployment automation tool written in Go. Designed for paranoid systems engineers who manage 50+ production applications across multiple VPS servers.

Key Principles

  • Local-Only: All configuration, secrets, and deployment logic remain on your local machine
  • Zero Server State: Servers are execution-only targets with no deployment metadata stored
  • Automatic Rollback: Failed migrations trigger immediate rollback of database and files
  • Full Audit Trail: Every deployment step is logged locally with timestamps

Features

  • Interactive Setup: Scaffold new apps easily using an interactive wizard
  • Automated Provisioning: Automatically configure Nginx, SSL (Certbot), and PM2
  • Local Build Pipeline: Build locally and only upload the dist/build directory to save bandwidth
  • Environment Management: Inject build-time variables and securely sync server variables
  • SSH key-based authentication (no passwords)
  • YAML configuration files for servers and applications
  • Automatic database backups before deployments (MySQL/PostgreSQL)
  • Automatic application file backups
  • Rsync-based file synchronization
  • Build, migrate, and restart command execution
  • HTTP and process-based health checks
  • Automatic rollback on migration failure
  • Manual rollback command
  • Backup retention management
  • Multi-runtime support (Node.js, PHP, Python, Go, Ruby)

Installation

Prerequisites

  • Go 1.21 or later
  • rsync installed locally
  • SSH access to target servers

Build from Source

# Clone or download to your machine
cd server-manager

# Download dependencies
go mod download

# Build the binary
go build -o bin/deployer ./cmd/deployer

# Or use the build script
go run build.go

# Build for all platforms
go run build.go --all

Install Globally

sudo cp bin/deployer /usr/local/bin/

Directory Structure

server-manager/
├── bin/                    # Compiled binaries
├── cmd/
│   └── deployer/
│       └── main.go         # CLI entry point
├── internal/
│   ├── config/             # Configuration parsing
│   ├── ssh/                # SSH client wrapper
│   ├── backup/             # Backup/restore operations
│   ├── deploy/             # Deployment orchestration
│   ├── rollback/           # Rollback operations
│   ├── health/             # Health checks
│   ├── status/             # Status reporting
│   └── logger/             # Logging system
├── configs/
│   ├── servers/            # Server configurations (*.yaml)
│   └── apps/               # Application configurations (*.yaml)
├── backups/                # Local backup metadata
├── releases/               # Release artifacts
├── logs/                   # Deployment logs
├── go.mod
└── README.md

Configuration

Server Configuration

Create a YAML file in configs/servers/:

# configs/servers/production-web-01.yaml
name: production-web-01
host: 192.168.1.100
ssh_user: deploy
ssh_port: 22

# Authentication - choose ONE of the following options:

# Option 1: SSH Key (RECOMMENDED)
auth_type: ssh_key
ssh_key_path: ~/.ssh/deploy_key

# Option 2: Plain Password
# auth_type: password
# ssh_password: your_password_here

# Option 3: Base64 Encoded Password
# auth_type: base64_password
# ssh_password_b64: eW91cl9wYXNzd29yZA==

# Global Backup Options (Used by `deployer server-backup`)
database:
  mysql:
    user: root
    password: my_password
    port: 3306

localdatabases_backup_path: ~/backups/servers
ecosystem_file_path: /var/www/ecosystem.config.js

Authentication Types

Type Field Description
ssh_key ssh_key_path Path to SSH private key (recommended)
password ssh_password Plain text password
base64_password ssh_password_b64 Base64 encoded password

Generating Base64 Password:

echo -n "your_password" | base64
# Output: eW91cl9wYXNzd29yZA==

Note: For password-based authentication, you need sshpass installed:

# Debian/Ubuntu
sudo apt install sshpass

# RHEL/CentOS
sudo yum install sshpass

# macOS
brew install hudochenkov/sshpass/sshpass

Application Configuration

Generate configurations using the interactive wizard (deployer init my-app), or create a YAML file in configs/apps/:

# configs/apps/my-app.yaml
app_name: my-app
server_name: production-web-01
local_path: ~/projects/my-app
app_path: /var/www/my-app
runtime: node
port: 3000

# Used by `deployer provision`
domains:
  - my-app.example.com

# Build Configuration
local_build_cmd: npm ci && npm run build
build_dir: dist
build_command: npm ci --production

# Environment Variables
env_build:
  NODE_ENV: production
env_server:
  DATABASE_URL: postgres://user:pass@localhost:5432/mydb
  PORT: "3000"

migrate_command: npm run migrate
restart_command: pm2 restart my-app || pm2 start ecosystem.config.js

# Specific directories to backup out of the app tree when using `deployer backup-dirs`
directories_for_backup:
  - "public/uploads"
  - "storage/app"

# Directories to preserve on server and NEVER overwrite or delete (e.g., user uploads, static files)
persistent_paths:
  - "public/uploads"
  - "storage/app"

# Whether to delete files on the server that are not in the local directory (default: false)
delete_on_deploy: false

health_check:
  type: http
  endpoint: /health
  port: 3000
  timeout: 30
  retries: 3

database:
  type: postgres
  name: my_app_db
  user: app_user
  password: "your_secure_password"
  host: localhost
  port: 5432
  backup_path: /var/backups/my-app

exclude_files:
  - "*.log"
  - "tmp/*"

Usage

Interactive App Setup (Recommended)

deployer init my-app

Provision Server (Nginx, SSL, PM2)

deployer provision my-app

Deploy an Application

# Basic deployment
deployer deploy my-app

# Deploy with specific steps skipped
deployer deploy --skip-migration my-app
deployer deploy --skip-server-build --skip-restart my-app

# Force upload (skip database and app backups)
deployer deploy --force my-app

Deployment Options:

  • --skip-migration: Skip the database migration step
  • --skip-server-build: Skip the server build step (build_command)
  • --skip-restart: Skip the application restart step
  • --skip-backup: Skip the database and application backup steps
  • --skip-health-check: Skip the health check step
  • --force: Force upload (equivalent to skipping backups)

Rollback to Previous Version

deployer rollback my-app

Create Manual Backup

# Backup app specifically (app files + app database)
deployer backup my-app

# Backup specific directories defined in directories_for_backup
deployer backup-dirs my-app

# Restore specific directories zip over live path
deployer restore-dirs my-app /path/to/dirs.zip

# Backup entire server globally (all mysql + postgres dbs + pm2 ecosystem)
deployer server-backup my-server

# Restore entire server from zip (seeds all db files over pipes)
deployer server-restore my-server /path/to/server.zip

Check Application Status

# Single app
deployer status my-app

# All apps
deployer status --all

List Configurations

deployer list

Validate Configuration

# Validate specific app
deployer validate my-app

# Validate all configs
deployer validate

View Deployment Logs

deployer logs my-app

List Available Backups

deployer backups my-app

Dry Run (No Changes)

deployer -dry-run deploy my-app

Verbose Output

deployer -v deploy my-app

Deployment Flow

The deployment process follows these exact steps:

  1. Validate Configuration - Verify all configs are valid
  2. Local Build - Optional: Run local_build_cmd and inject env_build variables
  3. Connect to Server - Establish SSH connection
  4. Backup Database - Optional: Create timestamped database dump
  5. Backup Application - Copy current app directory
  6. Upload Files - Rsync new files (or just build_dir) to server
  7. Sync Environment Variables - Optional: Generate and upload .env securely
  8. Run Build Command - Optional: Execute build on remote server
  9. Run Migrations - Optional: Execute database migrations
  10. Restart Application - Restart the service via PM2/systemd
  11. Health Check - Verify application is running

Automatic Rollback

If any step after backup fails, the system automatically:

  1. Restores the database from backup
  2. Restores the application files from backup
  3. Restarts the application
  4. Logs the failure and rollback

Security Considerations

What This Tool Does Right

  • No secrets on servers: Database passwords never leave your machine
  • SSH key authentication only: No password-based SSH
  • Timestamped backups: Full audit trail with checksums
  • Local-only configs: Nothing sensitive stored remotely
  • Minimal dependencies: Only 2 external Go packages (both from trusted sources)

Recommended Server Setup

  1. Create a dedicated deploy user:
sudo useradd -m -s /bin/bash deploy
sudo mkdir -p /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
  1. Generate SSH key (on your local machine):
ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -C "deploy@server-manager"
chmod 600 ~/.ssh/deploy_key
  1. Copy public key to server:
ssh-copy-id -i ~/.ssh/deploy_key.pub deploy@your-server
  1. Grant necessary permissions:
# Allow deploy user to restart services (add to sudoers)
echo "deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart *" | sudo tee /etc/sudoers.d/deploy
echo "deploy ALL=(ALL) NOPASSWD: /bin/systemctl reload php*-fpm" | sudo tee -a /etc/sudoers.d/deploy
  1. Set correct file permissions:
# Config files should only be readable by you
chmod 600 configs/servers/*.yaml
chmod 600 configs/apps/*.yaml

Security Checklist

  • SSH keys have 600 permissions
  • Config files have 600 permissions
  • Deploy user has minimal sudo privileges
  • Servers have fail2ban or similar
  • SSH root login is disabled
  • SSH password authentication is disabled
  • Database passwords are strong (32+ characters)
  • Backup directories have restricted permissions

Exit Codes

Code Meaning
0 Success
1 Error (deployment failed, no rollback)
2 Deployment failed but rollback succeeded

Troubleshooting

SSH Connection Failed

# Test SSH connection manually
ssh -i ~/.ssh/deploy_key -p 22 deploy@your-server

# Check key permissions
ls -la ~/.ssh/deploy_key  # Should be -rw-------

Rsync Errors

# Verify rsync is installed locally
which rsync

# Test rsync manually
rsync -avz -e "ssh -p 22 -i ~/.ssh/deploy_key" ./test/ deploy@server:/tmp/test/

Database Backup Failed

# Verify database credentials by SSH-ing to server
ssh deploy@server
mysqldump --user=dbuser --password=dbpass dbname > /dev/null
# or
PGPASSWORD='dbpass' pg_dump -U dbuser dbname > /dev/null

Contributing

This is a single-purpose tool designed for reliability over features. Keep it simple.

License

MIT License - Use at your own risk. Always test in staging first.

About

A zero-agent, local-first deployment automation tool for VPS. Features incremental rsync, auto-rollbacks, and database backups.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors