Deployment
Deployment
HCP supports multiple deployment methods: Docker, Kamal, and traditional hosting.
Docker Deployment
Prerequisites
- Docker 24+
- Docker Compose 2.20+ (for development)
- Server with 2GB+ RAM
Production Build
# Build imagedocker build -t hcp:latest .
# Run containerdocker run -d \ -p 80:80 \ -e RAILS_MASTER_KEY=<master_key> \ -e DATABASE_URL=<db_url> \ --name hcp \ hcp:latestDocker Compose (Development)
# Start all servicesdocker-compose up -d
# View logsdocker-compose logs -f web
# Run commandsdocker-compose exec web bin/rails consoleEnvironment Variables
| Variable | Required | Description |
|---|---|---|
RAILS_MASTER_KEY | Yes | Encryption key from config/master.key |
DATABASE_URL | Yes | PostgreSQL connection string |
REDIS_URL | No | Redis for caching (defaults to built-in) |
RAILS_ENV | No | production (default) or development |
Production Dockerfile
# syntax=docker/dockerfile:1FROM ruby:3.3-slim AS builder
WORKDIR /appRUN apt-get update && apt-get install -y build-essential libpq-dev
COPY Gemfile Gemfile.lock ./RUN bundle config set --local deployment 'true' && \ bundle config set --local without 'development test' && \ bundle install
COPY . .RUN SECRET_KEY_BASE=dummy bundle exec rails assets:precompile
FROM ruby:3.3-slim AS runtime
WORKDIR /appRUN apt-get update && apt-get install -y libpq-dev && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app /appCOPY --from=builder /usr/local/bundle /usr/local/bundle
ENV RAILS_ENV=productionENV RAILS_SERVE_STATIC_FILES=true
EXPOSE 80
ENTRYPOINT ["./bin/docker-entrypoint"]CMD ["./bin/thrust", "./bin/rails", "server"]Kamal Deployment
Kamal is the recommended deployment method for production.
Installation
gem install kamalConfiguration
Create .kamal/deploy.yml:
service: hcpimage: benmacdonald/hcp
servers: web: - 192.168.1.100 - 192.168.1.101
proxy: ssl: true host: hcp.example.com
registry: server: ghcr.io username: benmacdonald password: - KAMAL_REGISTRY_PASSWORD
env: secret: - RAILS_MASTER_KEY - DATABASE_URL clear: RAILS_ENV: production RAILS_SERVE_STATIC_FILES: true
builder: multiarch: false args: RUBY_VERSION: "3.3"Deploy Commands
# Setup server (first time)kamal setup
# Deploykamal deploy
# View logskamal logs
# Run consolekamal console
# Check statuskamal details
# Rollbackkamal rollbackSSL/TLS
Kamal automatically provisions SSL certificates via Let’s Encrypt when ssl: true is configured.
Cloud Deployment
Render.com
- Create new Web Service
- Connect GitHub repository
- Settings:
- Runtime: Docker
- Dockerfile Path:
./Dockerfile - Plan: Standard ($7+/month)
- Environment variables:
RAILS_MASTER_KEYDATABASE_URL(from Render PostgreSQL)
- Deploy
Railway
# Install Railway CLInpm install -g @railway/cli
# Loginrailway login
# Link projectrailway link
# Deployrailway upDigitalOcean App Platform
- Create App
- Select Docker source
- Configure environment variables
- Deploy
Database Setup
PostgreSQL
-- Create databaseCREATE DATABASE hcp_production;
-- Create userCREATE USER hcp WITH PASSWORD 'secure_password';GRANT ALL PRIVILEGES ON DATABASE hcp_production TO hcp;Connection URL
postgresql://hcp:secure_password@localhost:5432/hcp_productionMigrations
# Dockerdocker-compose exec web bin/rails db:migrate
# Kamalkamal exec 'bin/rails db:migrate'Monitoring
Health Checks
Built-in health endpoint:
GET /up
Response: 200 OK (if healthy)Logging
Kamal/Rails logs to stdout by default. Use external log aggregation:
- Datadog
- Papertrail
- LogDNA
Metrics
Track key metrics:
- Request count/latency
- Database connections
- Background job queue depth
- Error rates
Backup & Recovery
Database Backups
# Automated daily backuppg_dump $DATABASE_URL | gzip > backup-$(date +%Y%m%d).sql.gz
# Restoregunzip < backup-20240115.sql.gz | psql $DATABASE_URLAsset Storage
- All assets are compiled into Docker image
- No persistent storage required for uploads
- Store backups externally (S3, etc.)
Security Checklist
- Master key stored securely (not in repo)
- Database credentials rotated regularly
- SSL/TLS enabled
- Firewall rules configured
- Automated security updates enabled
- Database backups encrypted
- Access logs monitored
Next: Troubleshooting