Skip to main content

🚀 uhdeploy - Universal Deployer CLI

A modern, declarative, and color-rich deployment CLI tool for web applications, Docker containers, and static sites. Deploy seamlessly from your local machine to any Linux VPS or hosting server using SSH/SFTP or FTP.


📦 Installation

Install uhdeploy directly via pip:

pip install uhdeploy

Or install from source for development:

git clone https://github.com/AbdullahAhmad-0/Universal-Deployer.git
cd Universal-Deployer
pip install -e .

✨ Features

  • Global CLI Command: Run uhdeploy anywhere in your terminal.
  • YAML + Dockerfile-Style Syntax: Configure complex builds and deployments using intuitive directives like RUN, COPY, CMD, WORKDIR, and ENV.
  • Interactive File Discovery: If deploy.yml is not found in the current folder, uhdeploy prompts you to enter your project directory or file path automatically.
  • Dual Protocol Support:
    • SSH / SFTP: Full remote terminal execution (paramiko), automated directory sync, and Docker container orchestration.
    • FTP: Built-in FTP transfer (ftplib) for static/shared hosting environments (with graceful warnings for unsupported remote commands).
  • Flexible Docker Workflows:
    • Local Build & Tar Transfer (Default): Builds the Docker image locally, exports it to a .tar archive, transfers it via SFTP, and loads it into the remote Docker daemon. This saves RAM and CPU on low-spec VPS servers!
    • Remote Build: Syncs files and triggers docker compose build directly on the VPS.
    • Auto Environment Sync: Automatically detects and syncs environment files (e.g. .env.production) referenced in your docker-compose.yml.
  • Traditional (No Docker) Deployments: Perfect for static frontends (React, Vue, Next.js static exports, Vite) or traditional Node/Python/PHP apps with local builds and Nginx reloading.
  • Dynamic Variable Substitution: Seamlessly interpolate ${VPS_IP}, ${SSH_KEY_PATH}, or custom environment variables from .env or .env.deploy files.
  • Rich Terminal UI: Full ANSI color formatting with colorama, interactive numbered selection menus, step badges ([Docker], [SSH], [FTP]), and upload progress bars.

⚡ Quick Start

1. Initialize Configuration

Generate a starter deploy.yml file in your project directory:

uhdeploy --init

Or view a commented example in your terminal:

uhdeploy --example

2. Configure Environment Variables (.env)

Create a .env file in your project root with your server credentials:

VPS_IP=123.45.67.89
VPS_USER=root
SSH_KEY_PATH=~/.ssh/id_rsa
SSH_PORT=22
# Optional:
SSH_PASSPHRASE=
VPS_PASSWORD=

3. Run Deployer

Launch the deployer:

# Interactive service selection menu
uhdeploy

# Or deploy a specific service directly
uhdeploy frontend

# Or deploy all services in order
uhdeploy all

(You can also run it via python -m uhdeploy or python deploy.py)


🛠️ Configuration Guide (deploy.yml)

The configuration file defines global server credentials and individual service deployment pipelines.

# =============================================================================
# 🌐 GLOBAL SERVER SETTINGS (Inherited by all services)
# =============================================================================
server:
  type: ssh                    # "ssh" (SFTP + Shell) or "ftp" (File transfer only)
  host: ${VPS_IP}              # VPS Hostname or IP (from .env)
  user: ${VPS_USER:-root}      # SSH/FTP Username (defaults to root)
  port: 22                     # Port: 22 for SSH, 21 for FTP
  key_path: ${SSH_KEY_PATH}    # Path to private key file
  passphrase: ${SSH_PASSPHRASE}# (Optional) Private key passphrase
  password: ${VPS_PASSWORD}    # (Optional) SSH or FTP password
  remote_dir: /opt/my-app      # Remote base directory on VPS

# Optional custom env file to load (default: .env or .env.deploy)
env_file: .env

# =============================================================================
# 📦 SERVICES DEFINITION
# =============================================================================
services:

  # ---------------------------------------------------------------------------
  # 1. Frontend Service (WITHOUT DOCKER)
  # ---------------------------------------------------------------------------
  frontend:
    description: "Build Next.js / React frontend and sync static files"
    docker: false              # Disable docker for this service
    work_dir: ./frontend       # Working directory relative to project root

    # Local build steps (Dockerfile-style string commands):
    build:
      - RUN npm install
      - RUN npm run build
      - COPY package.json dist/package.json

    # Upload files or directories to the VPS:
    upload:
      - dist/ -> ${remote_dir}/frontend/dist
      - public/ -> ${remote_dir}/frontend/public

    # Commands executed on VPS after uploading (SSH only):
    run_in_vps:
      - RUN systemctl reload nginx
      - RUN echo "Frontend updated and Nginx reloaded!"

  # ---------------------------------------------------------------------------
  # 2. Backend Service (WITH DOCKER)
  # ---------------------------------------------------------------------------
  backend:
    description: "FastAPI / Node API running in Docker Compose"
    work_dir: ./backend

    docker:
      enabled: true
      compose_file: docker-compose.yml # Compose file (defaults to docker-compose.yml)
      # (Optional: .env.production referenced in compose is auto-synced!)
      service_name: backend            # Name of service inside docker-compose.yml
      build_mode: local                # "local" (build tarball & upload) or "remote"
      image: my-backend:latest
      context: ./backend
      dockerfile: ./backend/Dockerfile # (Optional)

    # Remote steps executed on VPS BEFORE starting Docker:
    before_deploy:
      - RUN mkdir -p ${remote_dir}/backend/data

    # Remote steps executed on VPS AFTER starting Docker:
    # (Note: 'docker compose up -d <service>' is already executed automatically!)
    run_in_vps:
      - RUN docker compose ps
      - RUN docker compose logs --tail=25 backend

🧩 Step Directives Reference

Within build, before_deploy, and run_in_vps, you can write steps as clean strings or structured objects:

Directive Example Description
RUN <cmd> - RUN npm run build Runs a shell command (locally in build, or on the VPS in before_deploy / run_in_vps).
CMD <cmd> - CMD python manage.py migrate Alias for RUN.
COPY <src> <dst> - COPY ./dist -> ${remote_dir}/dist Copies local files/folders locally or uploads them to the remote server.
WORKDIR <dir> - WORKDIR ./subfolder Changes current working directory for subsequent steps.
ENV <k>=<v> - ENV NODE_ENV=production Sets an environment variable for subsequent steps.

🔒 SSH vs. 📡 FTP Differences

Feature SSH / SFTP FTP (ftplib)
File & Directory Sync ✅ Yes ✅ Yes
Progress Indicator ✅ Yes ✅ Yes
Remote Shell Execution (RUN) ✅ Yes ❌ Not supported by FTP
Docker Container Management ✅ Yes ❌ Not supported by FTP
Authentication Key file, Passphrase, or Password Username & Password

🖥️ Command-Line Interface (CLI)

Usage:
  uhdeploy [OPTIONS] [SERVICE_NAME]
  (or python -m uhdeploy [OPTIONS] [SERVICE_NAME])

Options:
  -h, --help               Show full colorful help screen and exit.
  -e, --example            Display a syntax-highlighted example deploy.yml.
  --init                   Generate a starter deploy.yml in the current directory.
  -f, --file PATH          Specify path to deploy configuration file.
  -p, --project DIR        Specify project directory containing deploy configuration.
  -s, --service NAME       Name of service to deploy (or 'all').
  -l, --list               List all services available in the configuration file.
  --dry-run                Validate configuration and simulate steps without connecting.

CLI Examples

# Preview build and deployment steps without making server changes:
uhdeploy backend --dry-run

# List configured services in a custom deploy file:
uhdeploy -f ./custom-deploy.yml --list

# Deploy a specific service from an external project directory:
uhdeploy -p D:/Projects/my-app frontend

🚢 Publishing to PyPI

To build and publish uhdeploy to PyPI:

  1. Install build tools:

    pip install --upgrade build twine
    
  2. Build distribution packages (tar.gz and .whl):

    python -m build
    
  3. Check distribution packages:

    twine check dist/*
    
  4. Upload to PyPI:

    twine upload dist/*
    

Once published, anyone can install your package with:

pip install uhdeploy

📄 License

MIT License. Created by Abdullah Ahmad. Feel free to customize and extend for your deployment pipelines!

Metadata

Release files for uhdeploy 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for uhdeploy 0.1.1
File Size Uploaded Provenance Actions
uhdeploy-0.1.1.tar.gz 24.2 kB Without provenance Details for uhdeploy-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for uhdeploy 0.1.1
File Interpreter ABI Platform Actions
uhdeploy-0.1.1-py3-none-any.whl Python 3 none any Details for uhdeploy-0.1.1-py3-none-any.whl

Total release size: 44.9 kB

Release files / uhdeploy-0.1.1.tar.gz

Download URL uhdeploy-0.1.1.tar.gz
Size 24.2 kB
Tags Source
SHA-256 checksum
How to use checksums
cda006d2fae5c7b3405b52a8e7d567f4a603e158f8fc25dfa0c94290bf344a3d
BLAKE2b-256 checksum
How to use checksums
a176d95ab9d6283d9d060042b27b3a0b78f9becaf2cd8e1960fd415297a7546f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Release files / uhdeploy-0.1.1-py3-none-any.whl

Download URL uhdeploy-0.1.1-py3-none-any.whl
Size 20.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3beb0514f9f6b8932dd647ccc9ba94d7d08e108a82fb9a9eb423326f27b770e7
BLAKE2b-256 checksum
How to use checksums
c35afa0c3bde78332728089368e9154090387f013e02b6259f68afd40d59d87a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Security for uhdeploy 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page