Repository navigation
Expand file tree
/
Copy pathcompose.coolify.yaml
More file actions
222 lines (218 loc) · 10.3 KB
/
Copy pathcompose.coolify.yaml
File metadata and controls
222 lines (218 loc) · 10.3 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
221
222
# Coolify deployment - API and web app (staging).
#
# Routing: traffic enters via Cloudflare Tunnel -> Coolify's Traefik proxy ->
# this container on the shared Coolify network. Services may use the same
# internal container ports as other Coolify resources; they are routed by
# service/domain, not by globally unique container ports. Avoid hand-written
# generic Traefik service labels such as `api`, `web`, or `website` because
# those names are provider-wide and can collide with other Coolify apps.
#
# Required env vars (set in Coolify -> Resource -> Environment Variables):
# POSTGRES_HOST, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD,
# POSTGRES_MIGRATION_CONNECTION,
# JWT_SECRET_KEY, ENCRYPTION_KEY, ASSET_TOKEN_SECRET_KEY,
# AUTH_SECRET, API_PUBLIC_URL, WEB_PUBLIC_URL,
# PaymentGateways__Stripe__ApiKey,
# PaymentGateways__Stripe__PublishableKey,
# PaymentGateways__Stripe__AccountId,
# Billing__Stripe__WebhookSecret, Billing__Stripe__WebhookEndpointId,
# Billing__Stripe__ApiVersion, Billing__Stripe__LiveMode
#
# Recommended env vars:
# JWT_ISSUER, JWT_AUDIENCE
#
# Migration env var:
# POSTGRES_MIGRATION_CONNECTION
# Full PostgreSQL connection string for a DDL-capable migration role.
# Its username must differ from POSTGRES_USER. Startup initialization uses
# this connection; runtime traffic always uses POSTGRES_USER.
# Before the first migration, a PostgreSQL administrator must run:
# psql -v migration_role=<role> -d <database> \
# -f apps/api/scripts/bootstrap-economy-database.sql
#
# Coolify owns SERVICE_FQDN_* / SERVICE_URL_* variables and service routing.
# Application containers consume explicit public URLs only. Do not pass
# port-suffixed SERVICE_FQDN_*_* values into containers; stale generated values
# can override custom domains in multi-service compose deployments.
services:
backend:
build:
context: .
dockerfile: apps/api/Dockerfile
image: game-guild-api
ports:
- '8080'
environment:
- ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Staging}
- ASPNETCORE_HTTP_PORTS=8080
- OpenTelemetry__Enabled=${OPENTELEMETRY_ENABLED:-false}
- OpenTelemetry__ServiceName=${OPENTELEMETRY_SERVICE_NAME:-GameGuild.API}
- OpenTelemetry__ServiceInstanceId=${OPENTELEMETRY_SERVICE_INSTANCE_ID:-}
- OpenTelemetry__OtlpEndpoint=${OPENTELEMETRY_OTLP_ENDPOINT:-}
- OpenTelemetry__OtlpProtocol=${OPENTELEMETRY_OTLP_PROTOCOL:-http/protobuf}
- OpenTelemetry__ConsoleExporterEnabled=${OPENTELEMETRY_CONSOLE_EXPORTER_ENABLED:-false}
- OpenTelemetry__IncludeSqlStatements=${OPENTELEMETRY_INCLUDE_SQL_STATEMENTS:-false}
- Authentication__Web3__Siwe__Origin=${WEB_PUBLIC_URL:?set WEB_PUBLIC_URL}
- ASPNETCORE_FORWARDEDHEADERS_ENABLED=true
- DATAPROTECTION_KEYS_PATH=/app/.aspnet/DataProtection-Keys
- SeedData__ImportSnapshotCourses=${SEED_SNAPSHOT_COURSES:-false}
# Shared Coolify Postgres
- ConnectionStrings__DefaultConnection=Host=${POSTGRES_HOST:?set POSTGRES_HOST};Port=${POSTGRES_PORT:-5432};Database=${POSTGRES_DB:?set POSTGRES_DB};Username=${POSTGRES_USER:?set POSTGRES_USER};Password=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD};Include Error Detail=false;Gss Encryption Mode=Disable;Maximum Pool Size=100;Minimum Pool Size=5;Connection Idle Lifetime=300
- ConnectionStrings__AuthenticationDb=Host=${POSTGRES_HOST:?set POSTGRES_HOST};Port=${POSTGRES_PORT:-5432};Database=${POSTGRES_DB:?set POSTGRES_DB};Username=${POSTGRES_USER:?set POSTGRES_USER};Password=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD};Include Error Detail=false;Gss Encryption Mode=Disable;Maximum Pool Size=100;Minimum Pool Size=5;Connection Idle Lifetime=300
- ConnectionStrings__MigrationConnection=${POSTGRES_MIGRATION_CONNECTION:?set POSTGRES_MIGRATION_CONNECTION with a role distinct from POSTGRES_USER}
- POSTGRES_MIGRATION_CONNECTION=${POSTGRES_MIGRATION_CONNECTION:?set POSTGRES_MIGRATION_CONNECTION with a role distinct from POSTGRES_USER}
- Database__RunStartupInitialization=true
- Database__GrantRuntimeRoleAfterMigrations=true
- Database__FailStartupOnMigrationFailure=true
- Database__FailStartupOnSeedFailure=true
- Database__FailStartupOnGrantFailure=true
# JWT configuration consumed by the API and auth services
- Jwt__SecretKey=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}
- Jwt__Issuer=${JWT_ISSUER:-GameGuild}
- Jwt__Audience=${JWT_AUDIENCE:-GameGuild.Users}
- Authentication__JwtSecretKey=${JWT_SECRET_KEY:?set JWT_SECRET_KEY}
- Authentication__JwtIssuer=${JWT_ISSUER:-GameGuild}
- Authentication__JwtAudience=${JWT_AUDIENCE:-GameGuild.Users}
- Authentication__JwtExpiration=${JWT_EXPIRATION:-24:00:00}
- Encryption__Key=${ENCRYPTION_KEY:?set ENCRYPTION_KEY}
- Encryption__EncryptionKey=${ENCRYPTION_KEY:?set ENCRYPTION_KEY}
- Redis__Enabled=true
- Redis__ConnectionString=${REDIS_CONNECTION_STRING:?set REDIS_CONNECTION_STRING}
- Redis__InstanceName=${REDIS_INSTANCE_NAME:-game-guild:}
- Assets__Storage__ServiceUrl=${S3_SERVICE_URL:?set S3_SERVICE_URL}
- Assets__Storage__AccessKey=${S3_ACCESS_KEY:?set S3_ACCESS_KEY}
- Assets__Storage__SecretKey=${S3_SECRET_KEY:?set S3_SECRET_KEY}
- Assets__Token__SecretKey=${ASSET_TOKEN_SECRET_KEY:?set ASSET_TOKEN_SECRET_KEY}
- Assets__Storage__Region=${S3_REGION:-garage}
- Assets__Storage__BucketName=${S3_BUCKET:?set S3_BUCKET}
- Assets__Storage__TransformedBucketName=${S3_BUCKET_TRANSFORMED:-}
- Assets__Storage__QuarantineBucketName=${S3_BUCKET_QUARANTINE:-}
- Assets__Storage__ForcePathStyle=true
- Assets__Storage__PresignedUrlExpiryMinutes=${S3_PRESIGNED_EXPIRY:-60}
- StatementEmails__ConsoleBaseUrl=${STATEMENTEMAILS__CONSOLEBASEURL:-}
- EmailDelivery__Enabled=${EMAILDELIVERY__ENABLED:-true}
- EmailDelivery__FromEmail=${EMAILDELIVERY__FROMEMAIL:?set EMAILDELIVERY__FROMEMAIL}
- EmailDelivery__FromName=${EMAILDELIVERY__FROMNAME:-GameGuild}
- EmailDelivery__Ses__Region=${EMAILDELIVERY__SES__REGION:?set EMAILDELIVERY__SES__REGION}
- EmailDelivery__Events__TopicArn=${EMAILDELIVERY__EVENTS__TOPICARN:-}
# Canonical Stripe sections consumed by Payments and Billing.
- PaymentGateways__Stripe__IsEnabled=true
- PaymentGateways__Stripe__UseSimulation=false
- PaymentGateways__Stripe__ApiKey=${PaymentGateways__Stripe__ApiKey:?set PaymentGateways__Stripe__ApiKey}
- PaymentGateways__Stripe__PublishableKey=${PaymentGateways__Stripe__PublishableKey:?set PaymentGateways__Stripe__PublishableKey}
- PaymentGateways__Stripe__AccountId=${PaymentGateways__Stripe__AccountId:?set PaymentGateways__Stripe__AccountId}
- PaymentGateways__Stripe__ConnectedAccountId=${Billing__Stripe__ConnectedAccountId:-}
- PaymentGateways__Stripe__LiveMode=${Billing__Stripe__LiveMode:-false}
- Billing__Stripe__WebhookSecret=${Billing__Stripe__WebhookSecret:?set Billing__Stripe__WebhookSecret}
- Billing__Stripe__WebhookEndpointId=${Billing__Stripe__WebhookEndpointId:?set Billing__Stripe__WebhookEndpointId}
- Billing__Stripe__AccountId=${PaymentGateways__Stripe__AccountId:?set PaymentGateways__Stripe__AccountId}
- Billing__Stripe__ApiVersion=${Billing__Stripe__ApiVersion:?set Billing__Stripe__ApiVersion}
- Billing__Stripe__ConnectedAccountId=${Billing__Stripe__ConnectedAccountId:-}
- Billing__Stripe__LiveMode=${Billing__Stripe__LiveMode:-false}
- Billing__Stripe__WebhookToleranceSeconds=${Billing__Stripe__WebhookToleranceSeconds:-300}
volumes:
- dataprotection-keys-v2:/app/.aspnet/DataProtection-Keys
security_opt:
- no-new-privileges:true
healthcheck:
test: ['CMD-SHELL', 'curl -fsS http://127.0.0.1:8080/live || exit 1']
start_interval: 5s
start_period: 180s
interval: 30s
timeout: 10s
retries: 5
restart: unless-stopped
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '3'
labels:
- 'com.game-guild.app=api'
- 'com.game-guild.tier=backend'
- 'com.game-guild.environment=staging'
- 'traefik.docker.network=coolify'
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
networks:
default:
aliases:
- api
- gameguild-api-internal
coolify: {}
web:
build:
context: .
dockerfile: apps/web/Dockerfile
args:
GIT_HASH: ${GIT_HASH:-}
AUTH_SECRET: ${AUTH_SECRET:?set AUTH_SECRET}
API_INTERNAL_URL: http://backend:8080
API_PUBLIC_URL: ${API_PUBLIC_URL:?set API_PUBLIC_URL}
WEB_PUBLIC_URL: ${WEB_PUBLIC_URL:?set WEB_PUBLIC_URL}
AUTH_COOKIE_DOMAIN: ${AUTH_COOKIE_DOMAIN:-}
image: game-guild-web
ports:
- '3000'
environment:
- NODE_ENV=production
- PORT=3000
- HOSTNAME=0.0.0.0
- API_URL=http://backend:8080
- NEXT_PUBLIC_API_URL=${API_PUBLIC_URL:?set API_PUBLIC_URL}
- NEXT_PUBLIC_APP_URL=${WEB_PUBLIC_URL:?set WEB_PUBLIC_URL}
- WEB_PUBLIC_URL=${WEB_PUBLIC_URL:?set WEB_PUBLIC_URL}
- AUTH_COOKIE_DOMAIN=${AUTH_COOKIE_DOMAIN:-}
- NEXTAUTH_URL=${WEB_PUBLIC_URL:?set WEB_PUBLIC_URL}
- AUTH_SECRET=${AUTH_SECRET:?set AUTH_SECRET}
- AUTH_TRUST_HOST=true
security_opt:
- no-new-privileges:true
healthcheck:
test:
[
'CMD-SHELL',
"node -e \"fetch('http://127.0.0.1:3000/manifest.webmanifest').then(r=>{process.exit(r.ok?0:1)}).catch(()=>process.exit(1))\"",
]
start_interval: 10s
start_period: 90s
interval: 30s
timeout: 10s
retries: 5
restart: unless-stopped
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '3'
labels:
- 'com.game-guild.app=web'
- 'com.game-guild.tier=frontend'
- 'com.game-guild.environment=staging'
- 'traefik.docker.network=coolify'
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.25'
memory: 256M
networks:
- default
- coolify
depends_on:
backend:
condition: service_started
networks:
coolify:
external: true
volumes:
dataprotection-keys-v2:
driver: local