Kamal Deployment

Deploy Wraft using Kamal for production hosting

Kamal Deployment

Kamal is a deployment tool that makes it easy to deploy web applications to servers. This guide covers how to deploy Wraft using Kamal for production hosting.

Prerequisites

  • A server with SSH access
  • Docker installed on the server
  • Kamal CLI installed locally
  • Docker registry access (Docker Hub, GitHub Container Registry, etc.)

Server Setup

  1. Prepare your server

    • Ensure Docker is installed and running
    • Create a user with sudo privileges for deployment
    • Configure SSH key-based authentication
  2. Install Kamal on your local machine

# Using Homebrew (macOS)
brew install kamal
 
# Using npm
npm install -g @kamal/deploy
 
# Using curl
curl -fsSL https://kamal.dev/install.sh | sh

Configuration

Create a deploy.yml file in your kamal config file with the following configuration:

service: wraft
image: username/repo
 
servers:
  web:
    hosts:
      - &host_ip #your server-ip
 
    options:
      hostname: wraft-web.local
      publish:
        - '4000:4000'
    proxy: false
 
ssh:
  user:  # your server hostname
 
registry:
  username: # Dockerhub username
  password:
    - KAMAL_REGISTRY_PASSWORD
 
builder:
  arch: amd64
  context: .
  dockerfile: Dockerfile
  args:
    SECRET_KEY_BASE: ${SECRET_KEY_BASE}
 
env:
  clear:
    PORT: '4000'
    MIX_ENV: 'prod'
    DATABASE_URL: 'postgres://postgres:postgres@wraft-db:5432/wraft_data?ssl=false'
    MINIO_URL: 'http://wraft-minio:9000'
    MINIO_HOST: 'wraft-minio'
    MINIO_PORT: '9000'
    MINIO_BUCKET: 'wraft'
    SENTRY_DSN: 'https://public_key@app.getsentry.com/1'
    PADDLE_API_KEY: ''
    PADDLE_BASE_URL: ''
    PADDLE_WEBHOOK_SECRET_KEY: ''
    RESEND_API_KEY: 'your_resend_api_key_here'
    XELATEX_PATH: 'xelatex'
    TYPESENSE_HOST: 'wraft-typesense'
    TYPESENSE_PORT: '8108'
  secret:
    - SECRET_KEY_BASE
    - GUARDIAN_KEY
    - MINIO_ROOT_USER
    - MINIO_ROOT_PASSWORD
    - TYPESENSE_API_KEY
    - CLOAK_KEY
 
accessories:
  db:
    image: postgres:15
    host: *host_ip
    port: 5432
    env:
      secret:
        - POSTGRES_DB
        - POSTGRES_USER
        - POSTGRES_PASSWORD
    volumes:
      - wraft_db_data:/var/lib/postgresql/data
 
  minio:
    image: quay.io/minio/minio:RELEASE.2023-07-21T21-12-44Z
    host: *host_ip
    port: 9000
    cmd: minio server /data --console-address ":9001"
    env:
      clear:
        MINIO_SERVER_URL: 'http://wraft-minio:9000'
        MINIO_PROMETHEUS_AUTH_TYPE: 'public'
      secret:
        - MINIO_ROOT_USER
        - MINIO_ROOT_PASSWORD
    volumes:
      - minio_data:/data:rw
    options:
      publish:
        - '9001:9001'
 
  typesense:
    image: typesense/typesense:0.25.1
    host: *host_ip
    port: 8108
    env:
      clear:
        TYPESENSE_DATA_DIR: /data
        TYPESENSE_API_KEY: xyz
        TYPESENSE_ENABLE_CORS: 'true'
    volumes:
      - typesense_data:/data
 
  frontend:
    image: quay.io/wraft/wraft-frontend:latest
    host: *host_ip
    port: '3000'
    env:
      clear:
        NEXT_PUBLIC_API_HOST: http://backend-ip:4000 #Enter your backend ip
        NEXT_PUBLIC_WEBSOCKET_URL: ws://backend-ip:4000 #Enter your backend ip

Environment Variables

Set up the required environment variables for your deployment:

# Registry credentials
export KAMAL_REGISTRY_PASSWORD="your-registry-password"
 
# Application secrets
export SECRET_KEY_BASE="your-secret-key-base"
export GUARDIAN_KEY="your-guardian-key"
export CLOAK_KEY="your-cloak-key"
 
# MinIO credentials
export MINIO_ROOT_USER="your-minio-user"
export MINIO_ROOT_PASSWORD="your-minio-password"
 
# Typesense API key
export TYPESENSE_API_KEY="your-typesense-api-key"

Deployment Steps

  1. Initialize Kamal
kamal init
  1. Create the Kamal config directory
mkdir -p kamal/config
  1. Move the Kamal deployment config into the custom folder
mv config/deploy.yml kamal/config
  1. Add your secrets to the .kamal/secrets file in the project root

  2. Setup the deployment

kamal setup -c kamal/config/deploy.yml

This command will:

  • Install Docker on the server if not present
  • Configure the server for deployment
  • Set up the required directories and permissions
  1. Deploy the application
kamal deploy -c kamal/config/deploy.yml
  1. Add MinIO host entry
# macOS / Linux
echo "server-ip wraft-minio" | sudo tee -a /etc/hosts
 
# Windows
echo server-ip wraft-minio >> C:\Windows\System32\drivers\etc\hosts

This will:

  • Build and push the Docker image
  • Deploy the application to the server
  • Start all services and accessories
  1. Check deployment status
kamal app exec --reporter=dot

Configuration Details

Service Configuration

  • service: The name of your application service
  • image: Docker image name for your application
  • servers: List of server IPs where the application will be deployed
  • ssh: SSH connection details for the deployment server

Builder Configuration

  • arch: Target architecture (amd64, arm64)
  • context: Docker build context
  • dockerfile: Path to the Dockerfile

Environment Variables

  • clear: Environment variables that are not sensitive
  • secret: Sensitive environment variables (set via export)

Proxy Configuration

  • app_port: Port where your application runs
  • response_timeout: Maximum response time in seconds
  • path_prefix: URL path prefix
  • healthcheck: Health check configuration

Accessories

Accessories are additional services that run alongside your main application:

  • db: PostgreSQL database
  • minio: Object storage service
  • typesense: Search engine
  • backend: Backend API service

Monitoring and Maintenance

View logs

# Application logs
kamal app logs -c kamal/config/deploy.yml
 
# Accessory logs
kamal accessory logs db -c kamal/config/deploy.yml
kamal accessory logs minio -c kamal/config/deploy.yml
kamal accessory logs typesense -c kamal/config/deploy.yml
kamal accessory logs backend -c kamal/config/deploy.yml

Restart services

# Restart application
kamal app restart -c kamal/config/deploy.yml
 
# Restart accessories
kamal accessory restart db -c kamal/config/deploy.yml
kamal accessory restart minio -c kamal/config/deploy.yml

Update deployment

# Deploy new version
kamal deploy -c kamal/config/deploy.yml
 
# Rollback to previous version
kamal rollback -c kamal/config/deploy.yml

Troubleshooting

Common Issues

  1. SSH Connection Issues

    • Verify SSH key authentication
    • Check server firewall settings
    • Ensure the user has sudo privileges
  2. Docker Registry Issues

    • Verify registry credentials
    • Check image name and tags
    • Ensure registry is accessible from the server
  3. Port Conflicts

    • Check if required ports are available
    • Verify firewall rules
    • Ensure no other services are using the same ports

Health Checks

Monitor the health of your deployment:

# Check application health
kamal app health -c kamal/config/deploy.yml
 
# Check accessory health
kamal accessory health db -c kamal/config/deploy.yml
kamal accessory health minio -c kamal/config/deploy.yml

Security Considerations

  1. Environment Variables

    • Never commit sensitive environment variables to version control
    • Use Kamal's secret management for sensitive data
    • Rotate secrets regularly
  2. Network Security

    • Configure firewall rules appropriately
    • Use HTTPS in production
    • Implement proper access controls
  3. Database Security

    • Use strong passwords for database access
    • Configure SSL connections
    • Regular backups

Accessing a Running Container

#Attach to the running web container interactively
kamal app exec --roles web --interactive --reuse /bin/bash -c kamal/config/deploy.yml
 
#Attach to the running accessoty container interactively
kamal accessory exec db --interactive --reuse /bin/bash -c kamal/config/deploy.yml

Backup and Recovery

Database Backups

# Create database backup
kamal accessory exec db -- pg_dump -U postgres wraft_data > backup.sql -c kamal/config/deploy.yml
 
# Restore database
kamal accessory exec db -- psql -U postgres wraft_data < backup.sql -c kamal/config/deploy.yml

Volume Backups

# Backup volumes
kamal accessory exec db -- tar czf /tmp/db_backup.tar.gz /var/lib/postgresql/data -c kamal/config/deploy.yml

Scaling

To scale your deployment across multiple servers, add additional server IPs to the servers section:

servers:
  web:
    - 
    - 
    - 

Performance Optimization

  1. Resource Limits

    • Configure appropriate memory and CPU limits
    • Monitor resource usage
    • Scale based on demand
  2. Caching

    • Implement application-level caching
    • Use CDN for static assets
    • Configure database query caching
  3. Monitoring

    • Set up application monitoring
      • Monitor server resources
      • Configure alerting for critical issues

References and Resources

Official Documentation