Cloud
On this page 52
Stacks provides first-class cloud deployment support with automated infrastructure provisioning. Deploy your applications to AWS with a single command.
Deploy targets
cloud.provider in config/cloud.ts decides where buddy deploy ships. This page covers the AWS
target, which is the default.
cloud.provider | Target | Guide |
|---|---|---|
'aws' (default) | CloudFormation stack on AWS | This page |
'hetzner' | A Hetzner Cloud server | Deploy |
'ssh' | A Linux host you already own | Raspberry Pi |
Overview
Stacks Cloud offers:
- One-command deployment - Deploy with
buddy deploy - Automated infrastructure - AWS resources provisioned automatically
- Zero-downtime updates - Rolling deployments with health checks
- Automatic scaling - Scale based on demand
- Built-in CDN - CloudFront for static assets
- SSL/TLS - Automatic certificate management
Quick Start
Prerequisites
- AWS account with appropriate permissions
- AWS CLI configured (
aws configure) - Stacks project initialized
First Deployment
# Deploy to production (the first run provisions the cloud resources)
buddy deploy
Cloud Configuration
// config/cloud.ts
import { defineCloud } from '@stacksjs/config'
export default defineCloud({
provider: 'aws',
region: process.env.AWS_REGION || 'us-east-1',
domain: 'myapp.com',
compute: {
type: 'serverless', // 'serverless' | 'container' | 'vm'
memory: 1024, // MB for Lambda
timeout: 30, // seconds
},
database: {
type: 'aurora-serverless',
minCapacity: 0.5,
maxCapacity: 4,
autoPause: true,
pauseAfter: 300, // 5 minutes
},
storage: {
bucket: 'myapp-storage',
cdn: true,
},
cache: {
type: 'elasticache',
nodeType: 'cache.t3.micro',
},
cdn: {
enabled: true,
priceClass: 'PriceClass_100',
customDomain: true,
},
})
Deployment Environments
Development
# Deploy to development
buddy deploy --env=development
Staging
# Deploy to staging
buddy deploy --env=staging
Production
# Deploy to production
buddy deploy --env=production
# Or simply
buddy deploy
Infrastructure Components
Compute Options
Serverless (Lambda)
Best for: Variable workloads, cost optimization
compute: {
type: 'serverless',
memory: 1024,
timeout: 30,
provisioned: 5, // Optional: provisioned concurrency
}
Containers (ECS/Fargate)
Best for: Consistent workloads, long-running processes
compute: {
type: 'container',
cpu: 256,
memory: 512,
desiredCount: 2,
minCount: 1,
maxCount: 10,
}
Virtual Machines (EC2)
Best for: Maximum control, specific requirements
compute: {
type: 'vm',
instanceType: 't3.small',
minInstances: 2,
maxInstances: 10,
}
Database Options
Aurora Serverless
database: {
type: 'aurora-serverless',
engine: 'mysql', // or 'postgres'
minCapacity: 0.5,
maxCapacity: 8,
autoPause: true,
}
RDS
database: {
type: 'rds',
engine: 'mysql',
instanceClass: 'db.t3.small',
multiAZ: true,
storage: 100, // GB
}
DynamoDB
database: {
type: 'dynamodb',
billingMode: 'PAY_PER_REQUEST',
}
Cache Options
ElastiCache (Redis)
cache: {
type: 'elasticache',
engine: 'redis',
nodeType: 'cache.t3.micro',
numNodes: 1,
}
DynamoDB Accelerator (DAX)
cache: {
type: 'dax',
nodeType: 'dax.t3.small',
}
Storage
storage: {
bucket: 'myapp-storage',
versioning: true,
encryption: true,
cdn: true,
cors: [
{
allowedOrigins: ['https://myapp.com'],
allowedMethods: ['GET', 'PUT'],
},
],
}
Persistent compute storage
The Hetzner compute owner can declare block volumes and deployment placement in
config/cloud.ts. Attached projects inherit the host policy when they deploy.
Existing volumes are adopted by exact name and are never reformatted or shrunk.
compute: {
size: 'xlarge', // CX53
resize: { whenUnavailable: 'keep-current', upgradeDisk: true },
volumes: {
deployments: {
size: 250,
mountPath: '/var/lib/deployments',
deleteProtection: true,
},
},
deploymentStorage: {
volume: 'deployments',
migrateExisting: true,
includeBackups: true,
},
monitoring: {
filesystems: ['/', { path: '/var/lib/deployments', requiredMount: true }],
},
}
Preview with buddy cloud:apply --dry-run; apply with
buddy cloud:apply --yes. The ts-cloud CLI exposes the same operation as
cloud apply. An unavailable server type remains pending while storage is
applied. A server resize requires a restart; volume placement copies online,
verifies under deployment locks, and keeps running processes on their current
release. Shared databases stay at their existing paths.
Mounts persist by filesystem UUID. Bind mounts preserve /var/www release and
backup paths, and systemd dependencies prevent applications from starting on
unmounted storage. Every minute, the storage check verifies volume identity and
deployment mounts; the metrics collector reports each configured filesystem.
Inactive root copies are reclaimed hourly, preserving active and current code.
The dashboard exposes filesystem usage and mount health. Declare additional
writer locks in deploymentStorage.locks and systemd consumers in
deploymentStorage.dependentUnits; the owner configuration keeps these
host-specific integrations alongside the volume declaration.
Keep webhook secrets on the host with a typed reference:
notifications: {
discord: {
webhookUrl: { envFile: '/etc/myapp/notifications.env', variable: 'DISCORD_WEBHOOK_URL' },
},
}
The notifier reads assignments as data and retries failed deliveries through
monitoring's persisted state. Storage policy lives at
/etc/ts-cloud/compute-storage.json; reports and migration health comparisons
live under /var/lib/ts-cloud. The runtime is TypeScript executed by Bun.
CDN (CloudFront)
cdn: {
enabled: true,
priceClass: 'PriceClass_100', // US, Canada, Europe
customDomain: true,
certificate: 'auto', // Automatic ACM certificate
compression: true,
http2: true,
}
Domain & SSL
Custom Domain
domain: {
name: 'myapp.com',
hostedZone: 'myapp.com',
certificate: 'auto',
subdomains: {
api: 'api.myapp.com',
cdn: 'cdn.myapp.com',
},
}
Automatic SSL
Stacks automatically provisions and renews SSL certificates via AWS Certificate Manager.
Environment Variables
Buddy does not ship cloud environment commands yet. Manage your app's environment variables locally (or via your platform's secret store), then redeploy:
# Set a variable in your .env
buddy env:set APP_KEY secret123
# Read a variable back
buddy env:get APP_KEY
Scaling
Auto Scaling
scaling: {
enabled: true,
minInstances: 2,
maxInstances: 20,
targetCPU: 70, // Scale when CPU > 70%
targetMemory: 80,
scaleInCooldown: 300,
scaleOutCooldown: 60,
}
Manual Scaling
Manual scaling from the CLI is not implemented yet; scaling is configured through config/cloud.ts as shown above.
Monitoring
CloudWatch Integration
monitoring: {
enabled: true,
metrics: ['cpu', 'memory', 'requests', 'errors'],
alarms: {
errorRate: {
threshold: 5,
period: 60,
notification: 'alerts@myapp.com',
},
latency: {
threshold: 1000, // ms
period: 60,
notification: 'alerts@myapp.com',
},
},
}
Logs
A buddy cloud:logs command is not implemented yet; view logs in CloudWatch or via your server's journal (e.g. journalctl -u <service> on the deploy target).
Deployments
Zero-Downtime Deployment
# Default deployment (zero-downtime)
buddy deploy
# Skip the confirmation prompt (e.g. in CI)
buddy deploy --yes
Rollback
A buddy cloud:rollback command is not implemented yet; redeploy the previous release to roll back.
Deployment History
# Inspect servers, sites & deploys in the local cloud cockpit
buddy cloud:dashboard
CI/CD Integration
GitHub Actions
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v1
- name: Install dependencies
run: bun install
- name: Run tests
run: bun test
- name: Deploy
run: bun run deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Cost Optimization
Serverless
- Use Aurora Serverless with auto-pause
- Configure appropriate Lambda memory
- Use CloudFront caching effectively
Containers
- Use Spot instances for non-critical workloads
- Right-size your containers
- Implement efficient auto-scaling
General
# Remove cost-heavy resources that can be re-applied later
buddy cloud:optimize-cost
Security
IAM Roles
Stacks creates least-privilege IAM roles automatically.
VPC Configuration
vpc: {
enabled: true,
cidr: '10.0.0.0/16',
privateSubnets: 2,
publicSubnets: 2,
natGateway: true,
}
WAF (Web Application Firewall)
waf: {
enabled: true,
rules: ['AWSManagedRulesCommonRuleSet', 'AWSManagedRulesKnownBadInputsRuleSet'],
rateLimit: 1000, // requests per 5 minutes
}
Commands Reference
# Deploy application
buddy deploy
# Show the diff of the current, undeployed cloud changes
buddy cloud:diff
# Check for a jump box (declared by infrastructure.jumpBox, created by buddy deploy)
buddy cloud:add --jump-box
# Inspect servers, sites & deploys in the local cloud cockpit
buddy cloud:dashboard
# Invalidate the CloudFront cache
buddy cloud:invalidate-cache
# Remove cost-heavy resources that can be re-applied later
buddy cloud:optimize-cost
# Destroy infrastructure (alias: buddy undeploy)
buddy cloud:remove
Best Practices
- Start small - Begin with serverless, scale as needed
- Use staging - Test deployments in staging first
- Monitor costs - Review billing regularly
- Enable alerts - Set up CloudWatch alarms
- Secure secrets - Use environment variables for sensitive data
Related
- Deploy - the three deploy targets and the release flow
- Raspberry Pi - deploying to a host you already own, over SSH
- Configuration - Application configuration
- CI/CD - Continuous integration setup
- Testing - Test before deploying