Infrastructure Setup on Ionos

This page describes the full deployment setup I use on my Ionos VPS. It’s based on Traefik, Docker Compose, Kafka (KRaft), Spring Boot Admin, and Spring Boot image-build.

Everything runs inside a single network called ccpp-network.


Docker Compose

Below is the full Compose file, including Traefik labels, Kafka, frontend, API Gateway, microservices, and Spring Boot Admin.

services:
  discovery:
    image: ghcr.io/jbonifay/discovery:latest
    ports:
      - "8761:8761"
    networks:
      - ccpp-network

  api-gateway:
    image: ghcr.io/jbonifay/api-gateway:latest
    environment:
      EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka
      JWT_SECRET: ${JWT_SECRET}
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api-gateway.rule=Host(`ccpp.joffreybonifay.fr`) && PathPrefix(`/api`)"
      - "traefik.http.routers.api-gateway.entrypoints=websecure"
      - "traefik.http.routers.api-gateway.tls.certresolver=letsencrypt"
      - "traefik.http.routers.api-gateway.priority=10"
      - "traefik.http.middlewares.api-stripprefix.stripprefix.prefixes=/api"
      - "traefik.http.routers.api-gateway.middlewares=api-stripprefix"
      - "traefik.http.services.api-gateway.loadbalancer.server.port=8080"
    networks:
      - ccpp-network

  project-planning:
    image: ghcr.io/jbonifay/project-planning:latest
    environment:
      SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/project-planning
      SPRING_DATASOURCE_USERNAME: ${DB_USER}
      SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
      EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka
    depends_on:
      - kafka
    networks:
      - ccpp-network

  workspace:
    image: ghcr.io/jbonifay/workspace:latest
    environment:
      SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/workspace
      SPRING_DATASOURCE_USERNAME: ${DB_USER}
      SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
      EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka
    depends_on:
      - kafka
    networks:
      - ccpp-network

  ideation:
    image: ghcr.io/jbonifay/ideation:latest
    environment:
      SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/ideation
      SPRING_DATASOURCE_USERNAME: ${DB_USER}
      SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
      EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka
    depends_on:
      - kafka
    networks:
      - ccpp-network

  notification:
    image: ghcr.io/jbonifay/notification:latest
    environment:
      SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/notification
      SPRING_DATASOURCE_USERNAME: ${DB_USER}
      SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
      EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka
    depends_on:
      - kafka
    networks:
      - ccpp-network

  user-management:
    image: ghcr.io/jbonifay/user-management:latest
    environment:
      SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/user-management
      SPRING_DATASOURCE_USERNAME: ${DB_USER}
      SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
      EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://discovery:8761/eureka
      JWT_SECRET: ${JWT_SECRET}
    depends_on:
      - kafka
    networks:
      - ccpp-network

  #  admin-server:
  #    image: ghcr.io/jbonifay/spring-boot-admin:latest
  #    environment:
  #      - SPRING_BOOT_ADMIN_CONTEXT_PATH=/admin
  #    labels:
  #      - "traefik.enable=true"
  #      - "traefik.http.routers.admin.rule=Host(`ccpp.joffreybonifay.fr`) && PathPrefix(`/admin`)"
  #      - "traefik.http.routers.admin.entrypoints=websecure"
  #      - "traefik.http.routers.admin.tls.certresolver=letsencrypt"
  #      - "traefik.http.routers.admin.priority=10"
  #      - "traefik.http.services.admin.loadbalancer.server.port=8080"
  #    networks:
  #      - ccpp-network

  kafka:
    image: confluentinc/cp-kafka:latest
    environment:
      # KRaft mode settings
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: "broker,controller"
      KAFKA_CONTROLLER_QUORUM_VOTERS: "1@kafka:9093"
      KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"

      # TODO: verify why
      # Listeners: one for Docker network, one for host
      KAFKA_LISTENERS: "INTERNAL://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093"
      KAFKA_ADVERTISED_LISTENERS: "INTERNAL://kafka:9092,CONTROLLER://kafka:9093"
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT"
      KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL"

      # Cluster settings
      CLUSTER_ID: "MkU3OEVBNTcwNTJENDM2Qk"
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_NUM_PARTITIONS: 1

      # Log settings
      KAFKA_LOG_DIRS: "/tmp/kraft-combined-logs"
    networks:
      - ccpp-network

  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    ports:
      - "8762:8080"
    environment:
      KAFKA_CLUSTERS_0_NAME: "local"
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: "kafka:9092"
    networks:
      - ccpp-network

  postgres:
    image: postgres:latest
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    #    volumes:
    #      - ./init-scripts:/docker-entrypoint-initdb.d
    networks:
      - ccpp-network

volumes:
  postgres_data:

networks:
  ccpp-network:
#    external: true

Spring Boot Admin: Monitoring and Management

Spring Boot Admin provides:

  • Real-time monitoring of all Spring Boot microservices
  • Health status and metrics visualization
  • Application logs and environment information
  • Accessible at /admin path through Traefik

The admin server automatically discovers and monitors:

  • API Gateway
  • Project Planning service
  • Workspace service
  • Ideation service
  • Notification service