services:
  traefik:
    image: traefik:v3.6
    command:
      - "--api.dashboard=true"
      - "--api.insecure=false"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.email=contact@mota-thomas.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
    environment:
      DOCKER_HOST: unix:///var/run/docker.sock
      DOCKER_API_VERSION: "1.54"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_letsencrypt:/letsencrypt
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.rule=Host(`traefik.mota-thomas.com`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.middlewares=traefik-errors-403,traefik-errors-401,traefik-auth"
      - "traefik.http.routers.traefik.priority=1"
      - "traefik.http.middlewares.traefik-auth.forwardauth.address=http://oauth2-proxy:4180/oauth2/auth"
      - "traefik.http.middlewares.traefik-auth.forwardauth.trustForwardHeader=true"
      - "traefik.http.middlewares.traefik-auth.forwardauth.authResponseHeaders=X-Auth-Request-User,X-Auth-Request-Email"
      - "traefik.http.middlewares.traefik-errors-401.errors.status=401"
      - "traefik.http.middlewares.traefik-errors-401.errors.service=oauth2-proxy@docker"
      - "traefik.http.middlewares.traefik-errors-401.errors.query=/oauth2/sign_in?rd=https://traefik.mota-thomas.com/dashboard/"
      - "traefik.http.middlewares.traefik-errors-403.errors.status=403"
      - "traefik.http.middlewares.traefik-errors-403.errors.service=oauth2-proxy@docker"
      - "traefik.http.middlewares.traefik-errors-403.errors.query=/oauth2/sign_out?rd=/oauth2/sign_in"

  oauth2-proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0
    restart: unless-stopped
    environment:
      OAUTH2_PROXY_PROVIDER: oidc
      OAUTH2_PROXY_OIDC_ISSUER_URL: https://keycloak.mota-thomas.com/auth/realms/dev-platform
      OAUTH2_PROXY_CLIENT_ID: ${OAUTH2_PROXY_CLIENT_ID}
      OAUTH2_PROXY_CLIENT_SECRET: ${OAUTH2_PROXY_CLIENT_SECRET}
      OAUTH2_PROXY_COOKIE_SECRET: ${OAUTH2_PROXY_COOKIE_SECRET}
      OAUTH2_PROXY_EMAIL_DOMAINS: "*"
      OAUTH2_PROXY_REDIRECT_URL: https://traefik.mota-thomas.com/oauth2/callback
      OAUTH2_PROXY_UPSTREAMS: static://200
      OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:4180
      OAUTH2_PROXY_REVERSE_PROXY: "true"
      OAUTH2_PROXY_SCOPE: "openid email profile"
      OAUTH2_PROXY_OIDC_GROUPS_CLAIM: groups
      OAUTH2_PROXY_ALLOWED_GROUPS: admins
      OAUTH2_PROXY_PROMPT: "login"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.oauth2.rule=Host(`traefik.mota-thomas.com`) && PathPrefix(`/oauth2/`)"
      - "traefik.http.routers.oauth2.entrypoints=websecure"
      - "traefik.http.routers.oauth2.tls.certresolver=letsencrypt"
      - "traefik.http.routers.oauth2.priority=100"
      - "traefik.http.services.oauth2.loadbalancer.server.port=4180"

  gitea-db:
    image: postgres:15
    environment:
      POSTGRES_USER: gitea
      POSTGRES_PASSWORD: ${GITEA_DB_PASSWORD}
      POSTGRES_DB: gitea
    volumes:
      - gitea_db_data:/var/lib/postgresql/data

  gitea:
    image: gitea/gitea:latest
    depends_on:
      - gitea-db
    environment:
      GITEA__database__DB_TYPE: postgres
      GITEA__database__HOST: gitea-db:5432
      GITEA__database__NAME: gitea
      GITEA__database__USER: gitea
      GITEA__database__PASSWD: ${GITEA_DB_PASSWORD}
      GITEA__server__ROOT_URL: https://gitea.mota-thomas.com/
      GITEA__actions__ENABLED: "true"
    volumes:
      - gitea_data:/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.gitea.rule=Host(`gitea.mota-thomas.com`)"
      - "traefik.http.routers.gitea.entrypoints=websecure"
      - "traefik.http.routers.gitea.tls.certresolver=letsencrypt"
      - "traefik.http.services.gitea.loadbalancer.server.port=3000"

  gitea-runner:
    image: gitea/act_runner:latest
    restart: unless-stopped
    depends_on:
      - gitea
    environment:
      CONFIG_FILE: /config.yaml
      GITEA_INSTANCE_URL: https://gitea.mota-thomas.com
      GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN}
      GITEA_RUNNER_NAME: dev-platform-runner
      GITEA_RUNNER_LABELS: ubuntu-latest:docker://node:20-bookworm
    volumes:
      - ./gitea-runner/config.yaml:/config.yaml
      - gitea_runner_data:/data
      - /var/run/docker.sock:/var/run/docker.sock

  keycloak-db:
    image: postgres:15
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
    volumes:
      - keycloak_db_data:/var/lib/postgresql/data

  keycloak:
    image: quay.io/keycloak/keycloak:24.0
    command: start-dev
    environment:
      KC_DB: postgres
      KC_DB_URL_HOST: keycloak-db
      KC_DB_URL_DATABASE: keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
      KC_HTTP_RELATIVE_PATH: /auth
      KC_PROXY_HEADERS: xforwarded
      KC_HOSTNAME_STRICT: false
      KC_HTTP_ENABLED: true
    depends_on:
      - keycloak-db
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.keycloak.rule=Host(`keycloak.mota-thomas.com`)"
      - "traefik.http.routers.keycloak.entrypoints=websecure"
      - "traefik.http.routers.keycloak.tls.certresolver=letsencrypt"
      - "traefik.http.services.keycloak.loadbalancer.server.port=8080"

  sonarqube-db:
    image: postgres:15
    container_name: sonarqube-db
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: ${SONAR_DB_PASSWORD}
      POSTGRES_DB: sonarqube
    volumes:
      - sonarqube_db_data:/var/lib/postgresql/data

  sonarqube:
    image: sonarqube:community
    container_name: sonarqube
    depends_on:
      - sonarqube-db
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://sonarqube-db:5432/sonarqube
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: ${SONAR_DB_PASSWORD}
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_logs:/opt/sonarqube/logs
      - ./sonarqube/extensions:/opt/sonarqube/extensions
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.sonarqube.rule=Host(`sonarqube.mota-thomas.com`)"
      - "traefik.http.routers.sonarqube.entrypoints=websecure"
      - "traefik.http.routers.sonarqube.tls.certresolver=letsencrypt"
      - "traefik.http.services.sonarqube.loadbalancer.server.port=9000"

  code-server:
    image: lscr.io/linuxserver/code-server:latest
    container_name: code-server
    environment:
      PUID: 1000
      PGID: 1000
      TZ: Europe/Zurich
      DEFAULT_WORKSPACE: /config/workspace
    volumes:
      - code_server_config:/config
      - ./workspace:/config/workspace
    networks:
      - default
    restart: unless-stopped

  oauth2-proxy-code:
    image: quay.io/oauth2-proxy/oauth2-proxy:v7.8.1
    container_name: oauth2-proxy-code
    depends_on:
      - code-server
    environment:
      OAUTH2_PROXY_PROVIDER: keycloak-oidc
      OAUTH2_PROXY_CLIENT_ID: ${CODE_SERVER_OAUTH2_CLIENT_ID}
      OAUTH2_PROXY_CLIENT_SECRET: ${CODE_SERVER_OAUTH2_CLIENT_SECRET}
      OAUTH2_PROXY_COOKIE_SECRET: ${CODE_SERVER_OAUTH2_COOKIE_SECRET}
      OAUTH2_PROXY_COOKIE_SECURE: "true"
      OAUTH2_PROXY_EMAIL_DOMAINS: "*"
      OAUTH2_PROXY_REDIRECT_URL: https://code.mota-thomas.com/oauth2/callback
      OAUTH2_PROXY_OIDC_ISSUER_URL: https://keycloak.mota-thomas.com/auth/realms/dev-platform
      OAUTH2_PROXY_UPSTREAMS: http://code-server:8443
      OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:4180
      OAUTH2_PROXY_REVERSE_PROXY: "true"
      OAUTH2_PROXY_PASS_ACCESS_TOKEN: "true"
      OAUTH2_PROXY_PASS_USER_HEADERS: "true"
      OAUTH2_PROXY_SET_XAUTHREQUEST: "true"
      OAUTH2_PROXY_WHITELIST_DOMAINS: .mota-thomas.com
      OAUTH2_PROXY_COOKIE_DOMAINS: .mota-thomas.com
      OAUTH2_PROXY_COOKIE_NAME: "_oauth2_proxy_code"
      OAUTH2_PROXY_CODE_CHALLENGE_METHOD: S256
    labels:
      traefik.enable: "true"
      traefik.http.routers.code-server.rule: Host(`code.mota-thomas.com`)
      traefik.http.routers.code-server.entrypoints: websecure
      traefik.http.routers.code-server.tls.certresolver: letsencrypt
      traefik.http.services.code-server.loadbalancer.server.port: "4180"
    networks:
      - default
    restart: unless-stopped

volumes:
  gitea_db_data:
  gitea_data:
  gitea_runner_data:
  keycloak_db_data:
  traefik_letsencrypt:
  sonarqube_db_data:
  sonarqube_data:
  sonarqube_logs:
  code_server_config:
