https://github.com/elitan/luma
Ship Docker Anywhere
https://github.com/elitan/luma
bun cloud docker go typescript
Last synced: 3 months ago
JSON representation
Ship Docker Anywhere
- Host: GitHub
- URL: https://github.com/elitan/luma
- Owner: elitan
- Created: 2025-05-14T10:57:43.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-06-06T08:37:04.000Z (4 months ago)
- Last Synced: 2025-06-24T11:41:10.247Z (3 months ago)
- Topics: bun, cloud, docker, go, typescript
- Language: TypeScript
- Homepage: http://myluma.cloud
- Size: 88.4 MB
- Stars: 260
- Watchers: 5
- Forks: 6
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Luma: Ship Docker Anywhere ⚡
Zero-downtime deployments and automatic HTTPS on your own servers.
```
❯ luma deploy --force
Using Git SHA for release ID: 80d0f8c
Starting deployment with release 80d0f8c[✓] Configuration loaded (1ms)
[✓] Git status verified (4ms)
[✓] Infrastructure ready (879ms)
[✓] web → web:80d0f8c (1.8s)
[✓] Building Images (1.8s)
[✓] App State Reconciliation (884ms)
└─ web → 157.180.25.101
├─ [✓] Loading web image (1.7s)
├─ [✓] Zero-downtime deployment of web (3.5s)
└─ [✓] Configuring proxy for web (805ms)
[✓] Deploying Apps (6.2s)
[✓] Deployment completed successfully in 9.8sYour app is live at:
└─ https://test.eliasson.me
```Luma automatically handles:
- ✅ Zero-downtime blue-green deployments
- ✅ Automatic SSL certificates via Let's Encrypt
- ✅ Health checks and automatic rollbacks
- ✅ Docker image building and secure transfer
- ✅ Multi-server deployments---
## 🚀 Quick Start
### 1. Install Luma
```bash
npm install -g @elitan/luma
```### 2. Initialize your project
```bash
cd your-project
luma init
```This creates:
- `luma.yml` - Your deployment configuration
- `.luma/secrets` - Secure credentials (add to `.gitignore`)### 3. Configure your app
Edit `luma.yml`:
```yaml
name: my-appapps:
web:
image: my-app/web
servers:
- your-server.com
build:
context: .
dockerfile: Dockerfile
proxy:
hosts:
- myapp.com
app_port: 3000
```### 4. Set up your server
```bash
luma setup
```Luma will:
- Install Docker if needed
- Set up the reverse proxy
- Start services### 5. Deploy!
```bash
luma deploy
```Watch as Luma builds, deploys, and switches traffic with zero downtime.
---
## 📋 Prerequisites
- **Local machine**: Bun or Node.js 18+
- **Target servers**:
- Ubuntu/Debian Linux
- SSH access with sudo privileges
- Ports 80 and 443 open---
## 🆚 Why Luma vs Alternatives?
### vs Kamal (37signals)
- **TypeScript/Bun** instead of Ruby
- **Registry-less deployments** - no need for external Docker registries### vs Vercel/Netlify
- **Your own servers** - full control, no vendor lock-in
- **Any Docker app** - not limited to specific frameworks
- **Cost-effective** - pay only for your servers
- **No cold starts** - your containers are always running### vs Docker Compose
- **Zero-downtime deployments** - compose restarts cause downtime
- **Multi-server support** - deploy across multiple machines
- **Automatic SSL** and reverse proxy included
- **Git-based releases** and rollback capabilities---
## 🎯 Core Concepts
### Apps vs Services
**Apps** are your main applications (web servers, APIs) that you build and deploy with zero-downtime:
```yaml
apps:
web:
image: my-app/web
build:
context: .
dockerfile: Dockerfile
proxy:
hosts:
- example.com
app_port: 3000api:
image: my-app/api
build:
context: ./api
proxy:
hosts:
- api.example.com
app_port: 8080
```**Services** are supporting infrastructure (databases, caches) that use pre-built images:
```yaml
services:
postgres:
image: postgres:15
environment:
secret: [POSTGRES_PASSWORD]
volumes:
- postgres_data:/var/lib/postgresql/dataredis:
image: redis:7
```### Zero-Downtime Deployments
Luma automatically uses blue-green deployment for apps:
1. **Build and transfer** your Docker image securely to servers
2. **Deploy new version** alongside the current one
3. **Health check** the new version via configured health endpoint
4. **Switch traffic** atomically (sub-millisecond)
5. **Clean up** old versionNo Docker registry required - images are transferred directly!
### Registry-Free Operation
Built apps are transferred using secure Docker save/load:
- **Build locally** - your Docker images are built on your machine
- **Transfer securely** - images are saved as tar archives and uploaded via SSH
- **Load remotely** - Docker loads the image directly on your servers
- **No registry needed** - eliminates external dependencies and credentialsServices can still use registries for pre-built images like `postgres:15`.
### Automatic SSL
Luma includes a smart reverse proxy that automatically:
- Obtains SSL certificates via Let's Encrypt
- Routes traffic to your apps
- Handles health checks
- Manages zero-downtime deployments with blue-green switching### Health Checks
Luma performs automatic health checks during deployments to ensure zero-downtime deployments. Your application must implement a health check endpoint that returns HTTP 200 when healthy.
The default health check endpoint is `/up` but you can configure it to any path you want.
```yaml
apps:
api:
health_check:
path: /health # Health check endpoint (default: /up)
```**Health Check Behavior (Automatic):**
- **Method**: HTTP GET request
- **Success criteria**: HTTP 200 response
- **Timeout**: 5 seconds
- **Retries**: 3 attempts
- **Port**: Uses the configured `app_port` (defaults to 80)The only configurable option is:
- **path**: Health check endpoint path (default: `/up`)
All other health check behavior is handled automatically by Luma to ensure reliable deployments.
---
## 📖 Configuration Reference
### Basic Configuration
```yaml
name: my-project # Required: Project name# Optional: Global settings
ssh:
username: deploy # SSH user (default: root)
port: 22 # SSH port# Optional: Docker registry (only needed for services using private registries)
docker:
registry: ghcr.io # Docker registry
username: myuser # Registry usernameapps:
web:
image: my-app/web # Docker image name
servers:
- server1.com
- server2.com # Target servers# Build configuration (apps are built locally and transferred)
build:
context: .
dockerfile: Dockerfile
platform: linux/amd64# Proxy configuration for web apps
proxy:
hosts:
- example.com
- www.example.com
app_port: 3000# Environment variables
environment:
plain:
- NODE_ENV=production
- PORT=3000
secret:
- DATABASE_URL # From .luma/secrets
- API_KEY# Health check (optional)
health_check:
path: /health # Health check endpoint (default: /up)services:
database:
image: postgres:15
servers:
- db.example.com
environment:
secret:
- POSTGRES_PASSWORD
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
```### Secrets Management
Store sensitive values in `.luma/secrets`:
```bash
# .luma/secrets
DATABASE_URL=postgres://user:pass@localhost:5432/myapp
API_KEY=supersecretkey
# Only needed if using private registries for services
DOCKER_REGISTRY_PASSWORD=myregistrypassword
```**Important**: Add `.luma/secrets` to your `.gitignore`!
---
## 🛠️ Commands
### `luma init`
Initialize a new project with configuration files.
### `luma setup [service...]`
Prepare servers for deployment. Installs Docker, creates networks, sets up the proxy.
```bash
luma setup # Set up all servers
luma setup web api # Set up only servers for web and api
```### `luma deploy [app...]`
Deploy apps or services with zero downtime.
```bash
luma deploy # Deploy all apps
luma deploy web # Deploy specific app
luma deploy --services # Deploy services instead
luma deploy --force # Skip git status checks
luma deploy --verbose # Detailed logging
```### `luma status [app...]`
Check the status of your deployments.
```bash
luma status # Status of all apps
luma status web # Status of specific app# Example output:
📱 App: web
Status: ✅ RUNNING (green active)
Replicas: 2/2 running
Servers: server1.com, server2.com
```---
## 🏗️ Examples
### Simple Web App
```yaml
name: blog
apps:
web:
image: my-blog
servers:
- server.com
build:
context: .
proxy:
hosts:
- blog.com
app_port: 3000
environment:
secret: [DATABASE_URL]
```### Full-Stack App with Database
```yaml
name: ecommerceapps:
web:
image: ecommerce/frontend
servers:
- web1.com
- web2.com
build:
context: ./frontend
proxy:
hosts:
- shop.com
- www.shop.com
app_port: 3000api:
image: ecommerce/backend
servers:
- api.com
build:
context: ./backend
proxy:
hosts:
- api.shop.com
app_port: 8080
environment:
secret: [DATABASE_URL, JWT_SECRET]services:
postgres:
image: postgres:15
servers:
- db.com
environment:
secret: [POSTGRES_PASSWORD]
volumes:
- postgres_data:/var/lib/postgresql/dataredis:
image: redis:7
servers:
- cache.com
```### Microservices with Load Balancing
```yaml
name: platformapps:
user-service:
image: platform/users
replicas: 3
servers:
- app1.com
- app2.com
build:
context: ./services/users
proxy:
hosts:
- users.platform.com
app_port: 8080order-service:
image: platform/orders
replicas: 2
servers:
- app1.com
- app2.com
build:
context: ./services/orders
proxy:
hosts:
- orders.platform.com
app_port: 8081
```---
## 🔒 Security Best Practices
### Server Preparation Guide (from root)
Follow these steps to securely prepare your server for Luma deployments. All commands should be run as the `root` user (or with `sudo`).
1. **Create a dedicated user for Luma:**
```bash
sudo adduser luma
# Follow the prompts to set a password (it will be disabled later) and user details.
sudo usermod -aG sudo luma # Add luma to the sudo group
```2. **Install Docker Engine:**
Luma requires Docker to be installed on your target servers.
```bash
# Update package lists
sudo apt-get update# Install prerequisites
sudo apt-get install -y ca-certificates curl# Create keyrings directory
sudo install -m 0755 -d /etc/apt/keyrings# Add Docker's official GPG key
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc# Add Docker's stable repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null# Update package lists again
sudo apt-get update# Install Docker CE with all plugins
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin# Add the luma user to the docker group
sudo usermod -aG docker luma# Verify installation
sudo docker run hello-world
```_Note: You might need to log out and log back in as the `luma` user for the group changes to take effect, or use `newgrp docker` in the `luma` user's session._
3. **Set up SSH Key-Based Authentication for `luma`:**
**Prerequisites:** This step assumes you already have SSH keys generated on your local machine. If you don't have SSH keys yet, generate them first:
```bash
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# Follow the prompts. It's recommended to use a passphrase for your key.
```**Copy your public key to the server:**
Replace `your-server.com` with your server's IP address or hostname.```bash
ssh-copy-id luma@your-server.com
```This command will copy your local machine's public SSH key to the `luma` user's `~/.ssh/authorized_keys` file on the server.
4. **Secure SSH Configuration:**
Disable password authentication and make other security improvements to your SSH server. Edit the SSH daemon configuration file (`/etc/ssh/sshd_config`) on the server:
```bash
sudo nano /etc/ssh/sshd_config
```Make the following changes:
```
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
UsePAM no # If you are sure you don't need PAM for SSH
```After saving the changes, restart the SSH service:
```bash
sudo systemctl restart ssh
```**Important:** Ensure your SSH key authentication is working correctly before disabling password authentication, or you could lock yourself out of the server. Test by logging in from a new terminal window: `ssh luma@your-server.com`.
5. **Install Fail2Ban:**
Fail2Ban helps protect your server from brute-force attacks.
```bash
sudo apt-get update
sudo apt-get install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
```Fail2Ban works out-of-the-box with default settings for SSH. You can customize its configuration in `/etc/fail2ban/jail.local`.
6. **Configure Luma:**
In your `luma.yml` file, ensure you specify the `luma` user for SSH connections:
```yaml
ssh:
username: luma
# port: 22 # If you changed the SSH port
```After completing these steps, your server will be more secure and ready for Luma deployments.
### Secrets Management
- Never commit `.luma/secrets` to version control
- Use environment-specific secrets## 📚 Advanced Usage
### Multi-Environment Deployments
```yaml
# luma.staging.yml
name: myapp-staging
apps:
web:
image: myapp/web
build:
context: .
servers:
- staging.myapp.com# luma.production.yml
name: myapp-prod
apps:
web:
image: myapp/web
build:
context: .
servers:
- prod1.myapp.com
- prod2.myapp.com
```Deploy with:
```bash
luma deploy -c luma.staging.yml
luma deploy -c luma.production.yml
```### Using Docker Registries (Optional)
For services that need private registries or when you prefer registry-based workflows:
```yaml
# Global registry configuration
docker:
registry: my-registry.com
username: myuserservices:
private-service:
image: my-registry.com/private-service:latest
# Uses global registry configapps:
web:
# Per-app registry override
registry:
url: ghcr.io
username: different-user
password_secret: GITHUB_TOKEN
# Still uses build + transfer, registry only for pre-built images
```---
### Development Setup
```bash
git clone https://github.com/elitan/luma
cd luma
bun install
bun run dev
```### Running Tests
```bash
bun test
```---
## 📄 License
MIT License
---
**Made with ❤️ for developers who want simple, reliable deployments on their own infrastructure.**