diff --git a/.dockerignore b/.dockerignore index 004fb3ff..3a2797ed 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ node_modules +letsencrypt/ apps/dispatch/node_modules apps/dispatch-server/node_modules apps/hub/node_modules diff --git a/.env.prod b/.env.prod index ccecadc5..cd8883d5 100644 --- a/.env.prod +++ b/.env.prod @@ -7,18 +7,18 @@ AUTH_HUB_SECRET=var AUTH_DISPATCH_COOKIE_PREFIX=DISPATCH AUTH_HUB_COOKIE_PREFIX=HUB -AUTH_DISPATCH_URL=http://premiumag.de:3001 -AUTH_HUB_URL=http://premiumag.de:3000 +AUTH_DISPATCH_URL=https://dispatch.premiumag.de +AUTH_HUB_URL=https://hub.premiumag.de NEXT_PUBLIC_DISPATCH_SERVICE_ID=1 # ─────────────────────────────────────────────── # 🌐 Öffentliche URLs # ─────────────────────────────────────────────── -NEXT_PUBLIC_HUB_URL=http://premiumag.de:3000 -NEXT_PUBLIC_HUB_SERVER_URL=http://premiumag.de:3003 -NEXT_PUBLIC_DISPATCH_URL=http://premiumag.de:3001 -NEXT_PUBLIC_DISPATCH_SERVER_URL=http://premiumag.de:3002 +NEXT_PUBLIC_HUB_URL=https://hub.premiumag.de +NEXT_PUBLIC_HUB_SERVER_URL=https://api.hub.premiumag.de +NEXT_PUBLIC_DISPATCH_URL=https://dispatch.premiumag.de +NEXT_PUBLIC_DISPATCH_SERVER_URL=https://api.dispatch.premiumag.de # ─────────────────────────────────────────────── # 🗄️ Datenbank @@ -28,7 +28,7 @@ DATABASE_URL=postgresql://persistant-data:persistant-data-pw@postgres:5432/var # ─────────────────────────────────────────────── # 📡 LiveKit Konfiguration # ─────────────────────────────────────────────── -NEXT_PUBLIC_LIVEKIT_URL=ws://localhost:7880 +NEXT_PUBLIC_LIVEKIT_URL=wss://livekit.premiumag.de LIVEKIT_API_KEY=APIAnsGdtdYp2Ho LIVEKIT_API_SECRET=tdPjVsYUx8ddC7K9NvdmVAeLRF9GeADD6Fedm1x63fWC @@ -45,15 +45,14 @@ REDIS_PORT=6379 # 🧠 HUB Server (Backend) # ─────────────────────────────────────────────── HUB_SERVER_PORT=3000 -HUB_URL= # ─────────────────────────────────────────────── # 📚 Moodle # ─────────────────────────────────────────────── -MOODLE_URL=http://premiumag.de:8081 +MOODLE_URL=https://02.premiumag.de:8081 MOODLE_API_TOKEN=ac346f0324647b68488d13fd52a9bbe8 MOODLE_USER_PASSWORD=var-api-user-P1 -NEXT_PUBLIC_MOODLE_URL=http://premiumag.de:8081 +NEXT_PUBLIC_MOODLE_URL=https://02.premiumag.de:8081 # ─────────────────────────────────────────────── # 📧 E-Mail Einstellungen (nur HUB Server) diff --git a/apps/dispatch/app/dispatch/socket.ts b/apps/dispatch/app/dispatch/socket.ts index 39032d29..84605b5c 100644 --- a/apps/dispatch/app/dispatch/socket.ts +++ b/apps/dispatch/app/dispatch/socket.ts @@ -5,4 +5,5 @@ console.log("ENV:", process.env.NEXT_PUBLIC_DISPATCH_SERVER_URL); export const dispatchSocket: Socket = io(process.env.NEXT_PUBLIC_DISPATCH_SERVER_URL, { autoConnect: false, + transports: ["websocket"], }); diff --git a/apps/dispatch/app/pilot/socket.ts b/apps/dispatch/app/pilot/socket.ts index eb258d90..a7e81ab5 100644 --- a/apps/dispatch/app/pilot/socket.ts +++ b/apps/dispatch/app/pilot/socket.ts @@ -3,4 +3,5 @@ import { io, Socket } from "socket.io-client"; export const pilotSocket: Socket = io(process.env.NEXT_PUBLIC_DISPATCH_SERVER_URL, { autoConnect: false, + transports: ["websocket"], }); diff --git a/apps/hub/app/api/auth/[...nextauth]/auth.ts b/apps/hub/app/api/auth/[...nextauth]/auth.ts index a0fbb74e..917bc9e4 100644 --- a/apps/hub/app/api/auth/[...nextauth]/auth.ts +++ b/apps/hub/app/api/auth/[...nextauth]/auth.ts @@ -27,6 +27,7 @@ export const options: AuthOptions = { }, }), ], + secret: process.env.AUTH_HUB_SECRET, session: { strategy: "jwt", diff --git a/apps/hub/helper/authServices.ts b/apps/hub/helper/authServices.ts index 71f4803b..ab337d49 100644 --- a/apps/hub/helper/authServices.ts +++ b/apps/hub/helper/authServices.ts @@ -3,7 +3,7 @@ export const services = [ id: "1", service: "dispatch", name: "Leitstellendisposition", - approvedUrls: ["http://localhost:3001"], + approvedUrls: ["https://dispatch.premiumag.de"], }, { id: "2", diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 9d1f4e7c..710d921e 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,31 +1,57 @@ services: traefik: - image: traefik:v2.11 - ports: - - "80:80" - - "443:443" - - "8080:8080" # Traefik Dashboard - deploy: - placement: - constraints: - - node.role == manager - labels: - - "traefik.enable=true" - - "traefik.http.routers.api.rule=Host(`traefik.premiumag.de`)" - - "traefik.http.routers.api.service=api@internal" - - "traefik.http.routers.api.entrypoints=web" - - "traefik.http.services.api.loadbalancer.server.port=8080" + image: traefik:v3.4 command: - - "--api.dashboard=true" - - "--api.insecure=true" # Nur für Testzwecke! + - "--api.dashboard=true" # Dashboard aktivieren (nicht für Produktion) + - "--api.insecure=true" # Unsicheres Dashboard (nur für Entwicklung) + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--providers.docker.useBindPortIP=true" - "--entrypoints.web.address=:80" - - "--providers.docker" - - "--providers.docker.swarmmode=true" + - --entrypoints.web.http.redirections.entryPoint.to=websecure + - --entrypoints.web.http.redirections.entryPoint.scheme=https + - --entrypoints.web.http.redirections.entrypoint.permanent=true + - "--entrypoints.websecure.address=:443" + - "--certificatesresolvers.le.acme.httpchallenge=true" + - "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web" + - "--certificatesresolvers.le.acme.email=johannesambre@gmail.com" + - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json" + ports: + - "443:443" # HTTPS-Zugang + - "80:80" # HTTP-Zugang + - "8080:8080" # Traefik Dashboard volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" + - "./letsencrypt:/letsencrypt" + networks: + - traefik_network + + portainer: + image: portainer/portainer-ce:latest + volumes: + - portainer_data:/data + - /var/run/docker.sock:/var/run/docker.sock + restart: unless-stopped + labels: + # Frontend + - "traefik.enable=true" + - "traefik.http.routers.portainer-frontend.rule=Host(`portainer.premiumag.de`)" + - "traefik.http.routers.portainer-frontend.entrypoints=websecure" + - "traefik.http.services.portainer-frontend.loadbalancer.server.port=9000" + - "traefik.http.routers.portainer-frontend.service=portainer-frontend" + - "traefik.http.routers.portainer-frontend.tls.certresolver=le" + + # Edge + - "traefik.http.routers.portainer-edge.rule=Host(`edge.premiumag.de`)" + - "traefik.http.routers.portainer-edge.entrypoints=websecure" + - "traefik.http.services.portainer-edge.loadbalancer.server.port=8000" + - "traefik.http.routers.portainer-edge.service=portainer-edge" + - "traefik.http.routers.portainer-edge.tls.certresolver=le" + networks: + - traefik_network + + # Dispatch Service dispatch: - deploy: - replicas: 3 build: context: . dockerfile: ./apps/dispatch/Dockerfile @@ -35,14 +61,53 @@ services: - NEXT_PUBLIC_DISPATCH_SERVICE_ID=1 - NEXT_PUBLIC_LIVEKIT_URL=$NEXT_PUBLIC_LIVEKIT_URL - NEXT_PUBLIC_DISPATCH_SERVER_URL=$NEXT_PUBLIC_DISPATCH_SERVER_URL + env_file: + - .env.prod + deploy: + replicas: 1 labels: - "traefik.enable=true" - "traefik.http.routers.dispatch.rule=Host(`dispatch.premiumag.de`)" + - "traefik.http.routers.dispatch.entrypoints=websecure" + - "traefik.http.routers.dispatch.tls.certresolver=le" - "traefik.http.services.dispatch.loadbalancer.server.port=3000" - env_file: - - .env.prod + - "traefik.docker.network=var-monorepo_traefik_network" + environment: + - NEXTAUTH_URL=${AUTH_DISPATCH_URL} + networks: - postgres_network + - traefik_network + dispatch-server: + build: + context: . + dockerfile: ./apps/dispatch-server/Dockerfile + env_file: + - .env.prod + deploy: + replicas: 1 + labels: + - "traefik.enable=true" + - "traefik.http.routers.dispatch-server.rule=Host(`api.dispatch.premiumag.de`)" + - "traefik.http.routers.dispatch-server.entrypoints=websecure" + - "traefik.http.routers.dispatch-server.tls.certresolver=le" + - "traefik.http.services.dispatch-server.loadBalancer.sticky.cookie.name=server_id" + - "traefik.http.services.dispatch-server.loadBalancer.sticky.cookie.httpOnly=true" + - "traefik.http.services.dispatch-server.loadbalancer.server.port=3000" + - "traefik.docker.network=var-monorepo_traefik_network" + networks: + - postgres_network + - redis_network + - traefik_network + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + + + + # Hub Service hub: build: context: . @@ -52,47 +117,41 @@ services: - NEXT_PUBLIC_HUB_URL=$NEXT_PUBLIC_HUB_URL - NEXT_PUBLIC_LIVEKIT_URL=$NEXT_PUBLIC_LIVEKIT_URL - NEXT_PUBLIC_HUB_SERVER_URL=$NEXT_PUBLIC_HUB_SERVER_URL - container_name: hub - ports: - - "3000:3000" + labels: + - "traefik.enable=true" + - "traefik.http.routers.hub.rule=Host(`hub.premiumag.de`)" + - "traefik.http.routers.hub.entrypoints=websecure" + - "traefik.http.routers.hub.tls.certresolver=le" + - "traefik.http.services.hub.loadbalancer.server.port=3000" + - "traefik.docker.network=var-monorepo_traefik_network" + environment: + - NEXTAUTH_URL=${AUTH_HUB_URL} env_file: - .env.prod networks: - postgres_network + - traefik_network hub-server: build: context: . dockerfile: ./apps/hub-server/Dockerfile container_name: hub-server - ports: - - "3003:3000" - env_file: - - .env.prod - networks: - - postgres_network - depends_on: - postgres: - condition: service_healthy - dispatch-server: - deploy: - replicas: 3 - build: - context: . - dockerfile: ./apps/dispatch-server/Dockerfile - env_file: - - .env.prod - networks: - - postgres_network - - redis_network labels: - "traefik.enable=true" - - "traefik.http.routers.dispatch.rule=Host(`dispatch-server.premiumag.de`)" - - "traefik.http.services.dispatch.loadbalancer.server.port=3000" + - "traefik.http.routers.hub-server.rule=Host(`api.hub.premiumag.de`)" + - "traefik.http.routers.hub-server.entrypoints=websecure" + - "traefik.http.routers.hub-server.tls.certresolver=le" + - "traefik.http.services.hub-server.loadbalancer.server.port=3000" + - "traefik.docker.network=var-monorepo_traefik_network" + + env_file: + - .env.prod + networks: + - postgres_network + - traefik_network depends_on: postgres: condition: service_healthy - redis: - condition: service_healthy postgres: image: postgres:13 container_name: postgres @@ -112,15 +171,7 @@ services: - postgres-data:/var/lib/postgresql/data networks: - postgres_network - grafana: - image: grafana/grafana:latest - container_name: grafana - ports: - - "4100:3000" - depends_on: - - postgres - volumes: - - ./grafana:/var/lib/grafana + redis: container_name: redis image: redis/redis-stack:latest @@ -133,66 +184,98 @@ services: healthcheck: test: ["CMD", "redis-cli", "--raw", "incr", "ping"] - moodle_database: - container_name: moodle_database - image: docker.io/bitnami/mariadb:latest - environment: - # ALLOW_EMPTY_PASSWORD is recommended only for development. - - ALLOW_EMPTY_PASSWORD=yes - - MARIADB_USER=bn_moodle - - MARIADB_DATABASE=bitnami_moodle - - MARIADB_CHARACTER_SET=utf8mb4 - - MARIADB_COLLATE=utf8mb4_unicode_ci - volumes: - - "moodle_database:/bitnami/mariadb" - moodle: - image: bitnami/moodle:latest - container_name: moodle - ports: - - "8081:8080" # Moodle läuft auf http://localhost:8081 - environment: - - MOODLE_DATABASE_HOST=moodle_database - - MOODLE_DATABASE_PORT_NUMBER=3306 - - MOODLE_DATABASE_USER=bn_moodle - - MOODLE_DATABASE_NAME=bitnami_moodle + # grafana: + # image: grafana/grafana:latest + # container_name: grafana + # ports: + # - "4100:3000" + # depends_on: + # - postgres + # volumes: + # - ./grafana:/var/lib/grafana - - MOODLE_USERNAME=admin - - MOODLE_PASSWORD=admin123 - - MOODLE_EMAIL=admin@example.com - - MOODLE_SITE_NAME="Mein Lokales Moodle" - - MOODLE_SSLPROXY=false - - ALLOW_EMPTY_PASSWORD=yes - depends_on: - - moodle_database - volumes: - - moodle_data:/bitnami/moodle - - moodle_moodledata:/bitnami/moodledata + #moodle_database: + # container_name: moodle_database + # image: docker.io/bitnami/mariadb:latest + # environment: + # # ALLOW_EMPTY_PASSWORD is recommended only for development. + # - ALLOW_EMPTY_PASSWORD=yes + # - MARIADB_USER=bn_moodle + # - MARIADB_DATABASE=bitnami_moodle + # - MARIADB_CHARACTER_SET=utf8mb4 + # - MARIADB_COLLATE=utf8mb4_unicode_ci + # volumes: + # - "moodle_database:/bitnami/mariadb" + # networks: + # - moodle_db_network + #moodle: + # image: bitnami/moodle:latest + # container_name: moodle + # environment: + # - MOODLE_DATABASE_HOST=moodle_database + # - MOODLE_DATABASE_PORT_NUMBER=3306 + # - MOODLE_DATABASE_USER=bn_moodle + # - MOODLE_DATABASE_NAME=bitnami_moodle +# + # - MOODLE_USERNAME=admin + # - MOODLE_PASSWORD=admin123 + # - MOODLE_EMAIL=admin@example.com + # - MOODLE_SITE_NAME="Mein Lokales Moodle" + # - MOODLE_SSLPROXY=false + # - ALLOW_EMPTY_PASSWORD=yes + # depends_on: + # - moodle_database + # labels: + # - "traefik.enable=true" + # - "traefik.http.routers.moodle.rule=Host(`moodle.premiumag.de`)" + # - "traefik.http.routers.moodle.entrypoints=websecure" + # - "traefik.http.routers.moodle.tls.certresolver=le" + # - "traefik.http.services.moodle.loadbalancer.server.port=8080" + # - "traefik.docker.network=var-monorepo_traefik_network" + # networks: + # - moodle_db_network + # - traefik_network + # volumes: + # - moodle_data:/bitnami/moodle + # - moodle_moodledata:/bitnami/moodledata + # networks: + # - postgres_network + # - traefik_network # Für den Zugriff auf den Host - livekit-server: + livekit: image: livekit/livekit-server - container_name: livekit_server + command: --config /etc/livekit.yaml --node-ip 37.221.196.140 restart: unless-stopped + networks: + - traefik_network ports: - - "7880:7880" - "7881:7881" - "7882:7882/udp" + depends_on: + - redis volumes: - - "./livekit.yaml:/livekit.yaml" - command: - - "--config" - - "/livekit.yaml" - - "--node-ip=127.0.0.1" + - ./livekit.yaml:/etc/livekit.yaml + labels: + - "traefik.enable=true" + - "traefik.http.routers.livekit.rule=Host(`livekit.premiumag.de`)" + - "traefik.http.routers.livekit.entrypoints=websecure" + - "traefik.http.routers.livekit.tls=true" + - "traefik.http.routers.livekit.tls.certresolver=le" + - "traefik.http.routers.livekit.service=livekit" + - "traefik.http.services.livekit.loadbalancer.server.port=7880" + networks: default: driver: bridge - networks: - traefik_public: - external: true postgres_network: driver: bridge redis_network: driver: bridge + traefik_network: + driver: bridge + moodle_db_network: + driver: bridge volumes: postgres-data: @@ -201,3 +284,4 @@ volumes: moodle_moodledata: redis_data: driver: local + portainer_data: diff --git a/livekit.yaml b/livekit.yaml index 137b380b..6e296217 100644 --- a/livekit.yaml +++ b/livekit.yaml @@ -3,11 +3,10 @@ rtc: udp_port: 7882 tcp_port: 7881 use_external_ip: false - enable_loopback_candidate: false # ice_servers: # - urls: ["stun:stun.l.google.com:19302"] keys: APIAnsGdtdYp2Ho: tdPjVsYUx8ddC7K9NvdmVAeLRF9GeADD6Fedm1x63fWC logging: json: false - level: info + level: info \ No newline at end of file