directlx-claude-config/plans/cozy-stargazing-lobster.md

28 KiB

HiveOps Config Server Implementation Plan

Context

This plan addresses the implementation of a centralized configuration server (hiveops-config) for the HiveOps microservices ecosystem. The goal is to provide externalized, version-controlled configuration management using Spring Cloud Config Server.

Motivation: Currently, each microservice (hiveops-mgmt, hiveops-auth, hiveops-incident) manages its configuration independently through application.yml files and environment variables. This creates challenges:

  • Configuration drift between environments (dev, staging, prod)
  • No centralized view of all service configurations
  • Difficult to audit configuration changes
  • No version control for configuration history
  • Shared settings (like JWT secrets) duplicated across services

Solution: Implement Spring Cloud Config Server to centralize configuration in a Git repository with environment-specific profiles, enabling version control, audit trails, and consistent configuration across all services.

Existing Microservices:

  • hiveops-mgmt (port 8080): License management, internal user authentication
  • hiveops-incident (port 8081): Incident management and workflow
  • hiveops-auth (port 8082): Customer authentication with MFA

New Service:

  • hiveops-config (port 8083): Centralized configuration server

Architecture Decision

Spring Cloud Config Server with Git Backend

Approach: Centralized configuration with local/remote Git repository storage

Configuration Flow:
  Git Repository (config-repo/)
    ├── application.yml              # Shared defaults
    ├── hiveops-mgmt.yml            # mgmt-specific config
    ├── hiveops-mgmt-dev.yml        # mgmt dev profile
    ├── hiveops-mgmt-prod.yml       # mgmt prod profile
    ├── hiveops-auth.yml            # auth-specific config
    ├── hiveops-auth-dev.yml        # auth dev profile
    ├── hiveops-auth-prod.yml       # auth prod profile
    ├── hiveops-incident.yml        # incident-specific config
    ├── hiveops-incident-dev.yml    # incident dev profile
    └── hiveops-incident-prod.yml   # incident prod profile
          ↓
  hiveops-config (Spring Cloud Config Server)
    - Serves configuration over HTTP
    - Port 8083
    - Secure endpoints with HTTP Basic Auth
    - Health checks and monitoring
          ↓
  Client Services (mgmt, incident, auth)
    - Bootstrap phase: connect to config server
    - Load configuration before application startup
    - Support for config refresh without restart (@RefreshScope)

Benefits:

  • Version control for all configurations (Git history)
  • Environment-specific profiles (dev, prod, staging)
  • Centralized security settings
  • Dynamic configuration updates without redeployment
  • Audit trail via Git commits
  • Easy rollback to previous configurations
  • Shared configuration elimination (e.g., JWT secrets defined once)

Project Structure

hiveops-config/
├── src/main/
│   ├── java/com/hiveops/config/
│   │   ├── HiveopsConfigServerApplication.java  # Main class with @EnableConfigServer
│   │   └── config/
│   │       └── SecurityConfig.java              # HTTP Basic Auth for config endpoints
│   │
│   └── resources/
│       ├── application.yml                       # Config server settings (dev)
│       └── application-prod.yml                  # Prod profile (remote git)
│
├── config-repo/                                  # Local Git repository for configurations
│   ├── application.yml                           # Shared defaults
│   ├── hiveops-mgmt.yml
│   ├── hiveops-mgmt-dev.yml
│   ├── hiveops-mgmt-prod.yml
│   ├── hiveops-auth.yml
│   ├── hiveops-auth-dev.yml
│   ├── hiveops-auth-prod.yml
│   ├── hiveops-incident.yml
│   ├── hiveops-incident-dev.yml
│   ├── hiveops-incident-prod.yml
│   └── .gitignore
│
├── devops-scripts/
│   ├── build-and-push.sh
│   ├── deploy.sh
│   └── docker/
│       └── .env.example
│
├── Dockerfile                                    # Multi-stage Alpine build
├── docker-compose.yml                            # Dev environment
├── docker-compose.prod.yml                       # Prod deployment
├── pom.xml
└── README.md

Spring Cloud Config Server Implementation

Key Dependencies (pom.xml)

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.4.1</version>
</parent>

<properties>
    <java.version>21</java.version>
    <spring-cloud.version>2023.0.3</spring-cloud.version>
</properties>

<dependencies>
    <!-- Spring Cloud Config Server -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>

    <!-- Spring Boot Actuator (health checks) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <!-- Spring Security (HTTP Basic Auth) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <!-- Testing -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Main Application Class

package com.hiveops.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class HiveopsConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(HiveopsConfigServerApplication.class, args);
    }
}

Security Configuration (HTTP Basic Auth)

package com.hiveops.config.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Value("${config.security.username}")
    private String username;

    @Value("${config.security.password}")
    private String password;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/actuator/health", "/actuator/info").permitAll()
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults())
            .csrf(csrf -> csrf.disable());

        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.builder()
            .username(username)
            .password(passwordEncoder().encode(password))
            .roles("CONFIG_CLIENT")
            .build();

        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Config Server Configuration (application.yml)

server:
  port: 8083

spring:
  application:
    name: hiveops-config-server

  cloud:
    config:
      server:
        git:
          uri: file://${user.dir}/config-repo  # Dev: local repo
          default-label: main
          clone-on-start: true
          force-pull: true

# Security credentials
config:
  security:
    username: ${CONFIG_USERNAME:config-user}
    password: ${CONFIG_PASSWORD:changeme}

# Actuator endpoints
management:
  endpoints:
    web:
      exposure:
        include: health,info,env,refresh
  endpoint:
    health:
      show-details: always

# Logging
logging:
  level:
    root: INFO
    org.springframework.cloud.config: DEBUG

Production Configuration (application-prod.yml)

spring:
  cloud:
    config:
      server:
        git:
          uri: ${GIT_REPO_URL}  # Remote git repository URL
          username: ${GIT_USERNAME}
          password: ${GIT_PASSWORD}
          default-label: main
          clone-on-start: true
          force-pull: true
          timeout: 10

# Security (from environment variables)
config:
  security:
    username: ${CONFIG_USERNAME}
    password: ${CONFIG_PASSWORD}

Configuration Repository Structure

Naming Convention

Spring Cloud Config uses this pattern:

{application}-{profile}.yml

Where:

  • {application} = spring.application.name from client service
  • {profile} = spring.profiles.active from client service

Example Configurations

application.yml (shared across all services):

# Shared configuration for all HiveOps microservices

logging:
  level:
    root: INFO
    com.hiveops: DEBUG
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n"

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  endpoint:
    health:
      show-details: when-authorized

hiveops-auth-prod.yml (auth service production config):

server:
  port: 8082

spring:
  datasource:
    url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:hiveops_auth}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

# JWT Configuration (shared secret with other services)
jwt:
  secret: ${JWT_SECRET}
  expiration: 86400000
  refresh-expiration: 604800000

# MFA Configuration
mfa:
  secret-encryption-key: ${MFA_ENCRYPTION_KEY}
  totp-algorithm: SHA1
  totp-digits: 6
  totp-period: 30
  backup-code-count: 10

# Rate Limiting
rate-limit:
  ip:
    capacity: 20
    refill-tokens: 20
    refill-duration-minutes: 1
  user:
    capacity: 5
    refill-tokens: 5
    refill-duration-minutes: 15

Client Service Integration

Required Changes in Existing Services

For each service (hiveops-mgmt, hiveops-auth, hiveops-incident):

1. Add Dependencies to pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

2. Create bootstrap.yml (loaded before application.yml):

spring:
  application:
    name: hiveops-auth  # Change per service: hiveops-mgmt, hiveops-incident

  profiles:
    active: ${SPRING_PROFILES_ACTIVE:dev}

  cloud:
    config:
      uri: ${CONFIG_SERVER_URL:http://localhost:8083}
      username: ${CONFIG_USERNAME:config-user}
      password: ${CONFIG_PASSWORD:changeme}
      fail-fast: true  # Fail startup if config server unreachable
      retry:
        initial-interval: 1000
        max-interval: 2000
        max-attempts: 6

3. Configuration Migration Strategy:

  • Keep application.yml for local defaults (fallback when config server disabled)
  • Move environment-specific config to config-repo/{service}-{profile}.yml
  • Secrets remain in environment variables, referenced in config files

Docker Deployment

Dockerfile (Multi-Stage Alpine Build)

Following established HiveOps pattern:

# Build stage
FROM eclipse-temurin:21-jdk-alpine AS builder

WORKDIR /app

# Copy Maven files
COPY pom.xml .
COPY src ./src

# Build the application
RUN apk add --no-cache maven && \
    mvn clean package -DskipTests && \
    mv target/*.jar app.jar

# Runtime stage
FROM eclipse-temurin:21-jre-alpine

WORKDIR /app

# Create non-root user
RUN addgroup -S hiveops && adduser -S hiveops -G hiveops

# Copy JAR from builder
COPY --from=builder /app/app.jar .

# Copy config repository (for development)
COPY config-repo ./config-repo

# Initialize git in config-repo
RUN apk add --no-cache git && \
    cd config-repo && \
    git init && \
    git config user.email "config@hiveops.com" && \
    git config user.name "Config Server" && \
    git add . && \
    git commit -m "Initial commit" || true

# Change ownership
RUN chown -R hiveops:hiveops /app

# Switch to non-root user
USER hiveops

# Expose port
EXPOSE 8083

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8083/actuator/health || exit 1

# Run application
ENTRYPOINT ["java", "-jar", "app.jar"]

docker-compose.yml (Development)

version: '3.8'

services:
  hiveops-config:
    build: .
    container_name: hiveops-config-dev
    ports:
      - "8083:8083"
    environment:
      - SPRING_PROFILES_ACTIVE=dev
      - CONFIG_USERNAME=config-user
      - CONFIG_PASSWORD=dev-password
    volumes:
      - ./config-repo:/app/config-repo
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    networks:
      - hiveops-network

networks:
  hiveops-network:
    driver: bridge

docker-compose.prod.yml (Production)

version: '3.8'

services:
  hiveops-config:
    image: ${REGISTRY_URL}/hiveops-config:${VERSION:-latest}
    container_name: hiveops-config-prod
    restart: unless-stopped
    ports:
      - "8083:8083"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - CONFIG_USERNAME=${CONFIG_USERNAME}
      - CONFIG_PASSWORD=${CONFIG_PASSWORD}
      - GIT_REPO_URL=${GIT_REPO_URL}
      - GIT_USERNAME=${GIT_USERNAME}
      - GIT_PASSWORD=${GIT_PASSWORD}
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8083/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    networks:
      - hiveops-network
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

networks:
  hiveops-network:
    external: true

DevOps Scripts (Following Standard Pattern)

build-and-push.sh

#!/bin/bash

set -e

# Configuration
SERVICE_NAME="hiveops-config"
REGISTRY_URL="${REGISTRY_URL:-registry.hiveops.com}"

# Get version from pom.xml
VERSION=$(grep -oP '<version>\K[^<]+' pom.xml | head -1)

echo "Building $SERVICE_NAME version $VERSION..."

# Build Docker image
docker build -t $SERVICE_NAME:$VERSION .
docker tag $SERVICE_NAME:$VERSION $SERVICE_NAME:latest

# Tag for registry
docker tag $SERVICE_NAME:$VERSION $REGISTRY_URL/$SERVICE_NAME:$VERSION
docker tag $SERVICE_NAME:latest $REGISTRY_URL/$SERVICE_NAME:latest

# Login to registry
if [ -n "$REGISTRY_USERNAME" ] && [ -n "$REGISTRY_PASSWORD" ]; then
    echo "$REGISTRY_PASSWORD" | docker login $REGISTRY_URL -u "$REGISTRY_USERNAME" --password-stdin
fi

# Push to registry
echo "Pushing to registry..."
docker push $REGISTRY_URL/$SERVICE_NAME:$VERSION

if [ "$VERSION" != "latest" ]; then
    docker push $REGISTRY_URL/$SERVICE_NAME:latest
fi

echo "Build and push completed successfully!"
echo "Image: $REGISTRY_URL/$SERVICE_NAME:$VERSION"

deploy.sh

#!/bin/bash

set -e

SERVICE_NAME="hiveops-config"
COMPOSE_FILE="docker-compose.prod.yml"

# Check if docker-compose.prod.yml exists
if [ ! -f "$COMPOSE_FILE" ]; then
    COMPOSE_FILE="docker-compose.yml"
fi

echo "Deploying $SERVICE_NAME..."

# Load environment variables
if [ -f "devops-scripts/docker/.env" ]; then
    export $(cat devops-scripts/docker/.env | grep -v '^#' | xargs)
fi

# Pull latest image
docker-compose -f $COMPOSE_FILE pull

# Stop and remove old containers
docker-compose -f $COMPOSE_FILE down

# Start new containers
docker-compose -f $COMPOSE_FILE up -d

# Wait for health check
echo "Waiting for service to be healthy..."
sleep 10

# Check health
if docker ps | grep -q $SERVICE_NAME; then
    echo "$SERVICE_NAME deployed successfully!"
    docker-compose -f $COMPOSE_FILE logs --tail=50
else
    echo "Deployment failed!"
    docker-compose -f $COMPOSE_FILE logs
    exit 1
fi

devops-scripts/docker/.env.example

# Registry Configuration
REGISTRY_URL=registry.hiveops.com
REGISTRY_USERNAME=deploy-user
REGISTRY_PASSWORD=changeme

# Version
VERSION=1.0.0

# Config Server Security
CONFIG_USERNAME=config-user
CONFIG_PASSWORD=changeme-strong-password

# Git Repository (Production)
GIT_REPO_URL=https://github.com/hiveops/config-repo.git
GIT_USERNAME=git-user
GIT_PASSWORD=git-token

# Network
NETWORK_NAME=hiveops-network

Testing Strategy

Unit Tests

package com.hiveops.config;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class ConfigServerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    @WithMockUser(roles = "CONFIG_CLIENT")
    void shouldServeConfiguration() throws Exception {
        mockMvc.perform(get("/hiveops-mgmt/dev"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value("hiveops-mgmt"))
            .andExpect(jsonPath("$.profiles[0]").value("dev"));
    }

    @Test
    void healthEndpointShouldBePublic() throws Exception {
        mockMvc.perform(get("/actuator/health"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.status").value("UP"));
    }

    @Test
    void configEndpointShouldRequireAuth() throws Exception {
        mockMvc.perform(get("/hiveops-mgmt/dev"))
            .andExpect(status().isUnauthorized());
    }
}

Critical Files to Create

New Project Files

  1. /source/hiveops-src/hiveops-config/pom.xml

    • Maven dependencies (Spring Cloud Config Server, Security, Actuator)
  2. /source/hiveops-src/hiveops-config/src/main/java/com/hiveops/config/HiveopsConfigServerApplication.java

    • Main class with @EnableConfigServer annotation
  3. /source/hiveops-src/hiveops-config/src/main/java/com/hiveops/config/config/SecurityConfig.java

    • HTTP Basic Auth configuration
  4. /source/hiveops-src/hiveops-config/src/main/resources/application.yml

    • Config server settings (dev profile with local git repo)
  5. /source/hiveops-src/hiveops-config/src/main/resources/application-prod.yml

    • Production profile (remote git repo)
  6. /source/hiveops-src/hiveops-config/config-repo/application.yml

    • Shared configuration for all services
  7. /source/hiveops-src/hiveops-config/config-repo/hiveops-mgmt.yml

    • mgmt service base configuration
  8. /source/hiveops-src/hiveops-config/config-repo/hiveops-mgmt-dev.yml

    • mgmt service dev profile
  9. /source/hiveops-src/hiveops-config/config-repo/hiveops-mgmt-prod.yml

    • mgmt service prod profile
  10. /source/hiveops-src/hiveops-config/config-repo/hiveops-auth.yml

    • auth service base configuration
  11. /source/hiveops-src/hiveops-config/config-repo/hiveops-auth-dev.yml

    • auth service dev profile
  12. /source/hiveops-src/hiveops-config/config-repo/hiveops-auth-prod.yml

    • auth service prod profile
  13. /source/hiveops-src/hiveops-config/config-repo/hiveops-incident.yml

    • incident service base configuration
  14. /source/hiveops-src/hiveops-config/config-repo/hiveops-incident-dev.yml

    • incident service dev profile
  15. /source/hiveops-src/hiveops-config/config-repo/hiveops-incident-prod.yml

    • incident service prod profile
  16. /source/hiveops-src/hiveops-config/config-repo/.gitignore

    • Ignore patterns for config repo
  17. /source/hiveops-src/hiveops-config/Dockerfile

    • Multi-stage Alpine build
  18. /source/hiveops-src/hiveops-config/docker-compose.yml

    • Development environment
  19. /source/hiveops-src/hiveops-config/docker-compose.prod.yml

    • Production deployment
  20. /source/hiveops-src/hiveops-config/devops-scripts/build-and-push.sh

    • Build and push script
  21. /source/hiveops-src/hiveops-config/devops-scripts/deploy.sh

    • Deployment script
  22. /source/hiveops-src/hiveops-config/devops-scripts/docker/.env.example

    • Environment variables template
  23. /source/hiveops-src/hiveops-config/README.md

    • Documentation
  24. /source/hiveops-src/hiveops-config/src/test/java/com/hiveops/config/ConfigServerIntegrationTest.java

    • Integration tests

Modified Files (Client Services)

For each service: hiveops-mgmt, hiveops-auth, hiveops-incident

  1. pom.xml

    • Add spring-cloud-starter-config dependency
    • Add spring-cloud-starter-bootstrap dependency
    • Add spring-cloud-dependencies BOM
  2. src/main/resources/bootstrap.yml (NEW)

    • Config server connection settings
  3. devops-scripts/docker/.env.example

    • Add CONFIG_SERVER_URL, CONFIG_USERNAME, CONFIG_PASSWORD
  4. docker-compose.yml and docker-compose.prod.yml

    • Add config server environment variables
    • Add dependency on hiveops-config service

Verification Steps

1. Config Server Startup

cd /source/hiveops-src/hiveops-config
mvn spring-boot:run

# Expected log output:
# "Fetching config from local git repository at file://.../config-repo"
# "Started HiveopsConfigServerApplication in X.XXX seconds"

2. Health Check

curl http://localhost:8083/actuator/health

# Expected:
# {"status":"UP"}

3. Configuration Retrieval (Authenticated)

# Get mgmt dev configuration
curl -u config-user:changeme http://localhost:8083/hiveops-mgmt/dev

# Expected: JSON response with:
# - name: "hiveops-mgmt"
# - profiles: ["dev"]
# - propertySources: [array of config files]

4. Security Verification

# Without credentials should fail
curl http://localhost:8083/hiveops-mgmt/dev

# Expected: HTTP 401 Unauthorized

5. Client Service Integration

# Start config server
cd /source/hiveops-src/hiveops-config
mvn spring-boot:run &

# Start mgmt service with config client enabled
cd /source/hiveops-src/hiveops-mgmt
export CONFIG_SERVER_URL=http://localhost:8083
export CONFIG_USERNAME=config-user
export CONFIG_PASSWORD=changeme
mvn spring-boot:run

# Check logs for:
# "Fetching config from server at: http://localhost:8083"
# "Located environment: name=hiveops-mgmt, profiles=[dev]"

# Verify config loaded
curl http://localhost:8080/actuator/env | jq '.propertySources[] | select(.name | contains("configServer"))'

6. Docker Build and Run

# Build Docker image
cd /source/hiveops-src/hiveops-config
docker build -t hiveops-config:1.0.0 .

# Run container
docker run -d -p 8083:8083 \
  -e CONFIG_USERNAME=config-user \
  -e CONFIG_PASSWORD=changeme \
  --name hiveops-config \
  hiveops-config:1.0.0

# Test health
curl http://localhost:8083/actuator/health

Migration Strategy

Phase 1: Create Config Server (Week 1)

Tasks:

  1. Create hiveops-config project structure
  2. Implement config server with security
  3. Create config-repo with initial configurations (migrate from existing application.yml files)
  4. Deploy to dev environment
  5. Run tests to verify config serving

Verification:

  • Config server starts successfully
  • Health endpoint returns UP
  • Can retrieve configurations via HTTP
  • Security requires authentication

Phase 2: Integrate hiveops-mgmt (Week 2)

Tasks:

  1. Add Spring Cloud Config dependencies to hiveops-mgmt/pom.xml
  2. Create bootstrap.yml with config server connection
  3. Copy current application-prod.yml content to config-repo/hiveops-mgmt-prod.yml
  4. Test mgmt service with config server in dev environment
  5. Verify all existing functionality works

Rollback plan: Keep application.yml as fallback if config server unavailable

Phase 3: Integrate hiveops-auth (Week 3)

Tasks:

  1. Add dependencies to hiveops-auth/pom.xml
  2. Create bootstrap.yml
  3. Move auth configuration to config-repo
  4. Test authentication flows
  5. Deploy to staging

Phase 4: Integrate hiveops-incident (Week 4)

Tasks:

  1. Add dependencies to hiveops-incident/pom.xml
  2. Create bootstrap.yml
  3. Move incident configuration to config-repo
  4. Test incident workflows
  5. Deploy to staging

Phase 5: Production Deployment (Week 5)

Tasks:

  1. Create production config repository (separate Git repo on Gitea)
  2. Deploy config server to production
  3. Update all services to use prod config server
  4. Monitor logs and health checks
  5. Document configuration management process

Deployment order:

  1. hiveops-config (no dependencies)
  2. hiveops-mgmt (depends on config)
  3. hiveops-auth (depends on config)
  4. hiveops-incident (depends on config)

Security Considerations

1. Config Server Security

  • HTTP Basic Authentication: Required for all config endpoints
  • Strong passwords: Use environment variables, never hardcode
  • HTTPS in production: Use TLS certificates
  • Network isolation: Deploy in private network

2. Git Repository Security

  • Private repository: Never use public repos for production configs
  • Access tokens: Use personal access tokens instead of passwords
  • Branch protection: Require PR reviews for config changes
  • Audit logging: Track who changed what configuration

3. Secrets Management

Never commit secrets to Git

# Good: Reference environment variables
spring:
  datasource:
    password: ${DB_PASSWORD}

# Bad: Hardcoded secrets
spring:
  datasource:
    password: mySecretPassword123

4. Configuration Encryption (Future Enhancement)

Spring Cloud Config supports encryption:

encrypt:
  key: ${ENCRYPT_KEY}  # Symmetric key for encryption/decryption

# Encrypted values in config files:
spring:
  datasource:
    password: '{cipher}AQA2J5...'  # Encrypted

Configuration Best Practices

1. Property Naming Convention

# Use hierarchical structure
hiveops:
  mgmt:
    license:
      offline-grace-period: 7
      validation-interval: 24

  auth:
    mfa:
      enabled: true
      totp-digits: 6

2. Environment Separation

config-repo/
├── application.yml              # Common to all
├── hiveops-mgmt-dev.yml        # Dev-specific
├── hiveops-mgmt-staging.yml    # Staging-specific
├── hiveops-mgmt-prod.yml       # Prod-specific

3. Configuration Documentation

Add comments to config files:

# hiveops-auth.yml

# MFA Configuration
# totp-digits: Number of digits in TOTP code (6 or 8)
# totp-period: Time period in seconds (typically 30)
mfa:
  totp-digits: 6
  totp-period: 30

4. Git Workflow

  • Feature branches: Create branch for config changes
  • Pull requests: Require review before merging
  • Version tags: Tag releases (v1.0.0, v1.1.0)
  • Rollback: Easy to revert to previous commit

Last Updated: 2026-02-13