Simple, transparent deployment for containerized applications.
podlift deploys your Docker containers to any server with SSH access. No black boxes, no magic, no broken promises.
Transparent: See exactly what commands run on your servers. No custom infrastructure, just standard Docker + nginx.
Reliable: Validate everything before deployment. Clear errors with actionable solutions.
Non-Interactive: Every command works in CI/CD. No prompts, no waiting for input.
Zero-Downtime: Deploy new versions without dropping requests. Rollback instantly if needed.
Git-Native: Every deployment maps to a commit. Always know what's running in production.
Install podlift:
# Quick install (Linux/macOS)
curl -sSL https://raw.githubusercontent.com/ekinertac/podlift/main/install.sh | sh
# Or with Go
go install github.com/ekinertac/podlift@latest
# Or download binary from releases
# https://github.com/ekinertac/podlift/releasesInitialize your project:
cd myapp/
podlift initEdit podlift.yml to add your server and configuration:
service: myapp
domain: myapp.com
image: myapp
servers:
- host: 192.168.1.10
user: root
registry:
server: ghcr.io
username: ${REGISTRY_USER}
password: ${REGISTRY_PASSWORD}
dependencies:
postgres:
image: postgres:16
port: 5432
volume: postgres_data:/var/lib/postgresql/data
env:
POSTGRES_PASSWORD: ${DB_PASSWORD}
services:
web:
port: 8000
replicas: 2
healthcheck:
path: /health
env:
SECRET_KEY: ${SECRET_KEY}
DATABASE_URL: postgres://postgres:${DB_PASSWORD}@primary:5432/myapp
proxy:
enabled: true
ssl: letsencrypt
ssl_email: admin@myapp.com
hooks:
after_deploy:
- docker exec myapp-web-1 python manage.py migrateCreate a .env file in the same directory as podlift.yml:
cp .env.example .env
# Edit .env with your secretsDeploy:
podlift deployThat's it. Your app is live.
$ podlift deploy
[1/7] Validating configuration...
✓ SSH connection to 192.168.1.10
✓ Docker installed (v24.0.5)
✓ Git state clean (commit: a1b2c3d)
[2/7] Building image myapp:a1b2c3d...
✓ Built in 45s
[3/7] Pushing to server...
✓ Uploaded 234MB in 12s
[4/7] Loading image on server...
✓ Loaded in 8s
[5/7] Starting new containers...
✓ myapp-web-a1b2c3d-1 started
✓ Health check passed (5s)
[6/7] Updating nginx configuration...
✓ Traffic routing to new version
[7/7] Stopping old containers...
✓ myapp-web-x9y8z7w-1 stopped
✓ Deployment successful!
Deployed: a1b2c3d "Fix critical bug"
URL: http://192.168.1.10
Time: 1m 34s# Initialize configuration
podlift init
# Validate setup before deploying
podlift validate
# Deploy your application
podlift deploy
# Check running services
podlift ps
# View logs
podlift logs web
podlift logs web --follow
# Rollback to previous version
podlift rollback
podlift rollback --to v1.2.3
# Set up SSL with Let's Encrypt
podlift ssl setup --email admin@myapp.comNew containers start alongside old ones. Traffic switches only after health checks pass. No dropped requests.
Every deployment uses your current git commit. Dirty working trees are rejected. Production state always matches git history.
Deploy to multiple servers with shared dependencies. Workers, web servers, and databases all configured in one file.
Run PostgreSQL, Redis, or any Docker container alongside your app. Dependencies persist across deployments.
- Build locally + SCP to server (no registry needed)
- Build locally + push to registry
- Support for GitHub Container Registry, Docker Hub, or private registries
Uses nginx for reverse proxy, Docker for containers, standard SSH for deployment. Everything is debuggable.
service: myapp
domain: myapp.com
servers:
web:
- host: 192.168.1.10
user: root
labels: [primary]
- host: 192.168.1.11
user: root
dependencies:
postgres:
image: postgres:16
volume: postgres_data:/var/lib/postgresql/data
env:
POSTGRES_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:7
services:
web:
port: 8000
replicas: 2
healthcheck:
path: /health
expect: [200, 301]
env:
SECRET_KEY: ${SECRET_KEY}
DATABASE_URL: postgres://postgres:${DB_PASSWORD}@primary:5432/myapp
worker:
command: celery -A myapp worker
replicas: 1
proxy:
enabled: true
ssl: letsencrypt
ssl_email: admin@myapp.comFull documentation site: https://ekinertac.github.io/podlift/
Quick links:
- Installation - Detailed setup guide
- Configuration Examples - Real-world use cases
- Commands - Complete CLI reference
- Configuration - All configuration options
- Deployment Guide - Strategies, rollbacks, multi-server
- Troubleshooting - Common errors and solutions
- How It Works - Architecture and internals
- Migration - Moving from Kamal, Ansible, or manual deploys
Transparency Over Magic: You should understand what's happening. Run podlift deploy --dry-run to see every command before execution.
Standards Over Reinvention: Uses nginx, Docker Compose patterns, and standard tools. No custom infrastructure.
Fail Fast With Solutions: Validation catches errors before deployment. Error messages include how to fix them.
Non-Interactive By Default: Every command works in CI/CD without prompts.
Escape Hatches Everywhere: Skip steps with flags when needed. Manual intervention is always possible.
- Docker on your deployment servers
- SSH access with key-based authentication
- Git (for version tracking)
- Linux servers (Ubuntu 20.04+, Debian 11+, or similar)
podlift is under active development. See ROADMAP.md for planned features.
Current version: v0.1.0-alpha (MVP phase)
MIT
Inspired by Kamal's vision of simple deployment, but built for reliability and transparency.