Skip to main content

DockLift

Deploy web applications to VPS using Docker Compose with automatic SSL via Caddy.

Features

  • Simple Configuration: Lightweight YAML configuration for all deployment settings
  • Automatic SSL: Automatic HTTPS certificates via Caddy's ACME integration
  • Multi-App Support: Deploy multiple applications to the same VPS, each with its own domain
  • Auto Port Assignment: Automatically assigns ports to applications (starts at 3000, increments)
  • Idempotent Operations: All commands can be run multiple times safely
  • Dependency Management: Built-in support for databases, caches, and other services
  • Type-Safe: Full type hints throughout the codebase
  • Beautiful CLI: Rich terminal output with progress indicators

Installation

Using UV (recommended):

uv tool install docklift

Using pip:

pip install docklift

Quick Start

1. Initialize Configuration

Run the interactive setup:

docklift init

Or provide values as arguments to skip prompts:

docklift init myapp --domain myapp.example.com --host 192.168.1.100

This creates a docklift.yml file. The wizard will prompt for:

  • Application name and domain
  • VPS host and SSH credentials
  • Application port
  • Email for SSL certificate notifications (optional)

2. Bootstrap VPS

First time setup - installs Docker, Caddy, and creates shared infrastructure:

docklift bootstrap

This step is idempotent. It will:

  • Install Docker and Docker Compose (if not present)
  • Create a shared network for all applications
  • Set up Caddy reverse proxy with automatic HTTPS

3. Deploy Application

docklift deploy

This will:

  • Upload your application code
  • Generate docker-compose.yml
  • Build the Docker image on the VPS
  • Start the application
  • Configure Caddy to route traffic
  • Test the deployment

Configuration

Create a docklift.yml file:

vps:
  host: 192.168.1.100
  user: root
  ssh_key_path: ~/.ssh/id_rsa
  port: 22
  email: admin@example.com  # Optional: for Let's Encrypt SSL notifications

application:
  name: myapp
  domain: myapp.example.com
  dockerfile: ./Dockerfile
  context: .
  # port: 3000  # Optional: auto-assigned if not specified

  environment:
    NODE_ENV: production
    DATABASE_URL: postgres://postgres:password@postgres:5432/myapp
    REDIS_URL: redis://redis:6379

  dependencies:
    postgres:
      image: postgres:16-alpine
      environment:
        POSTGRES_DB: myapp
        POSTGRES_USER: postgres
        POSTGRES_PASSWORD: changeme
      volumes:
        - postgres_data:/var/lib/postgresql/data

    redis:
      image: redis:7-alpine
      volumes:
        - redis_data:/data

Commands

Initialize

Create a new configuration file interactively:

docklift init

Or provide arguments to skip prompts:

docklift init myapp --domain app.example.com --host 192.168.1.100 --user deploy

Bootstrap

Set up VPS infrastructure (run once per VPS):

docklift bootstrap [--config docklift.yml]

Deploy

Deploy or update an application:

docklift deploy [--config docklift.yml] [--skip-bootstrap]

Status

Check application status:

docklift status [--config docklift.yml]

Remove

Remove an application:

docklift remove [--config docklift.yml] [--remove-volumes]

Environment Variables and Secrets

DockLift supports loading environment variables from .env files to keep secrets out of version control.

Using .env Files

  1. Create a .env file in your project:
# .env
DATABASE_PASSWORD=super-secret-password
API_KEY=sk-1234567890
STRIPE_SECRET=sk_test_abc123
  1. Reference it in docklift.yml:
application:
  environment:
    NODE_ENV: production
    DATABASE_URL: postgres://user:${DATABASE_PASSWORD}@postgres:5432/db
  env_file: .env  # Load additional variables from .env
  1. Add .env to .gitignore:
echo ".env" >> .gitignore

Precedence Rules

  • Variables defined in docklift.yml take precedence over .env file
  • This allows you to override secrets for specific environments
  • Use YAML for non-sensitive config, .env for secrets

Example

With this setup:

# docklift.yml
environment:
  NODE_ENV: production
  API_KEY: override-key
env_file: .env
# .env
API_KEY=secret-from-env
DATABASE_URL=postgres://localhost/db

The result will be:

  • NODE_ENV=production (from YAML)
  • API_KEY=override-key (YAML overrides .env)
  • DATABASE_URL=postgres://localhost/db (from .env)

How It Works

Architecture

DockLift creates the following structure on your VPS:

/opt/docklift/
├── caddy-compose.yml        # Caddy reverse proxy
├── Caddyfile                # Caddy configuration
└── apps/
    ├── app1/
    │   ├── docker-compose.yml
    │   └── [app files]
    └── app2/
        ├── docker-compose.yml
        └── [app files]

Network Architecture

  • All applications and Caddy share a Docker network called docklift-network
  • Caddy listens on ports 80 and 443
  • Applications expose their internal ports only to the shared network
  • Caddy routes traffic based on domain name to the appropriate application

SSL Certificates

  • Caddy automatically obtains SSL certificates via Let's Encrypt
  • Certificates are automatically renewed
  • HTTP traffic is automatically redirected to HTTPS

Port Management

  • Applications can specify a port or leave it blank for auto-assignment
  • Auto-assigned ports start at 3000 and increment for each new application
  • Ports are only exposed internally to the Docker network (no host port conflicts)
  • When redeploying an existing app, the same port is reused

Example: Django Application

vps:
  host: myserver.example.com
  user: deploy
  ssh_key_path: ~/.ssh/deploy_key
  port: 22
  email: admin@myserver.example.com

application:
  name: django-app
  domain: app.example.com
  dockerfile: ./Dockerfile
  context: .
  port: 8000

  environment:
    DJANGO_SETTINGS_MODULE: myapp.settings.production
    DATABASE_URL: postgres://django:secure_pass@postgres:5432/django_db
    REDIS_URL: redis://redis:6379/0
    SECRET_KEY: your-secret-key-here

  dependencies:
    postgres:
      image: postgres:16-alpine
      environment:
        POSTGRES_DB: django_db
        POSTGRES_USER: django
        POSTGRES_PASSWORD: secure_pass
      volumes:
        - postgres_data:/var/lib/postgresql/data

    redis:
      image: redis:7-alpine
      volumes:
        - redis_data:/data

Example: Node.js Application

vps:
  host: myserver.example.com
  user: deploy
  ssh_key_path: ~/.ssh/deploy_key
  port: 22
  email: admin@myserver.example.com

application:
  name: nodejs-app
  domain: app.example.com
  dockerfile: ./Dockerfile
  context: .
  port: 3000

  environment:
    NODE_ENV: production
    MONGODB_URL: mongodb://mongo:27017/myapp

  dependencies:
    mongo:
      image: mongo:7
      volumes:
        - mongo_data:/data/db

Requirements

  • Python 3.12+
  • SSH access to a VPS running a modern Linux distribution
  • Docker-compatible VPS (Ubuntu 20.04+, Debian 11+, etc.)
  • Domain name(s) pointed to your VPS

Development

Built with:

  • Python 3.12+ with type hints
  • UV for package management
  • Fabric for SSH operations
  • Rich for beautiful CLI output
  • Pydantic for configuration validation
  • Click for CLI framework

Setup Development Environment

# Clone the repository
git clone https://github.com/amirkarimi/docklift.git
cd docklift

# Install dependencies
uv sync

# Run in development mode
uv run docklift --help

License

MIT

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Metadata

Release files for docklift 0.1.3

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

Source distribution (sdist)

Source distribution for docklift 0.1.3
File Size Uploaded
docklift-0.1.3.tar.gz 61.0 kB Details

Built distribution (wheel)

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

Total release size: 76.9 kB

Release files / docklift-0.1.3.tar.gz

Download URL docklift-0.1.3.tar.gz
Size 61.0 kB
Tags Source
SHA-256 checksum
How to use checksums
de1eb5d092855cf77356dd6b5370ac814a152f041244327823a674cde3811b48
BLAKE2b-256 checksum
How to use checksums
1989f91e99bbe57d0470365f147362cd9a2afc8f8de1d02aa30802c5154681e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 23, 2026.

Transparency log

Release files / docklift-0.1.3-py3-none-any.whl

Download URL docklift-0.1.3-py3-none-any.whl
Size 15.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e2ea421f2cb1cca37ec3164c33623f500c9ca31aa8c558be1b44bb9be5db37b8
BLAKE2b-256 checksum
How to use checksums
bbf788f1a205edb326776445e6edebfa152ee92d16b57945dd4ff9766084e4c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

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