Skip to content

Commit 9ebe505

Browse files
authored
Merge pull request #26 from UXcaptain/refactor-aws-s3-to-minio
REPLACE S3 storage from cloud AWS to self-hosted minIO
2 parents d88d7de + 19d6f37 commit 9ebe505

6 files changed

Lines changed: 72 additions & 61 deletions

File tree

.env.example

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ PORT=3000
2121

2222
AWS_SECRET_ACCESS_KEY=
2323
AWS_ACCESS_KEY_ID=
24-
AWS_REGION=
25-
AWS_BUCKET=
26-
TRANSCRIPTION_ENABLED=
24+
S3_REGION=
25+
S3_BUCKET=
26+
S3_ENDPOINT=
27+
28+
TRANSCRIPTION_ENABLED=
29+
30+
MINIO_ROOT_USER=
31+
MINIO_ROOT_PASSWORD=

.kilocode/rules/memory-bank/tech.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ PRISMA_POSTGRES_CONNECTION_STRING=postgresql://user:password@localhost:5432/uxca
8989
# AWS S3
9090
AWS_ACCESS_KEY_ID=your-access-key
9191
AWS_SECRET_ACCESS_KEY=your-secret-key
92-
AWS_REGION=eu-west-3
93-
AWS_BUCKET=your-bucket-name
92+
S3_REGION=eu-west-3
93+
S3_BUCKET=your-bucket-name
9494

9595
# Stripe
9696
STRIPE_API_KEY=sk_test_...

compose.yaml

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,56 @@
11
name: uxcaptain
22
services:
3-
server:
4-
container_name: server
5-
build:
6-
context: .
7-
dockerfile: Dockerfile.dev
8-
environment:
9-
NODE_ENV: ${NODE_ENV}
10-
DEPLOY_ENVIRONMENT: ${DEPLOY_ENVIRONMENT}
11-
POSTHOG_API_KEY: ${POSTHOG_API_KEY}
12-
SESSION_SECRET: ${SESSION_SECRET}
13-
BREVO_API_KEY: ${BREVO_API_KEY}
14-
PRISMA_POSTGRES_DIRECT_URL: ${PRISMA_POSTGRES_DIRECT_URL}
15-
PRISMA_POSTGRES_CONNECTION_STRING: ${PRISMA_POSTGRES_CONNECTION_STRING}
16-
TELEGRAM_BOT_API_KEY: ${TELEGRAM_BOT_API_KEY}
17-
FRONT_WEB_APP_ORIGIN_URL: ${FRONT_WEB_APP_ORIGIN_URL}
18-
STRIPE_API_KEY: ${STRIPE_API_KEY}
19-
STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET}
20-
PORT: ${PORT}
21-
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
22-
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
23-
AWS_BUCKET: dev-analysis-entry-storage
24-
AWS_REGION: ${AWS_REGION}
3+
# server:
4+
# container_name: server
5+
# build:
6+
# context: .
7+
# dockerfile: Dockerfile.dev
8+
# environment:
9+
# NODE_ENV: ${NODE_ENV}
10+
# DEPLOY_ENVIRONMENT: ${DEPLOY_ENVIRONMENT}
11+
# POSTHOG_API_KEY: ${POSTHOG_API_KEY}
12+
# SESSION_SECRET: ${SESSION_SECRET}
13+
# BREVO_API_KEY: ${BREVO_API_KEY}
14+
# PRISMA_POSTGRES_DIRECT_URL: ${PRISMA_POSTGRES_DIRECT_URL}
15+
# PRISMA_POSTGRES_CONNECTION_STRING: ${PRISMA_POSTGRES_CONNECTION_STRING}
16+
# TELEGRAM_BOT_API_KEY: ${TELEGRAM_BOT_API_KEY}
17+
# FRONT_WEB_APP_ORIGIN_URL: ${FRONT_WEB_APP_ORIGIN_URL}
18+
# STRIPE_API_KEY: ${STRIPE_API_KEY}
19+
# STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET}
20+
# PORT: ${PORT}
21+
# AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
22+
# AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
23+
# S3_BUCKET: dev-analysis-entry-storage
24+
# S3_REGION: ${S3_REGION}
2525

26+
# ports:
27+
# - 3000:3000
28+
# develop:
29+
# watch:
30+
# - path: .
31+
# action: sync+restart #* Synchronize code changes and restart the server
32+
# target: /usr/src/app/
33+
# depends_on: #* References the SERVICE name - NOT the container_name
34+
# database:
35+
# condition: service_started
36+
# minio:
37+
# condition: service_started
38+
# networks:
39+
# - uxcaptain-network
40+
41+
minio:
42+
image: minio/minio:latest
43+
container_name: minio
44+
restart: on-failure
45+
environment:
46+
- MINIO_ROOT_USER=${MINIO_ROOT_USER}
47+
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
48+
volumes:
49+
- /Users/martaperezsanchez/repos/minio:/data
2650
ports:
27-
- 3000:3000
28-
develop:
29-
watch:
30-
- path: .
31-
action: sync+restart #* Synchronize code changes and restart the server
32-
target: /usr/src/app/
33-
depends_on: #* References the SERVICE name - NOT the container_name
34-
database:
35-
condition: service_started
51+
- 9000:9000
52+
- 9001:9001
53+
command: server /data --console-address ":9001"
3654
networks:
3755
- uxcaptain-network
3856

server/controllers/analysisEntryController.js

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { generateS3GetPresignedUrl, generateS3PutPresignedUrl } from '../integrations/aws/s3.js';
1+
import { generateS3GetPresignedUrl } from '../integrations/aws/s3.js';
22
import { createAnalysisEntryInDb, getAnalysisEntryDetailsById, markAnalysisEntryAsSubmitted } from '../models/analysisEntryModel.js';
33
import { processTranscriptionRequest } from '../services/analysisService.js';
44

@@ -71,17 +71,3 @@ export const getAnalysisEntryDetails = async (req, res) => {
7171
transcriptionSegments: analysisEntryDetails.transcription_segments,
7272
});
7373
};
74-
75-
export const getAnalysisEntryPresignedUploadUrl = async (req, res) => {
76-
const { analysisEntryId, analysisId } = req.body;
77-
78-
const key = `analysis/${analysisId}/${analysisEntryId}/recording.mp4`;
79-
80-
const analysisEntryPresignedUrl = await generateS3PutPresignedUrl(key);
81-
82-
return res.status(200).json({
83-
success: true,
84-
message: 'PresignedUploadUrl retrieved successfully',
85-
analysisEntryPresignedUploadUrl: analysisEntryPresignedUrl,
86-
});
87-
};

server/integrations/aws/Transcribe.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ import {
77
import { getS3Object } from './s3.js';
88
import { logInfo } from '../../config/loggerFunctions.js';
99

10-
const transcribeClient = new TranscribeClient({ region: process.env.AWS_REGION });
10+
const transcribeClient = new TranscribeClient({ region: process.env.S3_REGION });
1111

1212
export const requestAnalysisEntryTranscriptionToAWSTranscribe = async (transcriptionRequest) => {
1313
const command = new StartTranscriptionJobCommand({
1414
TranscriptionJobName: transcriptionRequest.analysisEntryId,
1515
LanguageCode: transcriptionRequest.languageCode,
1616
Media: {
17-
MediaFileUri: `s3://${process.env.AWS_BUCKET}/analysis/${transcriptionRequest.analysisId}/${transcriptionRequest.analysisEntryId}/recording.mp4`,
17+
MediaFileUri: `s3://${process.env.S3_BUCKET}/analysis/${transcriptionRequest.analysisId}/${transcriptionRequest.analysisEntryId}/recording.mp4`,
1818
},
19-
OutputBucketName: process.env.AWS_BUCKET,
19+
OutputBucketName: process.env.S3_BUCKET,
2020
OutputKey: `analysis/${transcriptionRequest.analysisId}/${transcriptionRequest.analysisEntryId}/transcription.json`,
2121
});
2222

server/integrations/aws/s3.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3
22
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
33

44
export const s3client = new S3Client({
5-
region: process.env.AWS_REGION,
6-
credentials: { // https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/modules/credentials.html
7-
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
8-
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
5+
region: process.env.S3_REGION, // irrelevant since miniIO doesnt takei into account
6+
endpoint: process.env.S3_ENDPOINT, // Container network endpoint
7+
forcePathStyle: true, // Required for MinIO path-style URLs
8+
credentials: {
9+
accessKeyId: process.env.MINIO_ROOT_USER,
10+
secretAccessKey: process.env.MINIO_ROOT_PASSWORD,
911
},
1012
});
1113

1214
export const generateS3GetPresignedUrl = async (key) => {
1315
const command = new GetObjectCommand({
14-
Bucket: process.env.AWS_BUCKET,
16+
Bucket: process.env.S3_BUCKET,
1517
Key: key,
1618
});
1719

@@ -22,7 +24,7 @@ export const generateS3GetPresignedUrl = async (key) => {
2224

2325
export const generateS3PutPresignedUrl = async (key) => {
2426
const command = new PutObjectCommand({
25-
Bucket: process.env.AWS_BUCKET,
27+
Bucket: process.env.S3_BUCKET,
2628
Key: key,
2729
ContentType: 'video/mp4',
2830
});
@@ -36,7 +38,7 @@ export const generateS3PutPresignedUrl = async (key) => {
3638

3739
export const getS3Object = async (key) => {
3840
const command = new GetObjectCommand({
39-
Bucket: process.env.AWS_BUCKET,
41+
Bucket: process.env.S3_BUCKET,
4042
Key: key,
4143
});
4244

0 commit comments

Comments
 (0)