Deploy Bash is a lightweight, ultra fast, interactive, and extensible Bash script designed to automate code deployments across multiple servers. It is built for Debian-based systems and maintained by Buffer Punk.
deploy.sh simplifies deployment workflows by handling tasks like:
- Packaging and deploying your project to multiple remote servers
- Running remote setup commands (on first deploy or updates)
- Managing symlinks for version control (via
current→ latest version) - Supporting both domain and IP-based deployments
- Handling rollbacks to previous versions
- Restarting specified systemd services
- Interactive countdowns and safety prompts
The goal: make deployment effortless, safe, and repeatable — without requiring heavy CI/CD tooling.
✅ Deploy to one or multiple servers at once
✅ Supports both IPs and domain names
✅ Optional pre-deploy and setup commands
✅ Built-in rollback mechanism
✅ NPM install support for node projects
✅ apt update support (so you don't manually run it)
✅ Keeps only a specified number of releases (--keep)
✅ Validates configuration and inputs
✅ Interactive countdown before deploy
✅ Optionally adds itself to $PATH for one-line use (deploy [options])
✅ Uses human-readable color-coded outputs
- Debian-based OS (Ubuntu, Debian, etc.)
sshaccess to target serversbash,sudo, andscpavailablednsutils(for domain validation)- Remote servers must support
systemctl
git clone https://github.com/bufferpunk/deploy-bash.git
cd deploy-bash
chmod +x deploy.sh
./deploy.shThe first run will ask if you want to add it to your $PATH:
Do you want to add it to your $PATH? (y/n)If you choose “y”, it’ll create a symlink at /usr/local/bin/deploy, so you can run it globally:
deploy [options]You can deploy with flags or a configuration file.
deploy \
--project=myapp \
--type=ip \
--servers=[192.168.1.2,192.168.1.3] \
--services=[nginx,myapp.service] \
--deploy-dir=/var/www \
--setup=full
--apt-updateCreate a config file (e.g. prod.conf):
SERVERS=[192.168.1.2,192.168.1.3]
SERVICES=[nginx,myapp.service]
TYPE="ip"
PROJECT_NAME="myapp"
DEPLOY_DIR="/var/www"
SSH_USER="ubuntu"
SSH_KEY="~/.ssh/id_rsa"
NODE_HOME="." # use relative paths
SETUP_COMMAND="echo something"
# etc ...Then deploy with:
deploy --config=deployment/prod.confIf something goes wrong, rollback to an earlier version:
deploy --rollback=2 --config=prod.confThis restores the second-most recent version and restarts your services.
The --setup flag allows running arbitrary setup commands on remote servers.
--setup=full: deploys and then runs setup--setup=only: runs setup without deploying
You’ll be asked interactively how many setup commands you want to add, for example:
How many commands do you want to run on the remote server(s)?: 2
Enter command 1: apt update -y
Enter command 2: systemctl restart nginx
The script automatically archives deployed versions and keeps a maximum number of them (default 5).
Use --keep=<number> to change that limit.
deploy --config=deployment/deploy.conf --npmOutput (simplified):
myapp/
├── deployment/
| ├── awesome.conf
| ├── prod.conf
| └── your.other.scripts
├── versions/
│ ├── myapp20251020142300/
│ ├── myapp20251019115022/
│ └── ...
└── your_other_code
| Flag | Description | |
|---|---|---|
--config=<file> |
Load configuration from a file | |
--project=<name> |
Name of the project folder | |
--servers=[a,b,...] |
Comma-separated server list | |
--services=[a,b,...] |
Comma-separated systemd service names | |
--type=<domain / ip> |
Type of server list provided | |
--deploy-dir=<path> |
Remote directory for deployment | |
--apt-update |
Run apt update on server |
|
--npm |
Run npm install on server |
after deploying |
--setup=<full / only> |
Setup and deploy, or setup only | |
--rollback=<number> |
Roll back to a previous version | |
--keep=<number> |
Number of old versions to retain | |
--help / -h |
Show usage |
MIT License © 2025 Buffer Punk
Pull requests are welcome! Please open an issue first to discuss proposed changes.
Would you like me to add example configuration files (dev.conf, prod.conf) and usage output examples to this README too? They’d make it perfect for GitHub.