vibecarbon 0.1.7 → 0.2.0

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.
Files changed (102) hide show
  1. package/carbon/.env.example +3 -2
  2. package/carbon/DEVELOPMENT.md +18 -3
  3. package/carbon/PRODUCTION.md +1 -1
  4. package/carbon/content/docs/cli.mdx +3 -3
  5. package/carbon/content/docs/deployment.mdx +1 -1
  6. package/carbon/content/docs/development.mdx +1 -1
  7. package/carbon/content/docs/getting-started.mdx +0 -1
  8. package/carbon/scripts/dev-init.js +1 -1
  9. package/carbon/scripts/generate-dev-configs.sh +5 -7
  10. package/carbon/scripts/validate-dev-configs.sh +5 -7
  11. package/carbon/src/client/components/TechStackSection.tsx +0 -68
  12. package/carbon/src/client/index.css +0 -14
  13. package/carbon/src/client/locales/de.json +0 -18
  14. package/carbon/src/client/locales/en.json +86 -36
  15. package/carbon/src/client/locales/es.json +0 -18
  16. package/carbon/src/client/locales/fr.json +0 -18
  17. package/carbon/src/client/locales/pt.json +0 -18
  18. package/carbon/src/client/pages/Home.tsx +0 -3
  19. package/package.json +4 -2
  20. package/services/index.json +29 -0
  21. package/services/metabase/compose/docker-compose.override.yml +14 -0
  22. package/services/metabase/compose/docker-compose.prod.yml +29 -0
  23. package/services/metabase/compose/docker-compose.yml +68 -0
  24. package/services/metabase/db/init.sh +29 -0
  25. package/services/metabase/docs/integration.md +191 -0
  26. package/services/metabase/k8s/deployment.yaml +88 -0
  27. package/services/metabase/k8s/ingressroute.yaml +22 -0
  28. package/services/metabase/k8s/kustomization.yaml +9 -0
  29. package/services/metabase/k8s/network-policy.yaml +74 -0
  30. package/services/metabase/k8s/pvc.yaml +12 -0
  31. package/services/metabase/k8s/service.yaml +15 -0
  32. package/services/metabase/manifest.json +34 -0
  33. package/services/metabase/scripts/setup.sh +152 -0
  34. package/services/n8n/compose/docker-compose.override.yml +14 -0
  35. package/services/n8n/compose/docker-compose.prod.yml +32 -0
  36. package/services/n8n/compose/docker-compose.yml +99 -0
  37. package/services/n8n/db/init.sh +25 -0
  38. package/services/n8n/docs/SSO.md +124 -0
  39. package/services/n8n/docs/integration.md +155 -0
  40. package/services/n8n/hooks/hooks.js +131 -0
  41. package/services/n8n/k8s/deployment.yaml +116 -0
  42. package/services/n8n/k8s/ingressroute.yaml +24 -0
  43. package/services/n8n/k8s/kustomization.yaml +9 -0
  44. package/services/n8n/k8s/network-policy.yaml +82 -0
  45. package/services/n8n/k8s/pvc.yaml +14 -0
  46. package/services/n8n/k8s/service.yaml +14 -0
  47. package/services/n8n/manifest.json +36 -0
  48. package/services/n8n/scripts/setup.sh +42 -0
  49. package/{carbon/docker-compose.observability.prod.yml → services/observability/compose/docker-compose.prod.yml} +8 -0
  50. package/services/observability/docs/integration.md +31 -0
  51. package/services/observability/k8s/grafana-deployment.yaml +107 -0
  52. package/services/observability/k8s/grafana-provisioning-configmap.yaml +65 -0
  53. package/services/observability/k8s/grafana-pvc.yaml +14 -0
  54. package/services/observability/k8s/grafana-service.yaml +16 -0
  55. package/services/observability/k8s/ingressroute.yaml +22 -0
  56. package/services/observability/k8s/kustomization.yaml +24 -0
  57. package/services/observability/k8s/loki-configmap.yaml +74 -0
  58. package/services/observability/k8s/loki-deployment.yaml +72 -0
  59. package/services/observability/k8s/loki-pvc.yaml +14 -0
  60. package/services/observability/k8s/loki-service.yaml +16 -0
  61. package/services/observability/k8s/network-policy.yaml +141 -0
  62. package/services/observability/k8s/prometheus-configmap.yaml +80 -0
  63. package/services/observability/k8s/prometheus-deployment.yaml +78 -0
  64. package/services/observability/k8s/prometheus-pvc.yaml +14 -0
  65. package/services/observability/k8s/prometheus-rbac.yaml +55 -0
  66. package/services/observability/k8s/prometheus-service.yaml +16 -0
  67. package/services/observability/manifest.json +28 -0
  68. package/services/redis/compose/docker-compose.prod.yml +10 -0
  69. package/services/redis/compose/docker-compose.yml +24 -0
  70. package/services/redis/docs/integration.md +148 -0
  71. package/services/redis/k8s/deployment.yaml +70 -0
  72. package/services/redis/k8s/kustomization.yaml +8 -0
  73. package/services/redis/k8s/network-policy.yaml +20 -0
  74. package/services/redis/k8s/pvc.yaml +12 -0
  75. package/services/redis/k8s/service.yaml +15 -0
  76. package/services/redis/manifest.json +30 -0
  77. package/services/s3/compose/docker-compose.s3-ha.yml +86 -0
  78. package/services/s3/compose/docker-compose.s3.yml +35 -0
  79. package/services/s3/manifest.json +87 -0
  80. package/src/add.js +57 -89
  81. package/src/cli.js +1 -1
  82. package/src/create.js +3 -87
  83. package/src/lib/deploy/bundle.js +4 -2
  84. package/src/lib/deploy/compose/index.js +45 -17
  85. package/src/lib/deploy/orchestrator.js +13 -1
  86. package/src/remove.js +9 -6
  87. package/carbon/content/docs/optional-services.mdx +0 -160
  88. package/carbon/src/client/components/MetricsStrip.tsx +0 -48
  89. /package/{carbon/docker-compose.observability.override.yml → services/observability/compose/docker-compose.override.yml} +0 -0
  90. /package/{carbon/docker-compose.observability.yml → services/observability/compose/docker-compose.yml} +0 -0
  91. /package/{carbon → services/observability}/volumes/grafana/dashboards/logs.json +0 -0
  92. /package/{carbon → services/observability}/volumes/grafana/dashboards/overview.json +0 -0
  93. /package/{carbon → services/observability}/volumes/grafana/dashboards/postgresql.json +0 -0
  94. /package/{carbon → services/observability}/volumes/grafana/dashboards.dev/logs.json +0 -0
  95. /package/{carbon → services/observability}/volumes/grafana/dashboards.dev/overview.json +0 -0
  96. /package/{carbon → services/observability}/volumes/grafana/dashboards.dev/postgresql.json +0 -0
  97. /package/{carbon → services/observability}/volumes/grafana/provisioning/dashboards/dashboards.dev.yml +0 -0
  98. /package/{carbon → services/observability}/volumes/grafana/provisioning/dashboards/dashboards.yml +0 -0
  99. /package/{carbon → services/observability}/volumes/grafana/provisioning/datasources/datasources.yml +0 -0
  100. /package/{carbon → services/observability}/volumes/loki/loki-config.yml +0 -0
  101. /package/{carbon → services/observability}/volumes/prometheus/prometheus.yml +0 -0
  102. /package/{carbon → services/observability}/volumes/promtail/promtail-config.yml +0 -0
@@ -0,0 +1,24 @@
1
+ # Redis - In-memory data store
2
+ # Added via: vibecarbon add redis
3
+
4
+ services:
5
+ redis:
6
+ image: redis:alpine
7
+ container_name: {{PROJECT_NAME}}-redis
8
+ restart: unless-stopped
9
+ command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
10
+ ports:
11
+ - "6379:6379"
12
+ volumes:
13
+ - redis_data:/data
14
+ networks:
15
+ - vibecarbon-network
16
+ healthcheck:
17
+ test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
18
+ interval: 10s
19
+ timeout: 5s
20
+ retries: 5
21
+
22
+ volumes:
23
+ redis_data:
24
+ driver: local
@@ -0,0 +1,148 @@
1
+ # Redis Integration Guide
2
+
3
+ Redis is an in-memory data store used for caching, session management, rate limiting, and pub/sub messaging.
4
+
5
+ ## Connection Details
6
+
7
+ - **Host**: `redis` (internal) / `localhost` (external)
8
+ - **Port**: `6379`
9
+ - **Password**: See `REDIS_PASSWORD` in `.env.local`
10
+
11
+ ## Usage in Your Application
12
+
13
+ ### Install Redis Client
14
+
15
+ ```bash
16
+ pnpm add ioredis
17
+ ```
18
+
19
+ ### Server-Side Integration
20
+
21
+ Create `src/server/lib/redis.ts`:
22
+
23
+ ```typescript
24
+ import Redis from 'ioredis';
25
+ import { env } from './env';
26
+
27
+ export const redis = new Redis({
28
+ host: env.REDIS_HOST || 'redis',
29
+ port: parseInt(env.REDIS_PORT || '6379'),
30
+ password: env.REDIS_PASSWORD,
31
+ });
32
+
33
+ // Connection event handlers
34
+ redis.on('connect', () => console.log('Redis connected'));
35
+ redis.on('error', (err) => console.error('Redis error:', err));
36
+ ```
37
+
38
+ ### Caching Example
39
+
40
+ ```typescript
41
+ import { redis } from './lib/redis';
42
+
43
+ // Cache a value for 1 hour
44
+ await redis.setex('user:123', 3600, JSON.stringify(userData));
45
+
46
+ // Retrieve cached value
47
+ const cached = await redis.get('user:123');
48
+ if (cached) {
49
+ return JSON.parse(cached);
50
+ }
51
+ ```
52
+
53
+ ### Session Storage
54
+
55
+ ```typescript
56
+ import { redis } from './lib/redis';
57
+
58
+ // Store session
59
+ await redis.hset(`session:${sessionId}`, {
60
+ userId: user.id,
61
+ email: user.email,
62
+ createdAt: Date.now(),
63
+ });
64
+ await redis.expire(`session:${sessionId}`, 86400); // 24 hours
65
+
66
+ // Retrieve session
67
+ const session = await redis.hgetall(`session:${sessionId}`);
68
+ ```
69
+
70
+ ### Rate Limiting
71
+
72
+ ```typescript
73
+ import { redis } from './lib/redis';
74
+
75
+ async function rateLimit(key: string, limit: number, windowSecs: number): Promise<boolean> {
76
+ const current = await redis.incr(key);
77
+ if (current === 1) {
78
+ await redis.expire(key, windowSecs);
79
+ }
80
+ return current <= limit;
81
+ }
82
+
83
+ // Usage: 100 requests per minute per IP
84
+ const allowed = await rateLimit(`ratelimit:${ip}`, 100, 60);
85
+ ```
86
+
87
+ ### Pub/Sub Example
88
+
89
+ ```typescript
90
+ import Redis from 'ioredis';
91
+
92
+ const subscriber = new Redis({ /* config */ });
93
+ const publisher = new Redis({ /* config */ });
94
+
95
+ // Subscribe to channel
96
+ subscriber.subscribe('notifications', (err, count) => {
97
+ console.log(`Subscribed to ${count} channels`);
98
+ });
99
+
100
+ subscriber.on('message', (channel, message) => {
101
+ console.log(`Received ${message} from ${channel}`);
102
+ });
103
+
104
+ // Publish message
105
+ await publisher.publish('notifications', JSON.stringify({ type: 'alert', data: '...' }));
106
+ ```
107
+
108
+ ## Environment Variables
109
+
110
+ Add to your `.env.local`:
111
+
112
+ ```env
113
+ REDIS_HOST=redis
114
+ REDIS_PORT=6379
115
+ REDIS_PASSWORD=your-generated-password
116
+ ```
117
+
118
+ ## Docker Commands
119
+
120
+ ```bash
121
+ # View Redis logs
122
+ pnpm docker:logs redis
123
+
124
+ # Connect to Redis CLI
125
+ docker exec -it {{PROJECT_NAME}}-redis redis-cli -a $REDIS_PASSWORD
126
+
127
+ # Monitor Redis commands in real-time
128
+ docker exec -it {{PROJECT_NAME}}-redis redis-cli -a $REDIS_PASSWORD MONITOR
129
+ ```
130
+
131
+ ## Performance Tips
132
+
133
+ 1. **Use pipelining** for multiple commands:
134
+ ```typescript
135
+ const pipeline = redis.pipeline();
136
+ pipeline.get('key1');
137
+ pipeline.get('key2');
138
+ const results = await pipeline.exec();
139
+ ```
140
+
141
+ 2. **Set appropriate TTLs** to prevent memory bloat
142
+
143
+ 3. **Use Redis data structures** (hashes, sets, sorted sets) instead of serialized JSON when possible
144
+
145
+ 4. **Monitor memory usage**:
146
+ ```bash
147
+ redis-cli -a $REDIS_PASSWORD INFO memory
148
+ ```
@@ -0,0 +1,70 @@
1
+ apiVersion: apps/v1
2
+ kind: Deployment
3
+ metadata:
4
+ name: redis
5
+ labels:
6
+ app: redis
7
+ spec:
8
+ replicas: 1
9
+ selector:
10
+ matchLabels:
11
+ app: redis
12
+ template:
13
+ metadata:
14
+ labels:
15
+ app: redis
16
+ spec:
17
+ containers:
18
+ - name: redis
19
+ image: redis:alpine
20
+ command:
21
+ - redis-server
22
+ - --appendonly
23
+ - 'yes'
24
+ - --requirepass
25
+ - $(REDIS_PASSWORD)
26
+ ports:
27
+ - containerPort: 6379
28
+ env:
29
+ - name: REDIS_PASSWORD
30
+ valueFrom:
31
+ secretKeyRef:
32
+ name: vibecarbon-secrets
33
+ key: REDIS_PASSWORD
34
+ volumeMounts:
35
+ - name: redis-data
36
+ mountPath: /data
37
+ resources:
38
+ requests:
39
+ memory: 128Mi
40
+ cpu: 100m
41
+ limits:
42
+ memory: 512Mi
43
+ cpu: 500m
44
+ livenessProbe:
45
+ exec:
46
+ command:
47
+ - redis-cli
48
+ - -a
49
+ - $(REDIS_PASSWORD)
50
+ - ping
51
+ initialDelaySeconds: 10
52
+ periodSeconds: 10
53
+ readinessProbe:
54
+ exec:
55
+ command:
56
+ - redis-cli
57
+ - -a
58
+ - $(REDIS_PASSWORD)
59
+ - ping
60
+ initialDelaySeconds: 5
61
+ periodSeconds: 5
62
+ securityContext:
63
+ allowPrivilegeEscalation: false
64
+ volumes:
65
+ - name: redis-data
66
+ persistentVolumeClaim:
67
+ claimName: redis-pvc
68
+ securityContext:
69
+ seccompProfile:
70
+ type: RuntimeDefault
@@ -0,0 +1,8 @@
1
+ apiVersion: kustomize.config.k8s.io/v1beta1
2
+ kind: Kustomization
3
+
4
+ resources:
5
+ - deployment.yaml
6
+ - service.yaml
7
+ - pvc.yaml
8
+ - network-policy.yaml
@@ -0,0 +1,20 @@
1
+ apiVersion: networking.k8s.io/v1
2
+ kind: NetworkPolicy
3
+ metadata:
4
+ name: redis-policy
5
+ namespace: vibecarbon
6
+ spec:
7
+ podSelector:
8
+ matchLabels:
9
+ app: redis
10
+ policyTypes:
11
+ - Ingress
12
+ ingress:
13
+ # Allow connections from the application server only
14
+ - from:
15
+ - podSelector:
16
+ matchLabels:
17
+ app: vibecarbon-app
18
+ ports:
19
+ - protocol: TCP
20
+ port: 6379
@@ -0,0 +1,12 @@
1
+ apiVersion: v1
2
+ kind: PersistentVolumeClaim
3
+ metadata:
4
+ name: redis-pvc
5
+ labels:
6
+ app: redis
7
+ spec:
8
+ accessModes:
9
+ - ReadWriteOnce
10
+ resources:
11
+ requests:
12
+ storage: 1Gi
@@ -0,0 +1,15 @@
1
+ apiVersion: v1
2
+ kind: Service
3
+ metadata:
4
+ name: redis
5
+ labels:
6
+ app: redis
7
+ spec:
8
+ type: ClusterIP
9
+ ports:
10
+ - port: 6379
11
+ targetPort: 6379
12
+ protocol: TCP
13
+ name: redis
14
+ selector:
15
+ app: redis
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "redis",
3
+ "description": "In-memory data store for caching and sessions",
4
+ "version": "1.0.0",
5
+ "port": 6379,
6
+ "url": "redis://localhost:6379",
7
+
8
+ "files": {
9
+ "compose/docker-compose.yml": "docker-compose.redis.yml",
10
+ "compose/docker-compose.prod.yml": "docker-compose.redis.prod.yml",
11
+ "k8s/": "k8s/base/redis/",
12
+ "docs/integration.md": "redis-integration.md"
13
+ },
14
+
15
+ "envVars": {
16
+ "REDIS_PASSWORD": { "generate": "password", "length": 32 }
17
+ },
18
+
19
+ "kustomization": {
20
+ "entry": "redis/"
21
+ },
22
+
23
+ "credentials": {
24
+ "title": "Redis",
25
+ "fields": [
26
+ { "label": "Host", "value": "localhost:6379" },
27
+ { "label": "Credentials", "value": "Stored in .env.local (REDIS_PASSWORD)" }
28
+ ]
29
+ }
30
+ }
@@ -0,0 +1,86 @@
1
+ # S3 HA Storage Backend Configuration
2
+ # Overlay for Supabase Storage with cross-region replication via rclone
3
+ #
4
+ # Usage:
5
+ # docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.s3-ha.yml up -d
6
+ #
7
+ # Required environment variables in .env:
8
+ # S3_ACCESS_KEY - Hetzner S3 access key
9
+ # S3_SECRET_KEY - Hetzner S3 secret key
10
+ # S3_PRIMARY_BUCKET - Primary region bucket name
11
+ # S3_STANDBY_BUCKET - Standby region bucket name
12
+ # S3_PRIMARY_ENDPOINT - Primary region endpoint
13
+ # S3_STANDBY_ENDPOINT - Standby region endpoint
14
+ # S3_PRIMARY_REGION - Primary region (e.g., fsn1)
15
+ # S3_STANDBY_REGION - Standby region (e.g., hel1)
16
+ # S3_SYNC_INTERVAL - Sync interval in minutes (default: 5)
17
+
18
+ services:
19
+ storage:
20
+ environment:
21
+ # Override storage backend from 'file' to 's3'
22
+ STORAGE_BACKEND: s3
23
+ # S3 bucket configuration (uses primary bucket)
24
+ GLOBAL_S3_BUCKET: ${S3_PRIMARY_BUCKET}
25
+ GLOBAL_S3_ENDPOINT: ${S3_PRIMARY_ENDPOINT}
26
+ GLOBAL_S3_FORCE_PATH_STYLE: "true"
27
+ REGION: ${S3_PRIMARY_REGION}
28
+ # S3 credentials
29
+ AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY}
30
+ AWS_SECRET_ACCESS_KEY: ${S3_SECRET_KEY}
31
+
32
+ imgproxy:
33
+ environment:
34
+ # Enable S3 backend for image transformations
35
+ IMGPROXY_USE_S3: "true"
36
+ AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY}
37
+ AWS_SECRET_ACCESS_KEY: ${S3_SECRET_KEY}
38
+ AWS_REGION: ${S3_PRIMARY_REGION}
39
+ IMGPROXY_S3_ENDPOINT: ${S3_PRIMARY_ENDPOINT}
40
+
41
+ # Cross-region S3 synchronization service
42
+ s3-sync:
43
+ image: rclone/rclone:latest
44
+ restart: unless-stopped
45
+ environment:
46
+ # Primary bucket configuration
47
+ RCLONE_CONFIG_PRIMARY_TYPE: s3
48
+ RCLONE_CONFIG_PRIMARY_PROVIDER: Other
49
+ RCLONE_CONFIG_PRIMARY_ACCESS_KEY_ID: ${S3_ACCESS_KEY}
50
+ RCLONE_CONFIG_PRIMARY_SECRET_ACCESS_KEY: ${S3_SECRET_KEY}
51
+ RCLONE_CONFIG_PRIMARY_ENDPOINT: ${S3_PRIMARY_ENDPOINT}
52
+ RCLONE_CONFIG_PRIMARY_ACL: private
53
+ # Standby bucket configuration
54
+ RCLONE_CONFIG_STANDBY_TYPE: s3
55
+ RCLONE_CONFIG_STANDBY_PROVIDER: Other
56
+ RCLONE_CONFIG_STANDBY_ACCESS_KEY_ID: ${S3_ACCESS_KEY}
57
+ RCLONE_CONFIG_STANDBY_SECRET_ACCESS_KEY: ${S3_SECRET_KEY}
58
+ RCLONE_CONFIG_STANDBY_ENDPOINT: ${S3_STANDBY_ENDPOINT}
59
+ RCLONE_CONFIG_STANDBY_ACL: private
60
+ command: |
61
+ sh -c '
62
+ echo "Starting S3 cross-region sync..."
63
+ echo "Primary: ${S3_PRIMARY_BUCKET} @ ${S3_PRIMARY_ENDPOINT}"
64
+ echo "Standby: ${S3_STANDBY_BUCKET} @ ${S3_STANDBY_ENDPOINT}"
65
+ echo "Sync interval: ${S3_SYNC_INTERVAL:-5} minutes"
66
+ while true; do
67
+ echo "[$(date)] Starting sync from primary to standby..."
68
+ rclone sync primary:${S3_PRIMARY_BUCKET} standby:${S3_STANDBY_BUCKET} \
69
+ --transfers 8 \
70
+ --checkers 16 \
71
+ --fast-list \
72
+ --stats 30s \
73
+ --stats-one-line
74
+ echo "[$(date)] Sync complete. Sleeping for ${S3_SYNC_INTERVAL:-5} minutes..."
75
+ sleep ${S3_SYNC_INTERVAL:-5}m
76
+ done
77
+ '
78
+ healthcheck:
79
+ test: ["CMD", "rclone", "version"]
80
+ interval: 60s
81
+ timeout: 10s
82
+ retries: 3
83
+ deploy:
84
+ resources:
85
+ limits:
86
+ memory: 256M
@@ -0,0 +1,35 @@
1
+ # S3 Storage Backend Configuration
2
+ # Overlay for Supabase Storage to use Hetzner Object Storage (S3-compatible)
3
+ #
4
+ # Usage:
5
+ # docker compose -f docker-compose.yml -f docker-compose.s3.yml up -d
6
+ #
7
+ # Required environment variables in .env:
8
+ # S3_ACCESS_KEY - Hetzner S3 access key
9
+ # S3_SECRET_KEY - Hetzner S3 secret key
10
+ # S3_BUCKET - S3 bucket name
11
+ # S3_ENDPOINT - S3 endpoint URL (e.g., https://fsn1.your-objectstorage.com)
12
+ # S3_REGION - S3 region (e.g., fsn1)
13
+
14
+ services:
15
+ storage:
16
+ environment:
17
+ # Override storage backend from 'file' to 's3'
18
+ STORAGE_BACKEND: s3
19
+ # S3 bucket configuration
20
+ GLOBAL_S3_BUCKET: ${S3_BUCKET}
21
+ GLOBAL_S3_ENDPOINT: ${S3_ENDPOINT}
22
+ GLOBAL_S3_FORCE_PATH_STYLE: "true"
23
+ REGION: ${S3_REGION}
24
+ # S3 credentials
25
+ AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY}
26
+ AWS_SECRET_ACCESS_KEY: ${S3_SECRET_KEY}
27
+
28
+ imgproxy:
29
+ environment:
30
+ # Enable S3 backend for image transformations
31
+ IMGPROXY_USE_S3: "true"
32
+ AWS_ACCESS_KEY_ID: ${S3_ACCESS_KEY}
33
+ AWS_SECRET_ACCESS_KEY: ${S3_SECRET_KEY}
34
+ AWS_REGION: ${S3_REGION}
35
+ IMGPROXY_S3_ENDPOINT: ${S3_ENDPOINT}
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "s3",
3
+ "displayName": "Hetzner S3 Object Storage",
4
+ "description": "S3-compatible object storage for Supabase file storage backend",
5
+ "version": "1.0.0",
6
+ "type": "infrastructure",
7
+ "requiresCredentials": true,
8
+
9
+ "envVars": {
10
+ "S3_ACCESS_KEY": {
11
+ "prompt": true,
12
+ "secure": true,
13
+ "description": "Hetzner S3 access key"
14
+ },
15
+ "S3_SECRET_KEY": {
16
+ "prompt": true,
17
+ "secure": true,
18
+ "description": "Hetzner S3 secret key"
19
+ },
20
+ "S3_BUCKET": {
21
+ "generate": "from-project-name",
22
+ "description": "S3 bucket name"
23
+ },
24
+ "S3_ENDPOINT": {
25
+ "generate": "from-region",
26
+ "description": "S3 endpoint URL"
27
+ },
28
+ "S3_REGION": {
29
+ "prompt": true,
30
+ "options": ["fsn1", "nbg1", "hel1"],
31
+ "default": "fsn1",
32
+ "description": "S3 storage region"
33
+ }
34
+ },
35
+
36
+ "haEnvVars": {
37
+ "S3_PRIMARY_BUCKET": {
38
+ "generate": "from-project-name-primary",
39
+ "description": "Primary region bucket name"
40
+ },
41
+ "S3_STANDBY_BUCKET": {
42
+ "generate": "from-project-name-standby",
43
+ "description": "Standby region bucket name"
44
+ },
45
+ "S3_PRIMARY_ENDPOINT": {
46
+ "generate": "from-region",
47
+ "description": "Primary region endpoint"
48
+ },
49
+ "S3_STANDBY_ENDPOINT": {
50
+ "generate": "from-region",
51
+ "description": "Standby region endpoint"
52
+ },
53
+ "S3_PRIMARY_REGION": {
54
+ "prompt": true,
55
+ "options": ["fsn1", "nbg1", "hel1"],
56
+ "default": "fsn1",
57
+ "description": "Primary storage region"
58
+ },
59
+ "S3_STANDBY_REGION": {
60
+ "prompt": true,
61
+ "options": ["fsn1", "nbg1", "hel1"],
62
+ "default": "hel1",
63
+ "description": "Standby storage region"
64
+ },
65
+ "S3_SYNC_INTERVAL": {
66
+ "default": "5",
67
+ "description": "Cross-region sync interval in minutes"
68
+ }
69
+ },
70
+
71
+ "compose": {
72
+ "standard": "compose/docker-compose.s3.yml",
73
+ "ha": "compose/docker-compose.s3-ha.yml"
74
+ },
75
+
76
+ "instructions": {
77
+ "title": "Hetzner Object Storage Setup",
78
+ "url": "https://console.hetzner.cloud/",
79
+ "steps": [
80
+ "Go to https://console.hetzner.cloud/",
81
+ "Select your project (or create one)",
82
+ "Click 'Object Storage' in the sidebar",
83
+ "Click 'Create Credentials'",
84
+ "Copy the Access Key and Secret Key (secret shown only once!)"
85
+ ]
86
+ }
87
+ }