Skip to main content

Deploy web applications to VPS using Docker Compose with automatic SSL

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

docklift-0.1.2.tar.gz (60.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

docklift-0.1.2-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

Details for the file docklift-0.1.2.tar.gz.

File metadata

  • Download URL: docklift-0.1.2.tar.gz
  • Upload date:
  • Size: 60.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for docklift-0.1.2.tar.gz
Algorithm Hash digest
SHA256 e42213b8da635ef3b8b4ad06ffaeabfb92660b2a56ced2057a643210fef37a9e
MD5 70868b80006fa8701c5471b1aa6c2482
BLAKE2b-256 ed5a861f31343e74b32e98e962a05892434363f6f27b3c2e7d455d9e53d3cc4c

See more details on using hashes here.

Provenance

The following attestation bundles were made for docklift-0.1.2.tar.gz:

Publisher: publish.yml on amirkarimi/docklift

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file docklift-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: docklift-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 16.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for docklift-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4fb98c556c53d81a66e35fcfac927177f45c5849ce3577de1457424dbf2978aa
MD5 7fe0ae42ea024bc4838b49048c8b7aab
BLAKE2b-256 4c0d573602c8244e9c78b5a16e90534e1c97ff972ccdf1bcdad26ccbe23a45a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for docklift-0.1.2-py3-none-any.whl:

Publisher: publish.yml on amirkarimi/docklift

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page