Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Extract common environment variables in Langfuse web/worker into a separate file #32

Merged
merged 1 commit into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions lib/constructs/services/common-environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Database } from '../database';
import { Cache } from '../cache';
import { ClickHouse } from './clickhouse';
import { LOG_LEVEL } from '../../stack-config';

export interface CommonEnvironmentProps {
logLevel: LOG_LEVEL;
database: Database;
cache: Cache;
clickhouse: ClickHouse;
bucket: s3.IBucket;
}

export class CommonEnvironment extends Construct {
public readonly commonEnvironment: { [key: string]: string };
public readonly commonSecrets: { [key: string]: ecs.Secret };
constructor(scope: Construct, id: string, props: CommonEnvironmentProps) {
super(scope, id);

const { logLevel, database, cache, clickhouse, bucket } = props;

/**
* Encryption Key and Salt for Langfuse Services
*/
const encryptionKey = new secretsmanager.Secret(this, 'EncryptionKey', {
generateSecretString: {
passwordLength: 64,
excludeCharacters: 'ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+=-[]{};:,.<>?/', // only 0-9, a-f used
excludePunctuation: true,
excludeUppercase: true,
requireEachIncludedType: false,
},
});

const salt = new secretsmanager.Secret(this, 'Salt', {
generateSecretString: {
passwordLength: 32,
excludePunctuation: true,
},
});

/**
* Common environment variables and secrest for Langfuse Web/Worker
* @see https://langfuse.com/self-hosting/configuration
*/
this.commonEnvironment = {
TELEMETRY_ENABLED: 'true',
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: 'true',
LANGFUSE_LOG_LEVEL: logLevel,

DATABASE_NAME: database.databaseName,

CLICKHOUSE_MIGRATION_URL: 'clickhouse://clickhouse-tcp.local:9000',
CLICKHOUSE_URL: 'http://clickhouse-http.local:8123',
CLICKHOUSE_USER: clickhouse.clickhouseUser,
CLICKHOUSE_CLUSTER_ENABLED: 'false',

LANGFUSE_S3_EVENT_UPLOAD_BUCKET: bucket.bucketName,
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: 'events/',
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: bucket.bucketName,
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: 'media/',
};

this.commonSecrets = {
SALT: ecs.Secret.fromSecretsManager(salt),
ENCRYPTION_KEY: ecs.Secret.fromSecretsManager(encryptionKey),

DATABASE_HOST: ecs.Secret.fromSecretsManager(database.secret, 'host'),
DATABASE_USERNAME: ecs.Secret.fromSecretsManager(database.secret, 'username'),
DATABASE_PASSWORD: ecs.Secret.fromSecretsManager(database.secret, 'password'),

REDIS_CONNECTION_STRING: ecs.Secret.fromSecretsManager(cache.connectionStringSecret),

CLICKHOUSE_PASSWORD: ecs.Secret.fromSecretsManager(clickhouse.clickhousePassword),
};
}
}
61 changes: 20 additions & 41 deletions lib/constructs/services/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Duration, RemovalPolicy } from 'aws-cdk-lib';
import { Cache } from '../cache';
import { Database } from '../database';
import { ClickHouse } from './clickhouse';
import { LOG_LEVEL } from '../../stack-config';
import { CommonEnvironment } from './common-environment';

export interface WebProps {
domainName?: string;
Expand All @@ -27,9 +27,7 @@ export interface WebProps {
taskDefMemoryLimitMiB?: number;
langfuseWebTaskCount?: number;
imageTag: string;
logLevel: LOG_LEVEL;
encryptionKey: secretsmanager.ISecret;
salt: secretsmanager.ISecret;
commonEnvironment: CommonEnvironment;

database: Database;
cache: Cache;
Expand All @@ -56,9 +54,7 @@ export class Web extends Construct {
taskDefMemoryLimitMiB,
langfuseWebTaskCount,
imageTag,
logLevel,
encryptionKey,
salt,
commonEnvironment,

database,
cache,
Expand Down Expand Up @@ -129,44 +125,27 @@ export class Web extends Construct {
},
});

/**
* Set environment variables and sectrets
* @see https://langfuse.com/self-hosting/configuration
*/
const environment = {
NEXTAUTH_URL: this.url,
HOSTNAME: '0.0.0.0',
...commonEnvironment.commonEnvironment,
};

const secrets = {
NEXTAUTH_SECRET: ecs.Secret.fromSecretsManager(nextAuthSecret),
...commonEnvironment.commonSecrets,
};

taskDefinition.addContainer('Container', {
image: ecs.ContainerImage.fromRegistry(`langfuse/langfuse:${imageTag}`),
portMappings: [{ containerPort: 3000, name: 'web' }],
logging: new ecs.AwsLogDriver({ streamPrefix: 'log' }),

// https://langfuse.com/self-hosting/configuration
environment: {
NEXTAUTH_URL: this.url,
TELEMETRY_ENABLED: 'true',
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: 'true',
HOSTNAME: '0.0.0.0',
LANGFUSE_LOG_LEVEL: logLevel,

DATABASE_NAME: database.databaseName,

CLICKHOUSE_MIGRATION_URL: 'clickhouse://clickhouse-tcp.local:9000',
CLICKHOUSE_URL: 'http://clickhouse-http.local:8123',
CLICKHOUSE_USER: clickhouse.clickhouseUser,
CLICKHOUSE_CLUSTER_ENABLED: 'false',

LANGFUSE_S3_EVENT_UPLOAD_BUCKET: bucket.bucketName,
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: 'events/',
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: bucket.bucketName,
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: 'media/',
},
secrets: {
NEXTAUTH_SECRET: ecs.Secret.fromSecretsManager(nextAuthSecret),
SALT: ecs.Secret.fromSecretsManager(salt),
ENCRYPTION_KEY: ecs.Secret.fromSecretsManager(encryptionKey),

DATABASE_HOST: ecs.Secret.fromSecretsManager(database.secret, 'host'),
DATABASE_USERNAME: ecs.Secret.fromSecretsManager(database.secret, 'username'),
DATABASE_PASSWORD: ecs.Secret.fromSecretsManager(database.secret, 'password'),

REDIS_CONNECTION_STRING: ecs.Secret.fromSecretsManager(cache.connectionStringSecret),

CLICKHOUSE_PASSWORD: ecs.Secret.fromSecretsManager(clickhouse.clickhousePassword),
},
environment,
secrets,
healthCheck: {
command: ['CMD-SHELL', 'wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1'],
interval: Duration.seconds(15),
Expand Down
56 changes: 17 additions & 39 deletions lib/constructs/services/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,19 @@ import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import { Duration } from 'aws-cdk-lib';
import { Database } from '../database';
import { Cache } from '../cache';
import { ClickHouse } from './clickhouse';
import { LOG_LEVEL } from '../../stack-config';
import { CommonEnvironment } from './common-environment';

export interface WorkerProps {
cluster: ecs.ICluster;
enableFargateSpot?: boolean;
taskDefCpu?: number;
taskDefMemoryLimitMiB?: number;
imageTag: string;
logLevel: LOG_LEVEL;
encryptionKey: secretsmanager.ISecret;
salt: secretsmanager.ISecret;
commonEnvironment: CommonEnvironment;

database: Database;
cache: Cache;
Expand All @@ -35,9 +32,7 @@ export class Worker extends Construct {
taskDefCpu,
taskDefMemoryLimitMiB,
imageTag,
logLevel,
encryptionKey,
salt,
commonEnvironment,

database,
cache,
Expand All @@ -51,41 +46,24 @@ export class Worker extends Construct {
runtimePlatform: { cpuArchitecture: ecs.CpuArchitecture.X86_64 },
});

/**
* Set environment variables and sectrets
* @see https://langfuse.com/self-hosting/configuration
*/
const environment = {
...commonEnvironment.commonEnvironment,
};

const secrets = {
...commonEnvironment.commonSecrets,
};

taskDefinition.addContainer('Container', {
image: ecs.ContainerImage.fromRegistry(`langfuse/langfuse-worker:${imageTag}`),
portMappings: [{ containerPort: 3030, name: 'worker' }],
logging: new ecs.AwsLogDriver({ streamPrefix: 'log' }),

// https://langfuse.com/self-hosting/configuration
environment: {
TELEMETRY_ENABLED: 'true',
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: 'true',
LANGFUSE_LOG_LEVEL: logLevel,

DATABASE_NAME: database.databaseName,

CLICKHOUSE_MIGRATION_URL: 'clickhouse://clickhouse-tcp.local:9000',
CLICKHOUSE_URL: 'http://clickhouse-http.local:8123',
CLICKHOUSE_USER: clickhouse.clickhouseUser,
CLICKHOUSE_CLUSTER_ENABLED: 'false',

LANGFUSE_S3_EVENT_UPLOAD_BUCKET: bucket.bucketName,
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: 'events/',
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: bucket.bucketName,
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: 'media/',
},
secrets: {
SALT: ecs.Secret.fromSecretsManager(salt),
ENCRYPTION_KEY: ecs.Secret.fromSecretsManager(encryptionKey),

DATABASE_HOST: ecs.Secret.fromSecretsManager(database.secret, 'host'),
DATABASE_USERNAME: ecs.Secret.fromSecretsManager(database.secret, 'username'),
DATABASE_PASSWORD: ecs.Secret.fromSecretsManager(database.secret, 'password'),

REDIS_CONNECTION_STRING: ecs.Secret.fromSecretsManager(cache.connectionStringSecret),

CLICKHOUSE_PASSWORD: ecs.Secret.fromSecretsManager(clickhouse.clickhousePassword),
},
environment,
secrets,
healthCheck: {
command: ['CMD-SHELL', 'wget --no-verbose --tries=1 --spider http://localhost:3030/ || exit 1'],
interval: Duration.seconds(15),
Expand Down
34 changes: 9 additions & 25 deletions lib/langfuse-with-aws-cdk-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';

import { Construct } from 'constructs';
import { Web } from './constructs/services/web';
Expand All @@ -12,6 +11,7 @@ import { Cache } from './constructs/cache';
import { ClickHouse } from './constructs/services/clickhouse';
import { LOG_LEVEL, StackConfig, getStackConfig } from './stack-config';
import { Bastion } from './constructs/bastion';
import { CommonEnvironment } from './constructs/services/common-environment';

export interface LangfuseWithAwsCdkStackProps extends cdk.StackProps {
envName: string;
Expand Down Expand Up @@ -113,24 +113,12 @@ export class LangfuseWithAwsCdkStack extends cdk.Stack {
imageTag: clickhouseImageTag,
});

/**
* Encryption Key and Salt for Langfuse Services
*/
const encryptionKey = new secretsmanager.Secret(this, 'EncryptionKey', {
generateSecretString: {
passwordLength: 64,
excludeCharacters: 'ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+=-[]{};:,.<>?/', // only 0-9, a-f used
excludePunctuation: true,
excludeUppercase: true,
requireEachIncludedType: false,
},
});

const salt = new secretsmanager.Secret(this, 'Salt', {
generateSecretString: {
passwordLength: 32,
excludePunctuation: true,
},
const commonEnvironment = new CommonEnvironment(this, 'CommonEnvironment', {
logLevel: langfuseLogLvel,
database,
cache,
clickhouse,
bucket: langfuseBucket,
});

/**
Expand All @@ -148,9 +136,7 @@ export class LangfuseWithAwsCdkStack extends cdk.Stack {
taskDefMemoryLimitMiB: stackConfig.taskDefMemoryLimitMiB,
langfuseWebTaskCount: stackConfig.langfuseWebTaskCount,
imageTag: langfuseImageTag,
logLevel: langfuseLogLvel,
encryptionKey,
salt,
commonEnvironment,
database,
cache,
clickhouse,
Expand All @@ -166,9 +152,7 @@ export class LangfuseWithAwsCdkStack extends cdk.Stack {
taskDefCpu: stackConfig.taskDefCpu,
taskDefMemoryLimitMiB: stackConfig.taskDefMemoryLimitMiB,
imageTag: langfuseImageTag,
logLevel: langfuseLogLvel,
encryptionKey,
salt,
commonEnvironment,
database,
cache,
clickhouse,
Expand Down
2 changes: 1 addition & 1 deletion lib/stack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ const stackConfigMap: Record<string, StackConfig> = {
langfuseWebTaskCount: 2,
createBastion: true,
langfuseLogLevel: LOG_LEVEL.INFO,
langfuseImageTag: 'latest',
langfuseImageTag: '3.26',
auroraScalesToZero: false,
cacheMultiAz: false,
},
Expand Down
Loading