# 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) ```xml org.springframework.boot spring-boot-starter-parent 3.4.1 21 2023.0.3 org.springframework.cloud spring-cloud-config-server org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-security org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.springframework.security spring-security-test test org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import ``` ### Main Application Class ```java 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) ```java 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) ```yaml 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) ```yaml 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): ```yaml # 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): ```yaml 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:** ```xml org.springframework.cloud spring-cloud-starter-config org.springframework.cloud spring-cloud-starter-bootstrap ``` **2. Create bootstrap.yml** (loaded before application.yml): ```yaml 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: ```dockerfile # 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) ```yaml 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) ```yaml 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 ```bash #!/bin/bash set -e # Configuration SERVICE_NAME="hiveops-config" REGISTRY_URL="${REGISTRY_URL:-registry.hiveops.com}" # Get version from pom.xml VERSION=$(grep -oP '\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 ```bash #!/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 ```bash # 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 ```java 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 ```bash 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 ```bash curl http://localhost:8083/actuator/health # Expected: # {"status":"UP"} ``` ### 3. Configuration Retrieval (Authenticated) ```bash # 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 ```bash # Without credentials should fail curl http://localhost:8083/hiveops-mgmt/dev # Expected: HTTP 401 Unauthorized ``` ### 5. Client Service Integration ```bash # 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 ```bash # 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** ```yaml # 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: ```yaml 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 ```yaml # 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: ```yaml # 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