@akash-chowdhury-24/deployhub
v2.0.7
Published
Zero-configuration deployment and artifact manager
Maintainers
Readme
DeployHub
Zero-configuration deployment and artifact manager for Node.js projects. When you push to GitHub, DeployHub automatically detects your project type, builds it, creates a versioned artifact, uploads to cloud storage, and optionally deploys to your server.
Supported deployment targets: SSH, Docker, EC2, Azure VM, GCP VM, and Kubernetes — self-hosted and cloud VM only.
DeployHub no longer integrates with managed platforms like Vercel or Netlify — those tools already offer superior native git-push deployment. DeployHub instead focuses on artifact-first backups and self-hosted/server deployment, where no equivalent native solution exists.
Installation
DeployHub can be installed via npm (requires Node.js 18+) or as a standalone binary (no Node.js required).
npm (recommended for Node.js projects)
npm install -g @akash-chowdhury-24/deployhubOr use locally in your project:
npm install @akash-chowdhury-24/deployhub
npx deployhub initStandalone binary (Linux / macOS)
Downloads the latest release from GitHub Releases and installs to /usr/local/bin (or ~/.local/bin without sudo):
curl -fsSL https://raw.githubusercontent.com/Akash-Chowdhury-24/DeployHub/main/install.sh | shSupported platforms: Linux x64, macOS x64, macOS ARM64. If the binary download fails, the script falls back to npm install -g.
Standalone binary (Windows)
Run in PowerShell:
irm https://raw.githubusercontent.com/Akash-Chowdhury-24/DeployHub/main/install.ps1 | iexInstalls to %LOCALAPPDATA%\Programs\DeployHub and adds it to your user PATH. On Windows ARM64, the script installs via npm instead (no native binary yet).
Manual download
Pick the asset for your platform from the latest release:
| Platform | Asset |
|----------|-------|
| Linux x64 | deployhub-linux-x64 |
| macOS x64 | deployhub-macos-x64 |
| macOS ARM64 | deployhub-macos-arm64 |
| Windows x64 | deployhub-win.exe |
Make it executable (Linux/macOS) and place it on your PATH:
chmod +x deployhub-linux-x64
sudo mv deployhub-linux-x64 /usr/local/bin/deployhub
deployhub --versionVerify installation
deployhub --version
deployhub doctorTo update an npm install: deployhub update or npm install -g @akash-chowdhury-24/deployhub@latest. For binary installs, re-run the install script or download the new release.
Quick Start
1. Initialize
deployhub initThis interactive wizard will:
- Detect your framework (React, Vue, Next.js, Node, Python, etc.)
- Configure build commands and output directory
- Set up storage providers (AWS, Google Drive, Azure, GCP, Dropbox, Local)
- Optionally configure deployment targets (SSH, Docker, EC2, Azure VM, GCP VM, Kubernetes)
- Generate
deployhub.config.json - Generate
.github/workflows/deployhub.yml - Generate
.env.example
2. Configure credentials
cp .env.example .env
# Edit .env with your credentials
deployhub storage add aws
deployhub storage add gdrive3. Run pre-flight checks
deployhub doctor4. Deploy
deployhub buildOr push to main — GitHub Actions runs deployhub build automatically.
For a full walkthrough by project type, language, and deployment mode, see Complete Tutorial below.
Complete Tutorial
This section walks through every supported setup: frontend only, backend only, full stack, storage only (build + upload artifacts, no deploy), and storage + deployment (build, upload, then deploy). Use it as a checklist from zero to a working pipeline.
What DeployHub does on every run
When you run deployhub build (locally or in GitHub Actions), DeployHub runs these stages in order:
| Stage | What happens |
|-------|----------------|
| detect | Auto-detect framework, language, build output |
| install | Install dependencies (npm ci, pip install, mvn, etc.) |
| test | Run tests (skippable via config) |
| build | Run your build command(s) |
| docker | Build Docker image if Dockerfile exists and enabled |
| artifact | Create versioned artifact.zip + metadata locally |
| storage | Upload artifact to all selected providers (parallel) |
| deploy | Deploy to targets — only if you configured deployment during init |
| verify | Hit your health-check URL — only if configured |
| notify | Slack / email / webhook — only if enabled |
Storage only means you answer No to Configure deployment? during init. You still get builds and cloud backups; nothing is pushed to a server.
Storage + deployment means you answer Yes, pick targets, and add the matching secrets. Deploy always runs after storage upload succeeds.
Prerequisites (all projects)
- Git repository with a remote (GitHub recommended for CI).
- DeployHub installed — see Installation above.
- Run from your project root (where
package.json,go.mod,pom.xml, etc. lives).
| Language / stack | You need on the machine / in CI |
|------------------|----------------------------------|
| Node.js (React, Vue, Express, NestJS, …) | Node.js 18+, npm |
| Python (FastAPI, Django, Flask) | Python 3.11+, requirements.txt or pyproject.toml |
| PHP (Laravel, Symfony) | PHP, Composer, composer.json |
| Java (Spring Boot) | JDK 17+, Maven, pom.xml |
| Go | Go 1.22+, go.mod |
| .NET | .NET 8 SDK, .csproj |
| Ruby on Rails | Ruby 3.2+, Bundler, Gemfile |
Step 1 — Initialize (every workflow)
cd your-project
deployhub initThe wizard asks the same core questions for every setup:
| Prompt | What to choose |
|--------|----------------|
| Project name | Defaults to folder name; used in artifact paths and deploy paths |
| What are you deploying? | Frontend only · Backend only · Both (monorepo / fullstack) |
| Framework | Auto-detected when possible; confirm or change |
| Build command / output | Pre-filled per framework (see Framework defaults below) |
| Storage providers | Pick one or more: Local, AWS S3, Google Drive, Azure, GCP, Dropbox |
| Configure deployment? | No = storage only · Yes = storage + deploy |
| CLI source for GitHub Actions | Default npm:@akash-chowdhury-24/deployhub is fine for most users |
Generated files:
deployhub.config.json— project settings (no secrets).github/workflows/deployhub.yml— CI pipeline.env.example— list of env vars you may neednginx.conf— auto-generated if frontend deploys to SSHDockerfile— auto-generated if missing and you chose Docker or Kubernetes deploy (your existingDockerfileis never overwritten)k8s/deployment.yamlandk8s/service.yaml— auto-generated if missing and you chose Kubernetes deploy (existing manifests are never overwritten)
Step 2 — Credentials
cp .env.example .env
# Edit .env locally
deployhub storage add aws # repeat per provider
deployhub storage add gdriveFor GitHub Actions, add the same values as repository secrets (Settings → Secrets and variables → Actions). See GitHub Secrets.
Step 3 — Verify
deployhub doctorFix any ✗ items before your first build.
Step 4 — Build (and deploy if configured)
deployhub buildOr push to main / master — the generated workflow runs the same command.
Useful follow-up commands:
deployhub artifact list # see uploaded versions
deployhub artifact restore v1.2.3 # download a past build
deployhub deploy # deploy latest artifact without rebuilding
deployhub rollback v1.2.2 # roll back on server
deployhub logs # last deployment logsWalkthrough: Storage only
Use this when you want versioned build artifacts in the cloud but deploy manually (or add deployment later).
During deployhub init
- Choose project type (frontend / backend / both).
- Select framework and confirm build settings.
- Check at least one storage provider (Local is checked by default).
- Answer Configure deployment? → No.
Resulting config
deployhub.config.json will have "deploy": [] and "pipeline": { "deploy": false }. Every deployhub build still runs detect → install → test → build → artifact → storage.
Example: React app → AWS S3 only
deployhub init
# What are you deploying? → Frontend only
# Framework → React
# Build command → npm run build
# Build output → dist
# Storage → ✓ AWS S3
# Configure deployment? → Nocp .env.example .env
# Set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_BUCKET, AWS_REGION
deployhub doctor
deployhub buildArtifacts appear under artifact/{projectName}/{date}/v{version}/ locally and in your S3 bucket.
Same steps for other languages
Storage-only init is identical for every language — only the framework/build prompts change. See Framework defaults.
Walkthrough: Storage + deployment
Use this when you want build → upload artifact → deploy in one command.
During deployhub init
- Complete project type + framework setup.
- Select storage provider(s).
- Answer Configure deployment? → Yes.
- Follow the deployment prompts (differs by project type — below).
Deployment requires at least one storage provider. DeployHub restores from the uploaded artifact on the target.
Walkthrough: Frontend only
Init choices
| Prompt | Options | |--------|---------| | What are you deploying? | Frontend only | | Framework | React, Vue, Angular, Next.js, Svelte, Astro, Vanilla JS, Other | | Configure deployment? | No (storage only) or Yes |
If Yes to deployment:
| Prompt | Options | |--------|---------| | Deployment type | ssh, docker, ec2, azure-vm, gcp-vm, kubernetes | | Host, user, deploy path | SSH credentials and remote directory |
Self-hosted server (SSH, Docker, EC2, …)
Best when you serve static files from your own VPS or cloud VM. DeployHub uploads the built dist/ (or your output dir) over SSH and can generate nginx.conf.
| Deploy type | You provide |
|-------------|-------------|
| ssh | SSH_HOST, SSH_USER, SSH_KEY, deploy path |
| docker | Docker host access / image registry per your setup |
| ec2 | SSH credentials to EC2 instance |
| azure-vm / gcp-vm | SSH to VM |
| kubernetes | Cluster credentials (via env / kubeconfig) |
Example: Vue → Google Drive + SSH
deployhub init
# Frontend only → Vue
# Storage: Local + Google Drive
# Configure deployment? Yes → ssh
# Host, user, deploy path: /var/www/my-appcp .env.example .env
# GDRIVE_* and SSH_HOST, SSH_USER, SSH_KEY
deployhub doctor
git push origin mainExample: Angular → Azure Blob + SSH
deployhub init
# Frontend only → Angular
# Build: ng build, output dist
# Storage: Azure Blob
# Configure deployment? Yes → Self-hosted → ssh
# Host, user, deploy path: /var/www/my-appAdd AZURE_*, SSH_HOST, SSH_USER, SSH_KEY to .env and GitHub Secrets. Review the generated nginx.conf and install it on the server.
Frontend framework defaults
| Framework | Build command | Output dir | Notes |
|-----------|---------------|------------|-------|
| React | npm run build | dist or build | Create React App uses build |
| Vue | npm run build | dist | Vite default |
| Angular | ng build | dist | |
| Next.js | npm run build | .next | Use Vercel/Netlify native deploy for managed hosting |
| Svelte | npm run build | public | |
| Astro | astro build | dist | |
| Vanilla JS | (none) | . | Copies static files as-is |
Walkthrough: Backend only
Backends always deploy to a self-hosted target (SSH, Docker, EC2, Azure VM, GCP VM, or Kubernetes).
Init choices
| Prompt | Typical value |
|--------|----------------|
| What are you deploying? | Backend only |
| Language / framework | See table below |
| Start command | e.g. npm start, uvicorn main:app … |
| Port | e.g. 3000, 8000, 8080 |
| Storage | At least one provider |
| Configure deployment? | Yes for storage + deploy |
| Deployment type | ssh (most common), docker, ec2, kubernetes, … |
| App name | PM2 process name on server |
| Health check URL | e.g. https://api.example.com/health |
Example: Express API → S3 + SSH
deployhub init
# Backend only → Node.js Express
# Start: npm start, port 3000
# Storage: AWS S3
# Configure deployment? Yes → ssh
# Host: 203.0.113.10, user: deploy, path: /var/www/my-api
# App name: my-api
# Health URL: https://api.example.com/healthOn the server, ensure Node.js, PM2, and your app dependencies are available. DeployHub SSHs in, extracts the artifact, runs install if needed, and restarts PM2.
Example: FastAPI → Dropbox + SSH
deployhub init
# Backend only → Python FastAPI
# Start: uvicorn main:app --host 0.0.0.0 --port 8000
# Storage: Dropbox
# Deploy: sshServer needs Python 3.11+, pip, and ideally gunicorn/uvicorn for production.
Backend framework defaults
| Framework | Language | Build | Start | Port | Test |
|-----------|----------|-------|-------|------|------|
| Express | Node | — | npm start | 3000 | npm test |
| NestJS | Node | nest build | node dist/main | 3000 | npm test |
| Fastify / Koa | Node | — | npm start | 3000 | npm test |
| FastAPI | Python | — | uvicorn main:app --host 0.0.0.0 --port 8000 | 8000 | pytest |
| Django | Python | — | gunicorn config.wsgi:application --bind 0.0.0.0:8000 | 8000 | python manage.py test |
| Flask | Python | — | gunicorn app:app --bind 0.0.0.0:5000 | 5000 | pytest |
| Laravel | PHP | — | php artisan serve | 80 | php artisan test |
| Symfony | PHP | — | php-fpm | 80 | php bin/phpunit |
| Spring Boot | Java | mvn package | java -jar target/*.jar | 8080 | mvn test |
| Go | Go | go build -o bin/app . | ./bin/app | 8080 | go test ./... |
| .NET | C# | dotnet publish -c Release -o publish | dotnet App.dll | 5000 | dotnet test |
| Rails | Ruby | bundle exec rake assets:precompile | bundle exec puma | 3000 | bundle exec rspec |
Node.js backends without a build step still get packaged; set buildCommand to empty in config if you truly have no compile step.
Java / Go / .NET always run a compile step before artifact creation.
Walkthrough: Full stack (frontend + backend)
Choose Both (monorepo / fullstack) when frontend and backend live in the same repository root (typical monorepo layout).
Init flow
- Frontend — framework, build command, output directory.
- Backend — framework, start command, port.
- Storage — one or more providers.
- Configure deployment? → Yes.
- Frontend deploy path — self-hosted SSH (static files + nginx).
- Backend deploy — SSH, Docker, EC2, etc.
DeployHub runs both builds, packs them into one artifact, uploads once, then deploys frontend and backend to their respective server targets.
Example: React + Express monorepo
deployhub init
# Both (monorepo / fullstack)
# Frontend: React, npm run build, dist
# Backend: Express, npm start, port 3000
# Storage: AWS S3 + Local
# Configure deployment? Yes
# Frontend: ssh → /var/www/my-app/public
# Backend: ssh → api.example.com, path /var/www/my-app/api, PM2 name my-app-apiSecrets: AWS + SSH_*
Layout tip: Keep package.json scripts for both apps at the repo root, or ensure build commands point to the correct paths (edit deployhub.config.json after init if your monorepo uses subfolders).
Example: React + Express, both on one VPS
deployhub init
# Both → React + Express
# Frontend deploy: Self-hosted server
# Frontend path: /var/www/my-app/public
# Backend: ssh, path /var/www/my-app/apiDeployHub generates nginx.conf to serve static files and proxy API requests.
Example: Next.js API routes only
Use Frontend only with Next.js and deploy via SSH or your platform's native git-push workflow — no separate backend entry needed.
Framework defaults by language
JavaScript / TypeScript (Node)
All JS frontends share the same install/build flow: npm ci → npm run build → artifact from output directory.
| Role | Frameworks | |------|------------| | Frontend | React, Vue, Angular, Next.js, Svelte, Astro, Vanilla | | Backend | Express, NestJS, Fastify, Koa |
Init is the same for each; only default build/output/start commands differ (tables above).
Python
- Detect:
requirements.txtcontainingfastapi,django, orflask. - Install:
pip install -r requirements.txt - Test:
pytest(ifpytest.iniexists) or Django test runner. - Build: Usually skipped (
buildCommand: null); artifact includes source + dependencies list. - Deploy (SSH): Server must have Python + pip; start command runs uvicorn/gunicorn.
PHP
- Detect:
composer.jsonwithlaravel/frameworkorsymfony/framework-bundle. - Install: Composer (on CI and server).
- Deploy: SSH with PHP-FPM or
php artisanfor Laravel.
Java
- Detect:
pom.xmlwith Spring Boot. - Install/Build:
mvn packageproduces JAR intarget/. - Deploy: SSH runs
java -jar target/*.jar(or your custom start command).
Go
- Detect:
go.modpresent. - Build:
go build -o bin/app . - Artifact:
bin/binary + any config files. - Deploy: SSH copies binary and restarts process.
.NET
- Detect:
.csprojin project root. - Build:
dotnet publish -c Release -o publish - Deploy: SSH runs
dotnet YourApp.dllfrom publish folder.
Ruby
- Detect:
Gemfilewithrails. - Build:
bundle exec rake assets:precompile(for production assets). - Deploy: SSH with
bundle exec pumaor your configured start command.
GitHub Actions setup
After init, commit these files:
git add deployhub.config.json .github/workflows/deployhub.yml .env.example
git commit -m "Add DeployHub CI"- Open Settings → Secrets and variables → Actions in your GitHub repo.
- Add every secret listed at the end of
deployhub init(storage + deployment). - Push to
mainormaster— the workflow triggers on push.
The workflow installs the correct language runtime (Node, Python, Java, Go, .NET, Ruby) based on your deployhub.config.json, installs DeployHub, runs deployhub build, and uses your secrets.
To run manually: Actions → DeployHub → Run workflow.
Choosing storage providers
| Provider | Good for | Setup command |
|----------|----------|---------------|
| Local | Dev/testing, no cloud account | No credentials |
| AWS S3 | Production, CI-friendly | deployhub storage add aws |
| Google Drive | Small teams, manual downloads | deployhub storage add gdrive |
| Azure Blob | Azure ecosystem | deployhub storage add azure |
| GCP Storage | GCP ecosystem | deployhub storage add gcp |
| Dropbox | Simple off-site backup | deployhub storage add dropbox |
You can enable multiple providers — DeployHub uploads to all of them in parallel on every build.
Deployment target cheat sheet
| Project type | Frontend deploy options | Backend deploy options | |--------------|-------------------------|------------------------| | Frontend only | SSH/Docker/EC2/Azure VM/GCP VM/K8s | — | | Backend only | — | SSH/Docker/EC2/Azure VM/GCP VM/K8s | | Full stack | SSH (static + nginx) | SSH/Docker/EC2/K8s (always) |
| Mode | Storage | Deploy | When to use | |------|---------|--------|-------------| | Storage only | ✓ | ✗ | Backups, audit trail, manual releases | | Storage + deploy | ✓ | ✓ | Full CI/CD |
Choosing a deployment method
DeployHub supports six deployment targets. Pick based on what infrastructure you already have — DeployHub does not provision servers, VMs, or clusters for you.
| Method | Best for | You need already | |--------|----------|------------------| | ssh | Any Linux VPS or bare-metal server you control | Server with SSH, key pair, app runtime | | docker | Containerized apps (Dockerfile or docker-compose.yml) | Docker locally or on a remote host | | ec2 | AWS users with an existing EC2 instance | Running EC2 instance, security group, key pair | | azure-vm | Azure users with an existing virtual machine | Running Azure VM, NSG allowing SSH | | gcp-vm | GCP users with an existing Compute Engine VM | Running VM, firewall rule for SSH, metadata SSH key | | kubernetes | Teams with an existing K8s cluster | Cluster, kubectl access; manifests auto-generated if missing |
Deployment method guides
Each method below follows the same structure: prerequisites (before deployhub init), what DeployHub automates, after init (matches terminal output), and a variable reference.
One-time server setup (before your first deploy)
SSH-based methods (SSH, EC2, Azure VM, GCP VM) require a few one-time steps on the server before your first deploy. DeployHub does not silently change ownership or sudo policy for you.
SSH into your server once and run:
sudo mkdir -p /var/www/your-app-name
sudo chown your-ssh-user:your-ssh-user /var/www/your-app-nameReplace /var/www/your-app-name with your actual deploy path and your-ssh-user with your configured SSH_USER (e.g. ec2-user on Amazon Linux, ubuntu on Ubuntu). Without this, DeployHub cannot write your build output — deployhub doctor will catch it and show the exact fix.
Frontend deploys that auto-activate nginx.conf also need passwordless sudo for Nginx test/reload (and cp into /etc/nginx/). After installing Nginx, run sudo visudo and add a line like:
your-ssh-user ALL=(ALL) NOPASSWD: /usr/sbin/nginx, /bin/cp, /usr/bin/cp, /bin/systemctl, /usr/bin/systemctlSecurity note: This example grants broad privileges — unrestricted
cp(any source/destination) andsystemctl(any unit/action), not just Nginx. That keeps setup simple but is a significant trust boundary. For production, prefer a dedicated deploy user and a narrow wrapper script (e.g./usr/local/bin/deployhub-nginx-reloadthat only copies to your project's config path and runsnginx -t+ reload), then grantNOPASSWDonly for that script. The line above is a starting point for dev/test servers; tighten it before production.
Install Nginx if it is not already present:
- Amazon Linux / RHEL:
sudo yum install -y nginx && sudo systemctl enable --now nginx - Ubuntu / Debian:
sudo apt install -y nginx
DeployHub detects whether the server uses Debian-style sites-available or RHEL-style conf.d at deploy time and writes a uniquely named config file for your project only — it does not overwrite unrelated Nginx configs.
SSH
Prerequisites (before deployhub init):
- [ ] Complete one-time server setup (deploy path ownership + Nginx/sudo for frontends)
- [ ] A Linux server with SSH enabled
- [ ] Private SSH key file (.pem/.key) and public key in
authorized_keys - [ ] Port 22 open in firewall for your IP
- [ ] Deploy directory writable by your SSH user (e.g.
sudo mkdir -p /var/www/my-app && sudo chown ubuntu:ubuntu /var/www/my-app—/var/wwwis root-owned on most fresh Linux images) - [ ] App runtime on server (Node.js, Python, etc.) for backends
What DeployHub automates:
- Complete
.env.examplewith commented variables - SSH key permission check (offers to
chmod 600) - SSH connectivity test during
init - Deploy path write-permission check during
deployhub doctor - Nginx layout detection (Debian
sites-availablevs RHELconf.d) at deploy time - Nginx config test (
nginx -t) before reload - Passwordless sudo and Nginx checks during
deployhub doctor(frontend) - Artifact upload, extract, app restart (PM2, gunicorn, etc.)
After init:
- Ensure port 22 is open in your server firewall
- Ensure your deploy directory exists and is owned by your SSH user (see prerequisite above if
deployhub doctorreports permission denied) - Copy
.env.example→.env; setSSH_HOST,SSH_USER,SSH_KEY_PATH - Add GitHub Secrets:
SSH_HOST,SSH_USER,SSH_KEY(paste private key for CI) - Run
deployhub doctor git push origin main
| Variable | Description | Example | Where to get it |
|----------|-------------|---------|-----------------|
| SSH_HOST | Server IP or hostname | 203.0.113.10 | Your hosting provider dashboard |
| SSH_USER | SSH login user | ubuntu | AMI/image docs (Ubuntu→ubuntu, Amazon Linux→ec2-user) |
| SSH_KEY_PATH | Path to private key file | ~/.ssh/my-key.pem | Downloaded when server was created |
| SSH_SSH_PORT | SSH port (optional) | 22 | Server SSH config |
| SSH_DEPLOY_PATH | Remote deploy directory | /var/www/my-app | Your server layout |
| SSH_APP_NAME | PM2 process name (backend) | my-api | Your choice |
| SSH_PORT | App listen port (backend) | 3000 | Your app config |
| SSH_KEY | Private key contents (CI only) | -----BEGIN... | Same key as SSH_KEY_PATH |
Docker
Prerequisites:
- [ ] Docker installed (
docker --versionworks) - [ ] Registry account if pushing private images
- [ ]
docker-compose.ymlin project if you use multi-service Compose (not auto-generated)
What DeployHub automates:
- Starter
Dockerfileat project root when none exists (framework-aware; skipped if you already have one) .env.examplefor image name, registry, remoteDOCKER_HOST- Docker daemon connectivity test during
init docker compose upor build/push/run during deploy
After init:
- Set
DOCKER_IMAGE_NAMEin.env - For private registries: set
DOCKER_REGISTRY_USERNAMEandDOCKER_REGISTRY_TOKEN - For remote Docker: set
DOCKER_HOST(e.g.ssh://[email protected]) - Run
deployhub doctor, thengit push origin main
| Variable | Description | Example | Where to get it |
|----------|-------------|---------|-----------------|
| DOCKER_IMAGE_NAME | Image repository path | myorg/myapp | Your registry naming |
| DOCKER_IMAGE_TAG | Image tag | latest | Version or latest |
| DOCKER_REGISTRY_URL | Registry URL (optional) | https://ghcr.io | Registry docs |
| DOCKER_REGISTRY_USERNAME | Registry user | myuser | Registry account |
| DOCKER_REGISTRY_TOKEN | Registry password/token | (secret) | Docker Hub / GHCR PAT |
| DOCKER_HOST | Remote daemon (optional) | ssh://ubuntu@host | Remote Docker setup |
AWS EC2
Prerequisites:
- [ ] Complete one-time server setup (
ec2-useron Amazon Linux) - [ ] EC2 instance launched in AWS Console (DeployHub does not create it)
- [ ] Key pair
.pemdownloaded at launch - [ ] Security group: inbound SSH (22) from your IP
- [ ] Deploy directory writable by your SSH user (e.g.
sudo mkdir -p /var/www/my-app && sudo chown ec2-user:ec2-user /var/www/my-app—/var/wwwis root-owned on Amazon Linux by default) - [ ] App runtime on instance for backends
What DeployHub automates:
- EC2-specific
.env.example(SSH + optional AWS API vars) - SSH key validation and connectivity test
- Deploy path write-permission check during
deployhub doctor - Nginx layout detection and config test before reload (frontend)
- Passwordless sudo and Nginx checks during
deployhub doctor(frontend) - OS user suggestion from AMI hint (ubuntu, ec2-user)
- Optional public IP lookup via
EC2_INSTANCE_ID+ AWS CLI
After init:
- AWS Console → EC2 → Security Groups → Inbound rules → SSH port 22 from My IP
- Ensure your deploy directory exists and is owned by your SSH user (see prerequisite above if
deployhub doctorreports permission denied) - Copy
.env.example→.env; setSSH_KEY_PATH,SSH_HOST(orEC2_INSTANCE_ID+ AWS creds) - GitHub Secrets:
SSH_HOST,SSH_USER,SSH_KEY, plusAWS_*if using instance ID lookup - Run
deployhub doctor, thengit push origin main
| Variable | Description | Example | Where to get it |
|----------|-------------|---------|-----------------|
| SSH_HOST | Instance public IP/DNS | 54.123.45.67 | EC2 Console → Instances |
| SSH_USER | SSH user for AMI | ec2-user | AMI documentation |
| SSH_KEY_PATH | Path to .pem key | ~/.ssh/ec2-key.pem | Downloaded at instance launch |
| EC2_INSTANCE_ID | Instance ID (optional) | i-0abc123... | EC2 Console |
| AWS_ACCESS_KEY_ID | AWS key for API lookup | AKIA... | IAM → Users → Security credentials |
| AWS_SECRET_ACCESS_KEY | AWS secret | (secret) | Same as above |
| AWS_REGION | Instance region | us-east-1 | EC2 Console top bar |
Azure VM
Prerequisites:
- [ ] Complete one-time server setup (
azureuseror your VM login user) - [ ] Azure VM created in Portal (DeployHub does not provision it)
- [ ] NSG rule allowing inbound SSH (port 22)
- [ ] SSH public key on the VM
- [ ] Deploy directory writable by your SSH user (e.g.
sudo mkdir -p /var/www/my-app && sudo chown azureuser:azureuser /var/www/my-app) - [ ] App runtime for backends
What DeployHub automates:
- Azure VM
.env.examplewith SSH + optional Azure API vars - Auto-detects subscription ID via
azCLI if logged in - SSH key validation and connectivity test
- Deploy path write-permission check during
deployhub doctor - Nginx layout detection and config test before reload (frontend)
- Passwordless sudo and Nginx checks during
deployhub doctor(frontend)
After init:
- Azure Portal → VM → Networking → allow SSH (22) from your IP
- Ensure your deploy directory exists and is owned by your SSH user (see prerequisite above if
deployhub doctorreports permission denied) - Copy
.env.example→.env; setSSH_HOST,SSH_USER,SSH_KEY_PATH - For CI: add
AZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_CLIENT_SECRETas GitHub Secrets - Run
deployhub doctor, thengit push origin main
| Variable | Description | Example | Where to get it |
|----------|-------------|---------|-----------------|
| SSH_HOST | VM public IP | 20.1.2.3 | Azure Portal → VM overview |
| SSH_USER | SSH username | azureuser | Chosen at VM creation |
| SSH_KEY_PATH | Private key path | ~/.ssh/azure.pem | Your key file |
| AZURE_SUBSCRIPTION_ID | Subscription (optional) | uuid | az account show |
| AZURE_RESOURCE_GROUP | Resource group | my-app-rg | Portal → Resource groups |
| AZURE_VM_NAME | VM name | my-vm | Portal → Virtual machines |
GCP VM
Prerequisites:
- [ ] Complete one-time server setup (your GCP SSH username)
- [ ] Compute Engine VM created (DeployHub does not create it)
- [ ] Firewall rule allowing
tcp:22(defaultdefault-allow-sshmay exist) - [ ] SSH public key in Metadata → SSH Keys (GCP uses metadata keys, not launch key pairs like AWS)
- [ ] Deploy directory writable by your SSH user (e.g.
sudo mkdir -p /var/www/my-app && sudo chown $USER:$USER /var/www/my-app) - [ ] App runtime for backends
What DeployHub automates:
- GCP VM
.env.examplewith SSH + optional GCP API vars - Auto-detects project ID via
gcloudif authenticated - SSH key validation and connectivity test
- Deploy path write-permission check during
deployhub doctor - Nginx layout detection and config test before reload (frontend)
- Passwordless sudo and Nginx checks during
deployhub doctor(frontend)
After init:
- GCP Console → VPC → Firewall → ensure SSH (tcp:22) allowed from your IP
- Add SSH public key: Console → Compute Engine → Metadata → SSH Keys
- Ensure your deploy directory exists and is owned by your SSH user (see prerequisite above if
deployhub doctorreports permission denied) - Copy
.env.example→.env; setSSH_HOST,SSH_USER,SSH_KEY_PATH - Run
deployhub doctor, thengit push origin main
| Variable | Description | Example | Where to get it |
|----------|-------------|---------|-----------------|
| SSH_HOST | External IP | 34.56.78.90 | Compute Engine → VM instances |
| SSH_USER | SSH username | your_google_username | GCP OS Login or metadata |
| SSH_KEY_PATH | Private key path | ~/.ssh/gcp-key | Your local key pair |
| SSH_SSH_PORT | SSH connection port (optional) | 22 | Server SSH config |
| SSH_DEPLOY_PATH | Remote deploy directory (optional) | /var/www/my-app | Your server layout |
| SSH_APP_NAME | PM2 process name (backend) | my-api | Your choice |
| SSH_PORT | App listen port (backend) | 3000 | Your app config |
| SSH_KEY | Private key contents (CI only) | -----BEGIN... | Same key as SSH_KEY_PATH |
| GCP_PROJECT_ID | Project ID (optional) | my-project-123 | gcloud config get-value project |
| GCP_ZONE | VM zone (optional) | us-central1-a | VM instance details |
| GCP_INSTANCE_NAME | Instance name (optional) | my-vm | Compute Engine list |
| GCP_KEY_FILE | Service account JSON (optional, CI) | /path/to/key.json | IAM → Service Accounts → Keys |
Kubernetes
Prerequisites:
- [ ] Existing Kubernetes cluster (DeployHub does not provision clusters)
- [ ]
kubectlinstalled and configured on your local machine (fordeployhub doctor/ manualdeployhub deploy) - [ ] Cluster reachable from CI (kubeconfig secret or cloud auth)
What DeployHub automates:
- Starter
k8s/deployment.yamlandk8s/service.yamlwhen no manifests exist (skipped if you already have ak8s/directory or root-level Kubernetes YAML files) - GitHub Actions installs
kubectlon the CI runner and writes kubeconfig from secrets (no localkubectlrequired for the automated push-to-main deploy path) - Lists
kubectlcontexts duringinitfor easy selection - Auto-detects
~/.kube/config - Complete
.env.examplefor kubeconfig, context, namespace - Cluster connectivity test during
init
After init:
- Verify context:
kubectl config get-contexts - Create namespace if needed:
kubectl create namespace my-app - For private registries: create
imagePullSecretand setKUBE_IMAGE_PULL_SECRET - Copy
.env.example→.env; add kubeconfig/auth to GitHub Secrets for CI - Run
deployhub doctor, thengit push origin main
| Variable | Description | Example | Where to get it |
|----------|-------------|---------|-----------------|
| KUBECONFIG | Path to kubeconfig | ~/.kube/config | Default kubectl config |
| KUBE_CONTEXT | Context name | my-cluster | kubectl config get-contexts |
| KUBE_NAMESPACE | Target namespace | my-app | kubectl get namespaces |
| DOCKER_IMAGE_NAME | Container image | ghcr.io/org/app | Your registry |
| DOCKER_IMAGE_TAG | Image tag | 1.0.0 or latest | Project version or your choice |
| KUBE_IMAGE_PULL_SECRET | Pull secret name | regcred | kubectl create secret docker-registry |
Minimal deployhub.config.json examples
Storage only — React
{
"project": "my-react-app",
"projectType": "frontend",
"framework": "react",
"buildCommand": "npm run build",
"buildOutput": "dist",
"storage": ["local", "aws"],
"deploy": [],
"pipeline": { "test": true, "deploy": false, "verify": false }
}Storage + deploy — FastAPI on SSH
{
"project": "my-api",
"projectType": "backend",
"framework": "fastapi",
"language": "python",
"startCommand": "uvicorn main:app --host 0.0.0.0 --port 8000",
"port": 8000,
"storage": ["aws"],
"deploy": ["production"],
"environments": {
"production": {
"deploymentType": "server",
"type": "ssh",
"host": "203.0.113.10",
"user": "deploy",
"deployPath": "/var/www/my-api",
"appName": "my-api",
"framework": "fastapi"
}
},
"pipeline": { "deploy": true, "verify": true },
"healthCheck": { "url": "https://api.example.com/health", "timeout": 30 }
}Prefer deployhub init over hand-writing config — it sets adapters, workflow, and secrets list correctly.
Troubleshooting
| Problem | Fix |
|---------|-----|
| Deploy requires storage upload | Add at least one storage provider in config |
| AWS / GDrive check fails in doctor | Run deployhub storage add <provider> and match GitHub Secrets |
| SSH deploy fails | Verify SSH_KEY_PATH points to your private .pem file (or SSH_KEY in CI); user can write to deploy path; port 22 open |
| Wrong output uploaded | Fix buildOutput in config (dist vs build vs .next) |
| Tests fail in CI | Set "pipeline": { "test": false } temporarily, or fix tests |
| Monorepo subfolders | Edit buildCommand paths in deployhub.config.json after init |
Run deployhub doctor after any config change.
Commands
| Command | Description |
|---------|-------------|
| deployhub init | Interactive project setup |
| deployhub build | Full pipeline: detect → install → test → build → artifact → storage → deploy |
| deployhub artifact create | Create artifact from current build |
| deployhub artifact list | List all artifacts |
| deployhub artifact restore <version> | Download and extract an artifact |
| deployhub storage add <provider> | Add storage provider credentials |
| deployhub storage list | List storage providers and connection status |
| deployhub deploy | Deploy latest artifact |
| deployhub rollback [version] | Rollback to a previous version |
| deployhub logs | Show logs from last deployment |
| deployhub doctor | Pre-flight checks |
| deployhub verify | Health check on configured endpoint |
| deployhub clean | Remove old local artifacts |
| deployhub update | Check for CLI updates |
GitHub Secrets
Add these secrets in your repository (Settings → Secrets and variables → Actions). Only add secrets for providers you selected during init. At the end of deployhub init, DeployHub prints the exact list for your project.
Storage
| Secret | Provider |
|--------|----------|
| AWS_ACCESS_KEY_ID | AWS S3 |
| AWS_SECRET_ACCESS_KEY | AWS S3 |
| AWS_BUCKET | AWS S3 |
| AWS_REGION | AWS S3 |
| GDRIVE_CLIENT_ID | Google Drive |
| GDRIVE_CLIENT_SECRET | Google Drive |
| GDRIVE_REFRESH_TOKEN | Google Drive |
| GDRIVE_FOLDER_ID | Google Drive |
| AZURE_CONNECTION_STRING | Azure Blob |
| AZURE_CONTAINER | Azure Blob |
| GCP_PROJECT_ID | GCP Storage |
| GCP_KEY_FILE | GCP Storage |
| GCP_BUCKET | GCP Storage |
| DROPBOX_ACCESS_TOKEN | Dropbox |
| FTP_HOST, FTP_USER, FTP_PASSWORD | FTP storage |
Server deployment (SSH, EC2, VMs, Docker, Kubernetes)
| Secret | Used for |
|--------|----------|
| SSH_HOST | Target server hostname or IP |
| SSH_USER | SSH username |
| SSH_KEY_PATH | Local path to private key (.env only) |
| SSH_KEY | Private key contents (GitHub Actions / CI) |
| SSH_SSH_PORT | SSH connection port (default 22) |
| SSH_DEPLOY_PATH | Remote directory (optional if set in config) |
| SSH_APP_NAME | PM2 process name for backends |
| SSH_PORT | App port on server (backend) |
| EC2_INSTANCE_ID, AWS_* | Optional EC2 dynamic IP lookup |
| AZURE_SUBSCRIPTION_ID, AZURE_RESOURCE_GROUP, AZURE_VM_NAME | Optional Azure VM IP lookup |
| GCP_PROJECT_ID, GCP_ZONE, GCP_INSTANCE_NAME, GCP_KEY_FILE | Optional GCP VM IP lookup |
| DOCKER_IMAGE_NAME, DOCKER_REGISTRY_*, DOCKER_HOST | Docker deployment |
| KUBECONFIG, KUBE_CONTEXT, KUBE_NAMESPACE | Kubernetes deployment |
See Deployment method guides for full per-method variable tables with examples.
deployhub doctor Output
The doctor command runs independent checks and always completes without crashing:
Checking Git... ✓ Git installed, repo detected, remote set
Checking Docker... ✓ Docker running
Checking Build command... ✓ "npm run build" found in package.json
Checking AWS... ✓ Credentials valid, bucket accessible
Checking Google Drive... ✓ Connected
Checking SSH target... ✓ Can reach host
Checking Health endpoint... ✓ URL reachable (HTTP 200)
Checking Secrets... ✓ All required env vars present
Checking GitHub Actions... ✓ Workflow file exists at .github/workflows/deployhub.yml
Checking Storage write... ✓ Test upload succeeded
✓ Ready to deploy (10/10 checks passed)If checks fail:
Checking AWS... ✗ Missing: AWS_SECRET_ACCESS_KEY
Checking Health endpoint... ✗ No URL configured
8/10 — fix the 2 issues above before deployingArtifact Structure
Each build creates:
artifact/
{projectName}/
{YYYY-MM-DD}/
v{semver}/
artifact.zip
metadata.json
logs.txt
checksums.txt
deployment.json
release-notes.md
README.mddeployment.json records server deployment metadata per environment:
{
"targets": ["production"],
"deployedAt": "2026-07-01T12:00:00.000Z",
"deployments": [
{
"environmentName": "production",
"serverAddress": "203.0.113.10",
"processId": "my-api",
"timestamp": "2026-07-01T12:00:00.000Z"
}
]
}Rollback redeploys a previous artifact to the configured server targets using this metadata.
Configuration
deployhub.config.json is generated by init. Credentials are never stored in this file — only in .env or GitHub Secrets.
Pipeline Stages
- detect — auto-detect project type
- install — install dependencies
- test — run test suite (skippable)
- build — run build command
- docker — build Docker image (skippable)
- artifact — create artifact.zip + metadata
- storage — upload to all configured providers (parallel)
- deploy — deploy to configured targets
- verify — health check after deployment
- notify — send Slack/email/webhook notifications
Author
Akash Chowdhury 📧 [email protected] 💼 linkedin.com/in/akash-chowdhury-12141a222
Built with ❤ — if DeployHub saves you time, feel free to connect on LinkedIn.
License
MIT
