feat: Docker secrets support for ResetData API key - Critical for WHOOSH scaling integration #5
							
								
								
									
										42
									
								
								Dockerfile.simple
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								Dockerfile.simple
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | # CHORUS - Simple Docker image using pre-built binary | ||||||
|  | FROM alpine:3.18 | ||||||
|  |  | ||||||
|  | # Install runtime dependencies | ||||||
|  | RUN apk --no-cache add \ | ||||||
|  |     ca-certificates \ | ||||||
|  |     tzdata \ | ||||||
|  |     curl | ||||||
|  |  | ||||||
|  | # Create non-root user for security | ||||||
|  | RUN addgroup -g 1000 chorus && \ | ||||||
|  |     adduser -u 1000 -G chorus -s /bin/sh -D chorus | ||||||
|  |  | ||||||
|  | # Create application directories | ||||||
|  | RUN mkdir -p /app/data && \ | ||||||
|  |     chown -R chorus:chorus /app | ||||||
|  |  | ||||||
|  | # Copy pre-built binary | ||||||
|  | COPY chorus-agent /app/chorus-agent | ||||||
|  | RUN chmod +x /app/chorus-agent && chown chorus:chorus /app/chorus-agent | ||||||
|  |  | ||||||
|  | # Switch to non-root user | ||||||
|  | USER chorus | ||||||
|  | WORKDIR /app | ||||||
|  |  | ||||||
|  | # Expose ports | ||||||
|  | EXPOSE 8080 8081 9000 | ||||||
|  |  | ||||||
|  | # Health check | ||||||
|  | HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ | ||||||
|  |     CMD curl -f http://localhost:8081/health || exit 1 | ||||||
|  |  | ||||||
|  | # Set default environment variables | ||||||
|  | ENV LOG_LEVEL=info \ | ||||||
|  |     LOG_FORMAT=structured \ | ||||||
|  |     CHORUS_BIND_ADDRESS=0.0.0.0 \ | ||||||
|  |     CHORUS_API_PORT=8080 \ | ||||||
|  |     CHORUS_HEALTH_PORT=8081 \ | ||||||
|  |     CHORUS_P2P_PORT=9000 | ||||||
|  |  | ||||||
|  | # Start CHORUS | ||||||
|  | ENTRYPOINT ["/app/chorus-agent"] | ||||||
| @@ -2,7 +2,7 @@ version: "3.9" | |||||||
|  |  | ||||||
| services: | services: | ||||||
|   chorus: |   chorus: | ||||||
|     image: anthonyrawlins/chorus:backbeat-v2.0.1 |     image: anthonyrawlins/chorus:resetdata-secrets-v1.0.5 | ||||||
|      |      | ||||||
|     # REQUIRED: License configuration (CHORUS will not start without this) |     # REQUIRED: License configuration (CHORUS will not start without this) | ||||||
|     environment: |     environment: | ||||||
| @@ -28,7 +28,7 @@ services: | |||||||
|        |        | ||||||
|       # ResetData configuration (default provider) |       # ResetData configuration (default provider) | ||||||
|       - RESETDATA_BASE_URL=${RESETDATA_BASE_URL:-https://models.au-syd.resetdata.ai/v1} |       - RESETDATA_BASE_URL=${RESETDATA_BASE_URL:-https://models.au-syd.resetdata.ai/v1} | ||||||
|       - RESETDATA_API_KEY=${RESETDATA_API_KEY:?RESETDATA_API_KEY is required for resetdata provider} |       - RESETDATA_API_KEY_FILE=/run/secrets/resetdata_api_key | ||||||
|       - RESETDATA_MODEL=${RESETDATA_MODEL:-meta/llama-3.1-8b-instruct} |       - RESETDATA_MODEL=${RESETDATA_MODEL:-meta/llama-3.1-8b-instruct} | ||||||
|        |        | ||||||
|       # Ollama configuration (alternative provider) |       # Ollama configuration (alternative provider) | ||||||
| @@ -56,12 +56,13 @@ services: | |||||||
|     # Docker secrets for sensitive configuration |     # Docker secrets for sensitive configuration | ||||||
|     secrets: |     secrets: | ||||||
|       - chorus_license_id |       - chorus_license_id | ||||||
|  |       - resetdata_api_key | ||||||
|        |        | ||||||
|     # Persistent data storage |     # Persistent data storage | ||||||
|     volumes: |     volumes: | ||||||
|       - chorus_data:/app/data |       - chorus_data:/app/data | ||||||
|       # Mount prompts directory read-only for role YAMLs and defaults.md |       # Mount prompts directory read-only for role YAMLs and defaults.md | ||||||
|       - ../prompts:/etc/chorus/prompts:ro |       - /rust/containers/WHOOSH/prompts:/etc/chorus/prompts:ro | ||||||
|      |      | ||||||
|     # Network ports |     # Network ports | ||||||
|     ports: |     ports: | ||||||
| @@ -91,6 +92,7 @@ services: | |||||||
|       placement: |       placement: | ||||||
|         constraints: |         constraints: | ||||||
|           - node.hostname != rosewood |           - node.hostname != rosewood | ||||||
|  |           - node.hostname != acacia | ||||||
|         preferences: |         preferences: | ||||||
|           - spread: node.hostname |           - spread: node.hostname | ||||||
|       # CHORUS is internal-only, no Traefik labels needed |       # CHORUS is internal-only, no Traefik labels needed | ||||||
| @@ -120,7 +122,7 @@ services: | |||||||
|       start_period: 10s |       start_period: 10s | ||||||
|  |  | ||||||
|   whoosh: |   whoosh: | ||||||
|     image: anthonyrawlins/whoosh:backbeat-v2.1.0 |     image: anthonyrawlins/whoosh:scaling-v1.0.0 | ||||||
|     ports: |     ports: | ||||||
|       - target: 8080 |       - target: 8080 | ||||||
|         published: 8800 |         published: 8800 | ||||||
| @@ -163,6 +165,11 @@ services: | |||||||
|       WHOOSH_REDIS_PORT: 6379 |       WHOOSH_REDIS_PORT: 6379 | ||||||
|       WHOOSH_REDIS_PASSWORD_FILE: /run/secrets/redis_password |       WHOOSH_REDIS_PASSWORD_FILE: /run/secrets/redis_password | ||||||
|       WHOOSH_REDIS_DATABASE: 0 |       WHOOSH_REDIS_DATABASE: 0 | ||||||
|  |  | ||||||
|  |       # Scaling system configuration | ||||||
|  |       WHOOSH_SCALING_KACHING_URL: "https://kaching.chorus.services" | ||||||
|  |       WHOOSH_SCALING_BACKBEAT_URL: "http://backbeat-pulse:8080" | ||||||
|  |       WHOOSH_SCALING_CHORUS_URL: "http://chorus:8080" | ||||||
|     secrets: |     secrets: | ||||||
|       - whoosh_db_password |       - whoosh_db_password | ||||||
|       - gitea_token |       - gitea_token | ||||||
| @@ -170,6 +177,8 @@ services: | |||||||
|       - jwt_secret |       - jwt_secret | ||||||
|       - service_tokens |       - service_tokens | ||||||
|       - redis_password |       - redis_password | ||||||
|  |     volumes: | ||||||
|  |       - /var/run/docker.sock:/var/run/docker.sock | ||||||
|     deploy: |     deploy: | ||||||
|       replicas: 2 |       replicas: 2 | ||||||
|       restart_policy: |       restart_policy: | ||||||
| @@ -190,6 +199,8 @@ services: | |||||||
|       #   monitor: 60s |       #   monitor: 60s | ||||||
|       #   order: stop-first |       #   order: stop-first | ||||||
|       placement: |       placement: | ||||||
|  |         constraints: | ||||||
|  |           - node.hostname != acacia | ||||||
|         preferences: |         preferences: | ||||||
|           - spread: node.hostname |           - spread: node.hostname | ||||||
|       resources: |       resources: | ||||||
| @@ -522,6 +533,9 @@ secrets: | |||||||
|   chorus_license_id: |   chorus_license_id: | ||||||
|     external: true |     external: true | ||||||
|     name: chorus_license_id |     name: chorus_license_id | ||||||
|  |   resetdata_api_key: | ||||||
|  |     external: true | ||||||
|  |     name: resetdata_api_key | ||||||
|   whoosh_db_password: |   whoosh_db_password: | ||||||
|     external: true |     external: true | ||||||
|     name: whoosh_db_password |     name: whoosh_db_password | ||||||
|   | |||||||
| @@ -179,7 +179,7 @@ func LoadFromEnvironment() (*Config, error) { | |||||||
| 			}, | 			}, | ||||||
| 			ResetData: ResetDataConfig{ | 			ResetData: ResetDataConfig{ | ||||||
| 				BaseURL: getEnvOrDefault("RESETDATA_BASE_URL", "https://models.au-syd.resetdata.ai/v1"), | 				BaseURL: getEnvOrDefault("RESETDATA_BASE_URL", "https://models.au-syd.resetdata.ai/v1"), | ||||||
| 				APIKey:  os.Getenv("RESETDATA_API_KEY"), | 				APIKey:  getEnvOrFileContent("RESETDATA_API_KEY", "RESETDATA_API_KEY_FILE"), | ||||||
| 				Model:   getEnvOrDefault("RESETDATA_MODEL", "meta/llama-3.1-8b-instruct"), | 				Model:   getEnvOrDefault("RESETDATA_MODEL", "meta/llama-3.1-8b-instruct"), | ||||||
| 				Timeout: getEnvDurationOrDefault("RESETDATA_TIMEOUT", 30*time.Second), | 				Timeout: getEnvDurationOrDefault("RESETDATA_TIMEOUT", 30*time.Second), | ||||||
| 			}, | 			}, | ||||||
| @@ -363,3 +363,17 @@ func SaveConfig(cfg *Config, configPath string) error { | |||||||
| 	// For containers, configuration is environment-based, so this is a no-op | 	// For containers, configuration is environment-based, so this is a no-op | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // LoadRuntimeConfig loads configuration with runtime assignment support | ||||||
|  | func LoadRuntimeConfig() (*RuntimeConfig, error) { | ||||||
|  | 	// Load base configuration from environment | ||||||
|  | 	baseConfig, err := LoadFromEnvironment() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("failed to load base configuration: %w", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Create runtime configuration manager | ||||||
|  | 	runtimeConfig := NewRuntimeConfig(baseConfig) | ||||||
|  |  | ||||||
|  | 	return runtimeConfig, nil | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user