create-tigra 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,208 +1,221 @@
1
- # ===================================================================
2
- # PRODUCTION ENVIRONMENT CONFIGURATION
3
- # ===================================================================
4
- # This file contains production-optimized settings for high-traffic
5
- # deployments (10K-100K users/day). Copy to .env and customize.
6
- #
7
- # COOLIFY DEPLOYMENT NOTE:
8
- # When adding environment variables in Coolify, do NOT check
9
- # "Available at Buildtime" for any variable unless explicitly noted.
10
- # The server Dockerfile handles build-time config internally.
11
- # Secrets (DATABASE_URL, JWT_SECRET, COOKIE_SECRET, REDIS_URL) must
12
- # NEVER be available at buildtime — they get baked into the image layer.
13
- #
14
- # ===================================================================
15
-
16
- # ===================================================================
17
- # APPLICATION
18
- # ===================================================================
19
-
20
- # COOLIFY: Do NOT check "Available at Buildtime" — the Dockerfile
21
- # sets NODE_ENV=development during build to ensure devDependencies install.
22
- NODE_ENV=production
23
- PORT=3000
24
- HOST=0.0.0.0
25
-
26
- # ===================================================================
27
- # SERVER TIMEOUTS
28
- # ===================================================================
29
-
30
- # Fastify request timeout in milliseconds (default: 30000 = 30s)
31
- # Long-running routes (LLM calls, big exports) may need 180000+ (180s).
32
- # CRITICAL: the reverse proxy (Nginx/Coolify) timeout must be raised to
33
- # match, or the proxy cuts the connection before the server does.
34
- REQUEST_TIMEOUT_MS=30000
35
-
36
- # Fastify connection timeout in milliseconds (default: 60000 = 60s)
37
- CONNECTION_TIMEOUT_MS=60000
38
-
39
- # ===================================================================
40
- # DATABASE (MySQL 8.0+)
41
- # ===================================================================
42
-
43
- # Production database connection
44
- # CRITICAL: Use secure credentials, SSL/TLS, and private network
45
- # COOLIFY: Runtime only. Do NOT check "Available at Buildtime".
46
- DATABASE_URL="mysql://prod_user:SECURE_PASSWORD@db.internal:3306/prod_db?ssl=true"
47
-
48
- # Connection pool for high traffic (10K-100K users/day)
49
- # Recommended: 20-50 connections for production
50
- # Monitor and adjust based on load testing results
51
- DATABASE_POOL_MIN=10
52
- DATABASE_POOL_MAX=50
53
-
54
- # ===================================================================
55
- # REDIS
56
- # ===================================================================
57
-
58
- # Production Redis instance
59
- # CRITICAL: Use authentication and private network
60
- # COOLIFY: Runtime only. Do NOT check "Available at Buildtime".
61
- REDIS_URL="redis://:REDIS_PASSWORD@redis.internal:6379"
62
-
63
- # Production retry settings
64
- REDIS_MAX_RETRIES=5
65
- REDIS_CONNECT_TIMEOUT=5000
66
-
67
- # ===================================================================
68
- # RATE LIMITING
69
- # ===================================================================
70
-
71
- # Always enabled in production
72
- RATE_LIMIT_ENABLED=true
73
-
74
- # Production: keep at 1 (default limits are tuned for production)
75
- RATE_LIMIT_MULTIPLIER=1
76
-
77
- # Tight limits for sensitive auth routes in production
78
- RATE_LIMIT_AUTH_LOGIN_MAX=10
79
- RATE_LIMIT_AUTH_REGISTER_MAX=5
80
-
81
- # ===================================================================
82
- # IP AUTO-BLOCK
83
- # ===================================================================
84
-
85
- # Rate-limit violations before an IP is auto-blocked for every route.
86
- # Keep HIGH enough that a retry-looping legitimate client or a NAT'd
87
- # office sharing one egress IP cannot self-ban (sustained abuse only).
88
- # See src/config/rate-limit.config.ts before lowering.
89
- IP_AUTO_BLOCK_THRESHOLD=20
90
-
91
- # Sliding window for counting violations, in seconds (5 minutes)
92
- IP_AUTO_BLOCK_WINDOW_SECONDS=300
93
-
94
- # How long an auto-blocked IP stays blocked, in seconds (1 hour)
95
- IP_AUTO_BLOCK_DURATION_SECONDS=3600
96
-
97
- # ===================================================================
98
- # ACCOUNT ACTIVATION
99
- # ===================================================================
100
-
101
- # Require account verification before users can log in
102
- # Set to true in production for security
103
- REQUIRE_USER_VERIFICATION=true
104
-
105
- # ===================================================================
106
- # FILE UPLOAD
107
- # ===================================================================
108
-
109
- # Maximum file upload size in MB
110
- MAX_FILE_SIZE_MB=10
111
-
112
- # COOLIFY PERSISTENT STORAGE (required for uploads to survive redeployments):
113
- # Go to your service in Coolify → Storages → Add Volume Mount:
114
- # Name: uploads (or <project-name>-uploads)
115
- # Source Path: (leave empty Coolify manages the Docker volume)
116
- # Destination Path: /app/uploads
117
- # Without this, all uploaded files are lost on every redeployment.
118
-
119
- # ===================================================================
120
- # JWT AUTHENTICATION
121
- # ===================================================================
122
-
123
- # CRITICAL: Generate a cryptographically secure secret
124
- # Example: openssl rand -base64 48
125
- # COOLIFY: Runtime only. Do NOT check "Available at Buildtime" — this is a secret!
126
- JWT_SECRET="YOUR_PRODUCTION_JWT_SECRET_MUST_BE_AT_LEAST_32_CHARS_LONG"
127
-
128
- # Production token expiry (tighter security)
129
- JWT_ACCESS_EXPIRY="15m"
130
- JWT_REFRESH_EXPIRY="7d"
131
-
132
- # Cookie signing secret (separate from JWT for defense-in-depth)
133
- # COOLIFY: Runtime only. Do NOT check "Available at Buildtime" — this is a secret!
134
- COOKIE_SECRET="YOUR_PRODUCTION_COOKIE_SECRET_MUST_BE_AT_LEAST_32_CHARS"
135
-
136
- # ===================================================================
137
- # CORS
138
- # ===================================================================
139
-
140
- # REQUIRED in production - your frontend domain(s)
141
- # Multiple origins separated by commas
142
- CORS_ORIGIN="https://yourdomain.com,https://app.yourdomain.com"
143
-
144
- # Cookie domain for cross-origin deployments
145
- # REQUIRED when client and API are on different subdomains:
146
- # Client: https://app.example.com | API: https://api.example.com
147
- # → Set COOKIE_DOMAIN=".example.com" (leading dot = all subdomains)
148
- # This enables cookies to be shared between client and API subdomains.
149
- # Without it, login will silently fail (server returns 200 but browser drops cookies).
150
- COOKIE_DOMAIN=".yourdomain.com"
151
-
152
- # ===================================================================
153
- # EMAIL (Resend)
154
- # ===================================================================
155
-
156
- # Resend API key for transactional emails
157
- # COOLIFY: Runtime only. Do NOT check "Available at Buildtime" — this is a secret!
158
- RESEND_API_KEY="re_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
159
-
160
- # Sender email must be from a verified domain in Resend
161
- RESEND_FROM_EMAIL="noreply@yourdomain.com"
162
-
163
- # Frontend URL for email links (password reset, verification, etc.)
164
- CLIENT_URL="https://yourdomain.com"
165
-
166
- # ===================================================================
167
- # LOGGING
168
- # ===================================================================
169
-
170
- # Production: info or warn (reduces log volume)
171
- # Use warn to reduce costs in high-traffic scenarios
172
- LOG_LEVEL=info
173
-
174
- # ===================================================================
175
- # DATABASE SEEDING
176
- # ===================================================================
177
-
178
- # DO NOT SEED PRODUCTION. The seed script (npm run prisma:seed) creates
179
- # well-known demo accounts (admin@example.com) and hard-refuses to run when
180
- # NODE_ENV=production. These variables exist only to keep .env files in sync
181
- # across environments — leave them commented out in production.
182
- # SEED_ADMIN_PASSWORD=
183
- # SEED_USER_PASSWORD=
184
-
185
- # ===================================================================
186
- # ERROR TRACKING
187
- # ===================================================================
188
-
189
- # Sentry for production error monitoring
190
- # Get your DSN from: https://sentry.io/settings/projects/
191
- SENTRY_DSN="https://YOUR_PUBLIC_KEY@o0.ingest.sentry.io/YOUR_PROJECT_ID"
192
-
193
- # ===================================================================
194
- # PRODUCTION CHECKLIST
195
- # ===================================================================
196
- # [ ] DATABASE_URL uses secure credentials and SSL
197
- # [ ] JWT_SECRET is a strong random string (48+ chars)
198
- # [ ] CORS_ORIGIN is set to your exact frontend URL(s)
199
- # [ ] COOKIE_DOMAIN is set if client and API are on different subdomains
200
- # [ ] REDIS_URL uses authentication if Redis is exposed
201
- # [ ] LOG_LEVEL is set to info or warn
202
- # [ ] SENTRY_DSN is configured for error tracking
203
- # [ ] Database connection pool tested under load
204
- # [ ] All secrets are stored in environment variables, not in code
205
- # [ ] SSL/TLS certificates are configured
206
- # [ ] Firewall rules restrict access to database and Redis
207
- # [ ] In Coolify: NO secrets have "Available at Buildtime" checked
208
- # [ ] In Coolify: NODE_ENV does NOT have "Available at Buildtime" checked
1
+ # ===================================================================
2
+ # PRODUCTION ENVIRONMENT CONFIGURATION
3
+ # ===================================================================
4
+ # This file contains production-optimized settings for high-traffic
5
+ # deployments (10K-100K users/day). Copy to .env and customize.
6
+ #
7
+ # COOLIFY DEPLOYMENT NOTE:
8
+ # When adding environment variables in Coolify, do NOT check
9
+ # "Available at Buildtime" for any variable unless explicitly noted.
10
+ # The server Dockerfile handles build-time config internally.
11
+ # Secrets (DATABASE_URL, JWT_SECRET, COOKIE_SECRET, REDIS_URL) must
12
+ # NEVER be available at buildtime — they get baked into the image layer.
13
+ #
14
+ # ===================================================================
15
+
16
+ # ===================================================================
17
+ # APPLICATION
18
+ # ===================================================================
19
+
20
+ # COOLIFY: Do NOT check "Available at Buildtime" — the Dockerfile
21
+ # sets NODE_ENV=development during build to ensure devDependencies install.
22
+ NODE_ENV=production
23
+ PORT=3000
24
+ HOST=0.0.0.0
25
+
26
+ # ===================================================================
27
+ # SERVER TIMEOUTS
28
+ # ===================================================================
29
+
30
+ # Fastify request timeout in milliseconds (default: 30000 = 30s)
31
+ # Long-running routes (LLM calls, big exports) may need 180000+ (180s).
32
+ # CRITICAL: the reverse proxy (Nginx/Coolify) timeout must be raised to
33
+ # match, or the proxy cuts the connection before the server does.
34
+ REQUEST_TIMEOUT_MS=30000
35
+
36
+ # Fastify connection timeout in milliseconds (default: 60000 = 60s)
37
+ CONNECTION_TIMEOUT_MS=60000
38
+
39
+ # ===================================================================
40
+ # DATABASE (MySQL 8.0+)
41
+ # ===================================================================
42
+
43
+ # Production database connection
44
+ # CRITICAL: Use secure credentials, SSL/TLS, and private network
45
+ # COOLIFY: Runtime only. Do NOT check "Available at Buildtime".
46
+ DATABASE_URL="mysql://prod_user:SECURE_PASSWORD@db.internal:3306/prod_db?ssl=true"
47
+
48
+ # Connection pool for high traffic (10K-100K users/day)
49
+ # Recommended: 20-50 connections for production
50
+ # Monitor and adjust based on load testing results
51
+ DATABASE_POOL_MIN=10
52
+ DATABASE_POOL_MAX=50
53
+
54
+ # ===================================================================
55
+ # REDIS
56
+ # ===================================================================
57
+
58
+ # Production Redis instance
59
+ # CRITICAL: Use authentication and private network
60
+ # COOLIFY: Runtime only. Do NOT check "Available at Buildtime".
61
+ REDIS_URL="redis://:REDIS_PASSWORD@redis.internal:6379"
62
+
63
+ # Production retry settings
64
+ REDIS_MAX_RETRIES=5
65
+ REDIS_CONNECT_TIMEOUT=5000
66
+
67
+ # ===================================================================
68
+ # RATE LIMITING
69
+ # ===================================================================
70
+
71
+ # Always enabled in production
72
+ RATE_LIMIT_ENABLED=true
73
+
74
+ # Production: keep at 1 (default limits are tuned for production)
75
+ RATE_LIMIT_MULTIPLIER=1
76
+
77
+ # Tight limits for sensitive auth routes in production
78
+ RATE_LIMIT_AUTH_LOGIN_MAX=10
79
+ RATE_LIMIT_AUTH_REGISTER_MAX=5
80
+
81
+ # Trust Cloudflare's CF-Connecting-IP header for the real client IP (default: false)
82
+ # Used ONLY for rate-limiting and IP auto-block decisions. Behind Cloudflare,
83
+ # request.ip is a CF edge IP — without this, all users behind one edge collapse
84
+ # onto a single IP and can rate-limit or auto-ban each other.
85
+ # COOLIFY: Runtime only. Do NOT check "Available at Buildtime".
86
+ # SECURITY: the header is client-spoofable. Set true ONLY when this origin
87
+ # accepts traffic exclusively via Cloudflare (direct origin access is blocked
88
+ # at the firewall/network so clients cannot reach it bypassing CF).
89
+ # Note: the left-most X-Forwarded-For entry is now trusted as the client IP
90
+ # regardless of this flag (covers grey-cloud / DNS-only), so the origin must be
91
+ # proxy-locked (firewall direct access) in production either way.
92
+ TRUST_CLOUDFLARE=false
93
+
94
+ # ===================================================================
95
+ # IP AUTO-BLOCK
96
+ # ===================================================================
97
+
98
+ # Rate-limit violations before an IP is auto-blocked for every route.
99
+ # Keep HIGH enough that a retry-looping legitimate client or a NAT'd
100
+ # office sharing one egress IP cannot self-ban (sustained abuse only).
101
+ # See src/config/rate-limit.config.ts before lowering.
102
+ IP_AUTO_BLOCK_THRESHOLD=20
103
+
104
+ # Sliding window for counting violations, in seconds (5 minutes)
105
+ IP_AUTO_BLOCK_WINDOW_SECONDS=300
106
+
107
+ # How long an auto-blocked IP stays blocked, in seconds (1 hour)
108
+ IP_AUTO_BLOCK_DURATION_SECONDS=3600
109
+
110
+ # ===================================================================
111
+ # ACCOUNT ACTIVATION
112
+ # ===================================================================
113
+
114
+ # Require account verification before users can log in
115
+ # Set to true in production for security
116
+ REQUIRE_USER_VERIFICATION=true
117
+
118
+ # ===================================================================
119
+ # FILE UPLOAD
120
+ # ===================================================================
121
+
122
+ # Maximum file upload size in MB
123
+ MAX_FILE_SIZE_MB=10
124
+
125
+ # COOLIFY PERSISTENT STORAGE (required for uploads to survive redeployments):
126
+ # Go to your service in Coolify → Storages → Add Volume Mount:
127
+ # Name: uploads (or <project-name>-uploads)
128
+ # Source Path: (leave empty Coolify manages the Docker volume)
129
+ # Destination Path: /app/uploads
130
+ # Without this, all uploaded files are lost on every redeployment.
131
+
132
+ # ===================================================================
133
+ # JWT AUTHENTICATION
134
+ # ===================================================================
135
+
136
+ # CRITICAL: Generate a cryptographically secure secret
137
+ # Example: openssl rand -base64 48
138
+ # COOLIFY: Runtime only. Do NOT check "Available at Buildtime" — this is a secret!
139
+ JWT_SECRET="YOUR_PRODUCTION_JWT_SECRET_MUST_BE_AT_LEAST_32_CHARS_LONG"
140
+
141
+ # Production token expiry (tighter security)
142
+ JWT_ACCESS_EXPIRY="15m"
143
+ JWT_REFRESH_EXPIRY="7d"
144
+
145
+ # Cookie signing secret (separate from JWT for defense-in-depth)
146
+ # COOLIFY: Runtime only. Do NOT check "Available at Buildtime" — this is a secret!
147
+ COOKIE_SECRET="YOUR_PRODUCTION_COOKIE_SECRET_MUST_BE_AT_LEAST_32_CHARS"
148
+
149
+ # ===================================================================
150
+ # CORS
151
+ # ===================================================================
152
+
153
+ # REQUIRED in production - your frontend domain(s)
154
+ # Multiple origins separated by commas
155
+ CORS_ORIGIN="https://yourdomain.com,https://app.yourdomain.com"
156
+
157
+ # Cookie domain for cross-origin deployments
158
+ # REQUIRED when client and API are on different subdomains:
159
+ # Client: https://app.example.com | API: https://api.example.com
160
+ # Set COOKIE_DOMAIN=".example.com" (leading dot = all subdomains)
161
+ # This enables cookies to be shared between client and API subdomains.
162
+ # Without it, login will silently fail (server returns 200 but browser drops cookies).
163
+ COOKIE_DOMAIN=".yourdomain.com"
164
+
165
+ # ===================================================================
166
+ # EMAIL (Resend)
167
+ # ===================================================================
168
+
169
+ # Resend API key for transactional emails
170
+ # COOLIFY: Runtime only. Do NOT check "Available at Buildtime" — this is a secret!
171
+ RESEND_API_KEY="re_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
172
+
173
+ # Sender email — must be from a verified domain in Resend
174
+ RESEND_FROM_EMAIL="noreply@yourdomain.com"
175
+
176
+ # Frontend URL for email links (password reset, verification, etc.)
177
+ CLIENT_URL="https://yourdomain.com"
178
+
179
+ # ===================================================================
180
+ # LOGGING
181
+ # ===================================================================
182
+
183
+ # Production: info or warn (reduces log volume)
184
+ # Use warn to reduce costs in high-traffic scenarios
185
+ LOG_LEVEL=info
186
+
187
+ # ===================================================================
188
+ # DATABASE SEEDING
189
+ # ===================================================================
190
+
191
+ # DO NOT SEED PRODUCTION. The seed script (npm run prisma:seed) creates
192
+ # well-known demo accounts (admin@example.com) and hard-refuses to run when
193
+ # NODE_ENV=production. These variables exist only to keep .env files in sync
194
+ # across environments — leave them commented out in production.
195
+ # SEED_ADMIN_PASSWORD=
196
+ # SEED_USER_PASSWORD=
197
+
198
+ # ===================================================================
199
+ # ERROR TRACKING
200
+ # ===================================================================
201
+
202
+ # Sentry for production error monitoring
203
+ # Get your DSN from: https://sentry.io/settings/projects/
204
+ SENTRY_DSN="https://YOUR_PUBLIC_KEY@o0.ingest.sentry.io/YOUR_PROJECT_ID"
205
+
206
+ # ===================================================================
207
+ # PRODUCTION CHECKLIST
208
+ # ===================================================================
209
+ # [ ] DATABASE_URL uses secure credentials and SSL
210
+ # [ ] JWT_SECRET is a strong random string (48+ chars)
211
+ # [ ] CORS_ORIGIN is set to your exact frontend URL(s)
212
+ # [ ] COOKIE_DOMAIN is set if client and API are on different subdomains
213
+ # [ ] REDIS_URL uses authentication if Redis is exposed
214
+ # [ ] LOG_LEVEL is set to info or warn
215
+ # [ ] SENTRY_DSN is configured for error tracking
216
+ # [ ] Database connection pool tested under load
217
+ # [ ] All secrets are stored in environment variables, not in code
218
+ # [ ] SSL/TLS certificates are configured
219
+ # [ ] Firewall rules restrict access to database and Redis
220
+ # [ ] In Coolify: NO secrets have "Available at Buildtime" checked
221
+ # [ ] In Coolify: NODE_ENV does NOT have "Available at Buildtime" checked
@@ -17,6 +17,17 @@ services:
17
17
  image: mysql:8.0
18
18
  container_name: {{PROJECT_NAME}}-mysql
19
19
  restart: unless-stopped
20
+ # Local-dev resource bounds. mem_limit is a cgroup ceiling (a runaway container is
21
+ # OOM-killed in isolation instead of wedging the whole WSL2/Docker engine); the flags
22
+ # dev-tune MySQL 8 to a small, fast-warming footprint. Production reaches MySQL as a
23
+ # separate Coolify resource via DATABASE_URL — none of this touches prod.
24
+ mem_limit: 900m
25
+ command:
26
+ - --innodb-buffer-pool-size=128M # default is fine for dev; keeps RSS small
27
+ - --performance-schema=OFF # saves ~hundreds of MB on its own
28
+ - --skip-name-resolve # no reverse-DNS per connection (faster, leaner)
29
+ - --max-connections=60 # well above DATABASE_POOL_MAX (10) + headroom
30
+ - --innodb-flush-log-at-trx-commit=2 # dev durability/throughput trade — not for prod
20
31
  ports:
21
32
  - '127.0.0.1:${MYSQL_PORT:-{{MYSQL_PORT}}}:3306'
22
33
  environment:
@@ -57,6 +68,12 @@ services:
57
68
  image: redis:7-alpine
58
69
  container_name: {{PROJECT_NAME}}-redis
59
70
  restart: unless-stopped
71
+ # Local-dev resource bounds. Layer two ceilings: Redis's own --maxmemory (150mb) trips
72
+ # FIRST and refuses writes loudly (noeviction — create-tigra also keeps rate-limit/queue
73
+ # keys in Redis, so silent LRU eviction would be a dev data-loss trap), while the 200m
74
+ # cgroup mem_limit sits above it as a hard backstop. --save "" drops RDB snapshot fork/IO.
75
+ mem_limit: 200m
76
+ command: ['redis-server', '--maxmemory', '150mb', '--maxmemory-policy', 'noeviction', '--save', '']
60
77
  ports:
61
78
  - '127.0.0.1:${REDIS_PORT:-{{REDIS_PORT}}}:6379'
62
79
  volumes: