-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample.maestro.yaml
More file actions
220 lines (194 loc) · 8.74 KB
/
example.maestro.yaml
File metadata and controls
220 lines (194 loc) · 8.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# ============================================
# Maestro Configuration File
# ============================================
# This file contains all configuration for provisioning infrastructure.
# Copy this file to maestro.yaml and customize for your deployment.
#
# Secrets (API tokens, SSH keys) should NOT be placed here.
# They are fetched from Bitwarden Secrets Manager at runtime.
# Required environment variable: BWS_ACCESS_TOKEN
# ============================================
# [Required] Base domain for DNS records and nginx configuration
# Used by both Pulumi (for Cloudflare DNS) and Ansible (for nginx)
#
# Environment-specific subdomains are automatically created based on stack name:
# - dev stack: dev.example.com, api.dev.example.com, ssh0.dev.example.com
# - staging stack: stag.example.com, api.stag.example.com, ssh0.stag.example.com
# - prod stack: example.com, api.example.com, ssh0.example.com
domain: example.com
# ============================================
# Pulumi Configuration
# ============================================
# Pulumi provisions cloud infrastructure:
# - DigitalOcean virtual servers with cloudflared and SSL/TLS certificates
# - Cloudflare DNS records and tunnels for SSH access
pulumi:
# [required] Set to false to skip Pulumi provisioning.
# Useful if you've already ran pulumi provisioning before and just want to
# configure the server via Ansible (see below).
enabled: true
# [Required] Pulumi command to run: up, refresh, cancel, or output
# - up: Apply infrastructure changes
# - refresh: Reconcile state without deploying
# - cancel: Cancel a running update
# - output: Retrieve stack outputs without changes
command: up
# [Required] Cloudflare account ID
# Found at: https://dash.cloudflare.com/ -> "Copy Account ID" under the three
# dots next to account name
cloudflareAccountId: "your_account_id_here"
# [Required] SSH port for Cloudflare tunnel configuration
sshPort: 22
# [Required when pulumi.enabled is true] Stack definitions
# Each stack (dev, staging, prod) represents an isolated environment.
# Maestro provisions each defined stack sequentially.
stacks:
# Production stack example
prod:
servers:
# Single production server (handles backend and web)
- roles: [backend, web] # Required: one or more of backend, web
# groups: [devops] # Optional: override global ansible.groups for this server
# tags: [] # Optional: custom user-defined tags
# image: ubuntu-25-04-x64 # Optional, default: ubuntu-25-04-x64
# size: s-1vcpu-1gb # Optional, default: s-1vcpu-1gb
# region: nyc1 # Optional, default: nyc1
# Multi-stack setup example (uncomment to use):
# stacks:
# staging:
# servers:
# # Staging server for testing
# - roles: [backend, web]
# tags: [canary] # Custom tag for canary deployments
# region: nyc1
# prod:
# servers:
# # Production backend server
# - roles: [backend]
# groups: [devops, backend-team] # Per-server group override
# size: s-2vcpu-4gb # Larger size for production
# region: nyc1
# # Production web server
# - roles: [web]
# region: nyc1
# ============================================
# Ansible Configuration
# ============================================
# Ansible configures the provisioned servers based on their roles:
# - web role: nginx for web serving (static files or reverse proxy)
# - backend role: Docker and backend application container
#
# Security hardening (UFW firewall, system groups) is applied automatically
# to all servers. Firewall rules are role-based: web servers allow HTTPS from
# Cloudflare, backend servers allow their port from localhost only.
#
# Provisioning is role-based: a playbook runs only on servers that have the
# corresponding role in pulumi.stacks.*.servers[].roles. If no server has a
# role, that playbook is skipped entirely.
ansible:
# [Required] Set to false to skip Ansible provisioning.
# Useful if you want to manually configure your servers. You can SSH via the
# tunnel with hostname ssh<index>.<domain>, where 'index' is 0 to n-1.
enabled: true
# [Optional] System groups to create on all servers
# Groups not in this list (except system groups) will be removed.
# Can be overridden per-server via pulumi.stacks.*.servers[].groups
groups:
- devops
# Example with multiple groups:
# groups:
# - devops
# - docker
# - developers
# Web server provisioning (nginx)
# Required if any server has the "web" role
# Choose ONE mode: static (serve files directly) or docker (reverse proxy)
web:
# MODE 1: Static site - nginx serves files directly
# Use this for static sites (HTML/CSS/JS), SPAs, or pre-built frontends
static:
# [Required] Source type: "local" or "image"
source: local
# --- For source: local ---
# Build from a local directory and deploy static assets
# [Required when source is local] Path to the website source directory
dir: "/path/to/your/website"
# [Optional] Build command to run (omit if site is pre-built)
# Supports any build tool: bun, npm, yarn, pnpm, make, etc.
build: "bun run build"
# [Required when source is local] Subdirectory containing built assets
dist: "dist"
# --- For source: image ---
# Pull pre-built static assets from a container image
# Useful for CI pipelines that package sites as OCI images
# [Required when source is image] Container image reference
# image: ghcr.io/your-org/site-assets
# [Required when source is image] Image tag
# tag: latest
# [Required when source is image] Path inside container to extract assets from
# path: "/app/dist"
# MODE 2: Dockerized web app - nginx acts as reverse proxy
# Use this for SSR frameworks (Next.js, Nuxt), Node.js apps, or any containerized web server
# Uncomment to use instead of static mode (modes are mutually exclusive)
# docker:
# # [Required] Container image reference
# # Currently only GitHub Container Registry (ghcr.io) is supported
# image: ghcr.io/your-org/web-app
#
# # [Required] Image tag to deploy
# tag: latest
#
# # [Required] Port the web application listens on
# port: 3000
#
# # [Optional] Environment variables passed to the web container
# env:
# NODE_ENV: production
# # Add your application-specific environment variables
# Backend application provisioning
# Required if any server has the "backend" role
backend:
# [Required] Full container image reference
# Currently only GitHub Container Registry (ghcr.io) is supported
image: ghcr.io/your-org/your-app
# [Required] Image tag to deploy
tag: latest
# [Required] Port the backend application listens on
# Also used by Pulumi for Cloudflare tunnel configuration. The cloudflared
# daemon forwards HTTP requests to this port in your container.
port: 3000
# [Optional] Environment variables passed to the backend container
# Each key-value pair becomes an environment variable in the container
# Note: PORT is automatically injected from 'port' above; do not set it here
env:
# Add your application-specific environment variables:
# DATABASE_URL: postgres://user:pass@host:5432/db
# REDIS_URL: redis://localhost:6379
# API_KEY: your_api_key_here
# ============================================
# Secrets Configuration
# ============================================
# Configure how secrets are retrieved at runtime.
# Actual secret values are NEVER stored in this file.
secrets:
# [Optional, default: bws] Secrets provider
# Currently only "bws" (Bitwarden Secrets Manager) is supported
provider: bws
# [Optional] Bitwarden Secrets Manager project ID
# If omitted, secrets are fetched from all projects accessible by the token
# projectId: "your_bws_project_id"
# [Optional] List of additional secret names that must be present in Bitwarden
# before provisioning starts. These are validated after fetching from Bitwarden.
# Built-in required secrets:
# - GHCR_TOKEN: GitHub Container Registry token for pulling Docker images
# - GHCR_USERNAME: GitHub Container Registry username for authentication
# - VPS_SSH_KEY: SSH private key for server provisioning and configuration
# - PULUMI_ACCESS_TOKEN: Pulumi Cloud token for infrastructure state management
# - CLOUDFLARE_API_TOKEN: Cloudflare API token for DNS, tunnels, and SSL
# - DIGITALOCEAN_TOKEN: DigitalOcean API token for provisioning servers
requiredVars: []
# Example:
# requiredVars:
# - MY_API_KEY
# - DATABASE_PASSWORD
# - STRIPE_SECRET