Deployment

Deploy Rakiba projects to local Docker containers for testing or remote VPS servers for production. Both use the same bb deploy command with zero-downtime blue/green deployment by default.

Overview

Rakiba supports two deployment targets:

Target TypeUse CaseMechanism
Docker ContainerLocal testing, development sandboxesdocker exec / docker cp
VPS ServerRemote deployment, staging, productionSSH / rsync

Both use the same bb deploy command with the --target flag.

Prerequisites

Local Machine

Where you run bb deploy:

  • Babashka (bb) installed
  • Docker (for container targets)
  • SSH client and rsync (for VPS targets)
  • Project built with bb build capability

Target Server (VPS)

Before deploying to a VPS, ensure these are installed:

# Update packages
apt-get update

# Install Java 21, nginx, curl
DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-21-jre-headless nginx curl

# Create application user
useradd -m -s /bin/bash rakiba

# Create Java symlink (optional but recommended)
mkdir -p /opt/java
ln -sf /usr/lib/jvm/java-21-openjdk-amd64/* /opt/java/

# Create app directory
mkdir -p /home/rakiba
chown rakiba:rakiba /home/rakiba

Local Sandbox Deployment

Test deployments locally with a production-like environment using Docker containers.

Quick Start

# One-time DNS setup (requires sudo)
bb local:dns-setup

# Create a sandbox
bb local:create ubuntu@24.04 --name dev

# Deploy your project
bb deploy my-app --target dev

# Access it
open http://my-app.rakiba.test:9080

What You Get

A local sandbox provisions a full production stack:

ServiceDescription
PostgreSQL 16With TimescaleDB extension
ValkeyRedis-compatible cache
nginxReverse proxy with hostname routing
DatomicTransactor with PostgreSQL storage
GarageS3-compatible object storage

Sandbox Commands

CommandDescription
bb local:create ubuntu@24.04 --name <name>Create new sandbox
bb local:listList all sandboxes
bb local:status <name>Service health check
bb local:start/stop <name>Start/stop sandbox
bb local:destroy <name>Remove sandbox
bb local:shell <name>Interactive shell
bb local:logs <name> [service]View logs
bb local:upgrade <name>Sync services to config
bb deploy <project> --target <name>Deploy project

Port Mapping

ServiceDefault Port
HTTP (nginx)9080
PostgreSQL5432
Valkey6379
Garage S3 API3900
Garage Admin3903

Multiple sandboxes use incremented ports (9081, 5433, etc.).

VPS Deployment

VPS deployment uses the Rakiba Agent - a lightweight service running on your server that handles deployments, log streaming, and service management. See VPS Agent for the full architecture.

1. Add VPS to Inventory

Register your VPS with Rakiba:

# Basic usage (uses default SSH key and port 22)
bb vps:add root@192.168.1.100 --name prod

# With custom port and key
bb vps:add deploy@192.168.1.100 --name prod --port 2222 --key ~/.ssh/deploy_key

This creates an entry in .remote-inventory.edn.

2. Verify Connectivity

# Quick connectivity check
bb vps:status prod

# Full deployment readiness check (SSH + rsync)
bb vps:verify prod

3. Setup Agent (First Time)

Install the Rakiba agent on your VPS:

bb vps:setup prod

This installs a lightweight agent service that handles deployments and enables remote management from your local Admin Dashboard.

4. Deploy

# Deploy a project
bb deploy myproject --target prod

# Deploy with options
bb deploy myproject --target prod --skip-build --timeout 120

5. Verify Deployment

After deployment, the app is accessible at http://<vps-ip>:8001/ (port 8001 is the default).

curl http://192.168.1.100:8001/api/health

Blue/Green Deployment

By default, Rakiba uses blue/green deployment for zero-downtime updates. This strategy ensures your users never experience downtime during deployments.

How It Works

  1. A new version starts on a temporary “blue” port (primary port + 100)
  2. Health check verifies the new version is working
  3. Nginx switches traffic to the new version
  4. Old connections drain gracefully
  5. Old service is stopped

Benefits

  • Zero downtime during deployment
  • Instant rollback if health check fails
  • Traffic switch happens in milliseconds

Memory Consideration: Blue/green temporarily runs two JVM processes. Servers with less than 1GB RAM should use the :restart strategy instead.

Configuration

Add a :deployment key to your project’s rakiba.edn:

{:state-management :mount
 :server :jetty
 ;; ... other config ...
 
 :deployment
 {:strategy :blue-green       ; :blue-green (default) or :restart
  :health-check-timeout-ms 120000  ; 2 minutes (default)
  :drain-timeout-ms 30000          ; 30 seconds (default)
  :blue-port-offset 100}}          ; Port offset for blue service (default: 100)

Options

OptionDefaultDescription
:strategy:blue-greenDeployment strategy (:blue-green or :restart)
:health-check-timeout-ms120000How long to wait for health check (ms)
:drain-timeout-ms30000Time to drain connections before stopping old service (ms)
:blue-port-offset100Blue service port = primary port + offset

CLI Overrides

CLI flags override rakiba.edn configuration:

# Force legacy restart (overrides :strategy in config)
bb deploy myproject --target prod --no-blue-green

# Custom timeouts (override config values)
bb deploy myproject --target prod --timeout 180 --drain-timeout 60

Precedence: CLI flags > rakiba.edn :deployment > defaults

Deployment Flow

When you run bb deploy, the following steps occur:

  1. Resolve Target - Check if target is VPS (.remote-inventory.edn) or container (.local-envs/)
  2. Test Connection - Verify SSH connectivity (VPS) or Docker container is running
  3. Build - Run bb build to create uberjar (unless --skip-build)
  4. Upload - Transfer JAR and .env file via rsync (VPS) or docker cp (container)
  5. Install Service - Create systemd unit file
  6. Deploy - Blue/green deployment (default) or restart based on strategy
  7. Health Check - Poll /api/health until it responds
  8. Traffic Switch - Update nginx to route to new version (blue/green only)
  9. Drain & Cleanup - Gracefully stop old service (blue/green only)

Command Reference

VPS Management

CommandDescription
bb vps:add <user@host> --name <name>Add VPS to inventory
bb vps:add ... --port <port> --key <path>Add with custom SSH port and key
bb vps:listList registered VPS targets
bb vps:remove <name>Remove VPS from inventory
bb vps:status <name>Check SSH connectivity
bb vps:verify <name>Verify deployment prerequisites (SSH + rsync)

Deployment

CommandDescription
bb deploy <project> --target <name>Deploy project to target
bb deploy:status --target <name>Check deployment status

Deployment Options

FlagDescription
--target, -tTarget name (required)
--skip-buildSkip building uberjar
--timeoutHealth check timeout in seconds (default: from config or 60)
--no-blue-greenForce legacy restart deployment
--drain-timeoutConnection drain timeout in seconds (default: from config or 30)

Container Management

CommandDescription
bb test:deploy:container:createCreate E2E test container
bb test:deploy:container:destroyRemove container
bb test:deploy:container:statusCheck container status
bb test:deploy:e2e <project>Full E2E deployment test

Troubleshooting

SSH Connection Failed

# Check SSH connectivity manually
ssh -i /path/to/key -p <port> user@host "echo ok"

# Verify key permissions
chmod 600 ~/.ssh/id_rsa

Service Won’t Start

# Check service status on target
ssh user@host "systemctl status rakiba-<project>.service"

# View logs
ssh user@host "journalctl -u rakiba-<project>.service -n 50"

Health Check Timeout

The health check polls /api/health for 60 seconds by default. If your app takes longer to start:

bb deploy myproject --target prod --timeout 120

Permission Denied on Upload

For non-root SSH users, ensure:

  1. The SSH user owns /home/rakiba/ or has write access
  2. The SSH user has passwordless sudo for systemctl commands
# Fix ownership (run as root)
chown -R deploy:deploy /home/rakiba

# Add sudo access for systemctl
echo "deploy ALL=(ALL) NOPASSWD: /bin/systemctl" >> /etc/sudoers.d/deploy

Files Reference

FilePurpose
.remote-inventory.ednVPS targets (name, host, user, port, key)
.local-envs/<name>.ednDocker container state (ports, timestamps)
/etc/systemd/system/rakiba-<project>.serviceSystemd unit (on target)
/home/rakiba/<project>/Application directory (on target)