From afa53aa74721b7775314b4402f9b856b0d2882c4 Mon Sep 17 00:00:00 2001 From: Teck Meng Date: Thu, 30 May 2024 21:01:13 +0800 Subject: [PATCH] feat: stack compose --- compose/deploy-cloudy.yml | 870 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 870 insertions(+) create mode 100644 compose/deploy-cloudy.yml diff --git a/compose/deploy-cloudy.yml b/compose/deploy-cloudy.yml new file mode 100644 index 0000000..005013d --- /dev/null +++ b/compose/deploy-cloudy.yml @@ -0,0 +1,870 @@ +networks: + default: + external: true + name: ${NETWORK:-web} + net: + external: true + name: ${NETWORK:-web} + +x-environment: &default-environment + LOG_LEVEL: "INFO" + ACME_PATH: "./acme.json" + NETWORK: "${NETWORK:-web}" + DOMAINNAME: "${DOMAINNAME:-furyhawk.lol}" + TZ: "${TZ:-Asia/Singapore}" + FIN_LOCATION: "" + STREAMLIT_FIN_SERVER_PORT: "8501" + GROQ_API_KEY: "${GROQ_API_KEY}" + BAI_LOCATION: "" + STREAMLIT_BAI_SERVER_PORT: "8502" + +volumes: + bai_cache: {} + ghost_content: {} + ghost_mysql: {} + jellyfin_config: {} + jellyfin_cache: {} + pgadmin: {} + pgadmin_data: {} + privatebin_data: {} + thelounge_data: {} + minio_data: {} + neo4j_data: {} + neo4j_logs: {} + postgres_data: {} + logs: {} + production_traefik: {} + portainer_data: {} + data-node: + pgdata2: + libre-images: + libre-logs: + meili_data: + vol-emqx-data1: + name: foo-emqx-data1 + external: true + +services: + + portainer: + image: portainer/portainer-ce:sts + command: -H unix:///var/run/docker.sock + security_opt: + - no-new-privileges:true + environment: + <<: *default-environment + restart: always + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + expose: + - 8000 + - 9000 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.portainer.entrypoints=web-secure" + - "traefik.http.routers.portainer.rule=Host(`portainer.${DOMAINNAME}`) || Host(`port.${DOMAINNAME}`)" + - "traefik.http.routers.portainer.middlewares=csrf@file" + - "traefik.http.routers.portainer.tls.certresolver=letsencrypt" + - "traefik.http.routers.portainer.service=portainer_service" + - "traefik.http.services.portainer_service.loadbalancer.server.port=9000" + + traefik: + environment: + <<: *default-environment + build: + context: . + dockerfile: ./traefik/Dockerfile + image: traefik_production + security_opt: + - no-new-privileges:true + restart: always + deploy: + placement: + constraints: + - node.role == manager + volumes: + - logs:/logs + - production_traefik:/etc/traefik/acme:z + - /var/run/docker.sock:/var/run/docker.sock + extra_hosts: + - "host.docker.internal:host-gateway" + ports: + - target: 80 + published: 80 + protocol: tcp + mode: host + - target: 443 + published: 443 + protocol: tcp + mode: host + - "7687:7687" + - "8083:8083" + - "8084:8084" + - "8883:8883" + - "5432:5432" + # - "8080:8080" + # - "1883:1883" + # - 18083:18083 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.traefik.entrypoints=web-secure" + - "traefik.http.routers.traefik.rule=Host(`dashboard.${DOMAINNAME}`)" + - "traefik.http.routers.traefik.middlewares=auth@file" + - "traefik.http.routers.traefik.tls.certresolver=letsencrypt" + - "traefik.http.routers.traefik.service=api@internal" + + api_server: + image: furyhawk/listen:latest + restart: always + depends_on: + - postgres + environment: + DATABASE__HOSTNAME: ${DATABASE__HOSTNAME} + DATABASE__USERNAME: ${POSTGRES_USER} + DATABASE__PASSWORD: ${POSTGRES_PASSWORD} + DATABASE__PORT: ${DATABASE__PORT} + DATABASE__DB: ${DATABASE__DB} + SECURITY__JWT_SECRET_KEY: ${SECURITY__JWT_SECRET_KEY} + SECURITY__BACKEND_CORS_ORIGINS: ${SECURITY__BACKEND_CORS_ORIGINS} + SECURITY__ALLOWED_HOSTS: ${SECURITY__ALLOWED_HOSTS} + DOMAINNAME: ${DOMAINNAME} + ports: + - "8000:8000" + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.api_server.entrypoints=web-secure" + - "traefik.http.routers.api_server.rule=Host(`api.${DOMAINNAME}`)" + - "traefik.http.routers.api_server.middlewares=csrf@file, rate-limit@file" + - "traefik.http.routers.api_server.tls.certresolver=letsencrypt" + - "traefik.http.routers.api_server.service=api_server_service" + - "traefik.http.services.api_server_service.loadbalancer.server.port=8000" + + postgres: + image: postgres + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + PGDATA: "/var/lib/postgresql/data" + LANG: en_US.utf8 + TZ: Asia/Singapore + # DOMAINNAME: ${DOMAINNAME} + command: ["postgres", "-c", "log_connections=on"] + volumes: + - postgres_data:/var/lib/postgresql/data + # - ./config/postgresql.conf:/etc/postgresql.conf + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + interval: 30s + timeout: 10s + retries: 10 + # ports: + # - "5432:5432" + expose: + - 5432 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.tcp.routers.postgres.entrypoints=postgres-socket" + - "traefik.tcp.routers.postgres.rule=HostSNI(`*`)" + - "traefik.tcp.routers.postgres.service=postgres_service" + - "traefik.tcp.services.postgres_service.loadbalancer.server.port=5432" + # - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" + # - "traefik.tcp.routers.postgres.rule=HostSNIRegexp(`^.+\\.furyhawk\\.lol$`)" + # - "traefik.tcp.routers.postgres.tls=true" + # - "traefik.tcp.routers.postgres.tls.certresolver=letsencrypt" + # - "traefik.tcp.routers.postgres.middlewares=test-inflightconn" + # - "traefik.http.routers.postgres.entrypoints=web-secure" + # - "traefik.http.routers.postgres.rule=Host(`db.${DOMAINNAME}`)" + # - "traefik.http.routers.postgres.middlewares=rate-limit@file, csrf@file" + # - "traefik.http.routers.postgres.tls.certresolver=letsencrypt" + # - "traefik.http.routers.postgres.service=postgres_service" + # - "traefik.http.services.postgres_service.loadbalancer.server.port=5432" + + osrm-backend: + environment: + # OSRM manager setup + - OSRM_ALGORITHM=mld + - OSRM_THREADS=2 + - OSRM_PORT=${OSRM_PORT:-5000} + - OSRM_PROFILE=/opt/car.lua + - OSRM_MAP_NAME=${OSRM_MAP_NAME} + - OSRM_GEOFABRIK_PATH=${OSRM_GEOFABRIK_PATH} + # Notify OSRM Manager to restart without stopping container + - OSRM_NOTIFY_FILEPATH=/data/osrm_notify.txt + - DOMAINNAME=${DOMAINNAME} + image: furyhawk/osrm-backend:${OSRM_VERSION:-latest} + restart: unless-stopped + expose: + - ${OSRM_PORT:-5000} + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.osrm-backend.entrypoints=web-secure" + - "traefik.http.routers.osrm-backend.rule=Host(`osrm.${DOMAINNAME}`)" + - "traefik.http.routers.osrm-backend.middlewares=csrf@file" + - "traefik.http.routers.osrm-backend.tls.certresolver=letsencrypt" + - "traefik.http.routers.osrm-backend.service=osrm_backend_service" + - "traefik.http.services.osrm_backend_service.loadbalancer.server.port=${OSRM_PORT:-5000}" + + minio-common: + image: minio/minio:latest + environment: + MINIO_ROOT_USER: "${MINIO_ROOT_USER:-minioadmin}" + MINIO_ROOT_PASSWORD: "${MINIO_ROOT_PASSWORD:-minioadmin}" + MINIO_OPTS: "--console-address :9001" + MINIO_SERVER_URL: https://minio.${DOMAINNAME} + DOMAINNAME: ${DOMAINNAME} + # user: "1000:1000" + restart: unless-stopped + command: server /data --address :9000 --console-address :9001 + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 60s + timeout: 5s + retries: 5 + volumes: + - minio_data:/data + expose: + - 9000 + - 9001 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.minio-router.entrypoints=web-secure" + - "traefik.http.routers.minio-router.rule=Host(`drive.${DOMAINNAME}`) || Host(`storage.${DOMAINNAME}`)" + - "traefik.http.routers.minio-router.middlewares=csrf@file" + - "traefik.http.routers.minio-router.tls.certresolver=letsencrypt" + - "traefik.http.routers.minio-router.service=minio_common_service" + - "traefik.http.services.minio_common_service.loadbalancer.server.port=9001" + - "traefik.http.routers.minio-api-router.entrypoints=web-secure" + - "traefik.http.routers.minio-api-router.rule=Host(`minio.${DOMAINNAME}`) || Host(`s3.${DOMAINNAME}`)" + - "traefik.http.routers.minio-api-router.middlewares=csrf@file" + - "traefik.http.routers.minio-api-router.tls.certresolver=letsencrypt" + - "traefik.http.routers.minio-api-router.service=minio_api_service" + - "traefik.http.services.minio_api_service.loadbalancer.server.port=9000" + + neo4j_server: + # Docker image to be used + image: ${NEO4J_DOCKER_IMAGE:-neo4j:latest} + restart: unless-stopped + # Environment variables + environment: + NEO4J_AUTH: neo4j/${NEO4J_PASSWORD:-12345678} + NEO4J_dbms.default_listen_address: "0.0.0.0" + NEO4J_dbms.default_advertised_address: "neo4j.${DOMAINNAME}" + NEO4J_dbms.connector.bolt.advertised_address: ":443" + NEO4J_PLUGINS: '["apoc"]' + NEO4J_dbms_security_procedures_unrestricted: "apoc.*" + NEO4J_dbms_security_procedures_allowlist: "apoc.*" + NEO4J_server_memory_pagecache_size: 512M + NEO4J_server_memory_heap_max__size: 2G + DOMAINNAME: ${DOMAINNAME} + user: "1000:1000" + depends_on: + - traefik + volumes: + - neo4j_data:/data + - neo4j_logs:/logs + # Expose ports + expose: + - 7474 + - 7687 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.neo4j-router.entrypoints=web-secure" + - "traefik.http.routers.neo4j-router.rule=Host(`neo4j.${DOMAINNAME}`) && PathPrefix(`/neo4j`)||PathPrefix(`/browser`)" + - "traefik.http.routers.neo4j-router.middlewares=csrf@file, neo4j_strip@file" + - "traefik.http.routers.neo4j-router.tls.certresolver=letsencrypt" + - "traefik.http.routers.neo4j-router.service=neo4j_browser" + - "traefik.http.services.neo4j_browser.loadbalancer.server.port=7474" + - "traefik.http.routers.neo4j-bolt-router.entrypoints=web-secure" + - "traefik.http.routers.neo4j-bolt-router.rule=Host(`neo4j.${DOMAINNAME}`)" + - "traefik.http.routers.neo4j-bolt-router.middlewares=csrf@file" + - "traefik.http.routers.neo4j-bolt-router.tls.certresolver=letsencrypt" + - "traefik.http.routers.neo4j-bolt-router.service=neo4j_bolt" + - "traefik.http.services.neo4j_bolt.loadbalancer.server.port=7687" + - "traefik.tcp.routers.neo4j-bolt-router.entrypoints=bolt-socket" + - "traefik.tcp.routers.neo4j-bolt-router.rule=HostSNIRegexp(`^.+\\.furyhawk\\.lol$`)" + - "traefik.tcp.routers.neo4j-bolt-router.tls=true" + - "traefik.tcp.routers.neo4j-bolt-router.tls.certresolver=letsencrypt" + - "traefik.tcp.routers.neo4j-bolt-router.service=neo4j_bolt" + - "traefik.tcp.services.neo4j_bolt.loadbalancer.server.port=7687" + + syncthing: + image: syncthing/syncthing + environment: + - PUID=1000 + - PGID=1000 + - DOMAINNAME=${DOMAINNAME} + restart: unless-stopped + volumes: + - ~/st-sync:/var/syncthing + ports: + - "8384:8384" # Web UI + - "22000:22000/tcp" # TCP file transfers + - "22000:22000/udp" # QUIC file transfers + - "21027:21027/udp" # Receive local discovery broadcasts + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.syncthing.entrypoints=web-secure" + - "traefik.http.routers.syncthing.rule=Host(`sync.${DOMAINNAME}`)" + - "traefik.http.routers.syncthing.middlewares=csrf@file" + - "traefik.http.routers.syncthing.tls.certresolver=letsencrypt" + - "traefik.http.routers.syncthing.service=syncthing_service" + - "traefik.http.services.syncthing_service.loadbalancer.server.port=8384" + + dozzle: + image: amir20/dozzle:latest + restart: always + environment: + - DOMAINNAME=${DOMAINNAME} + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + expose: + - 8080 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.dozzle.entrypoints=web-secure" + - "traefik.http.routers.dozzle.rule=Host(`log.${DOMAINNAME}`)" + - "traefik.http.routers.dozzle.middlewares=auth@file, csrf@file" + - "traefik.http.routers.dozzle.tls.certresolver=letsencrypt" + - "traefik.http.routers.dozzle.service=dozzle_service" + - "traefik.http.services.dozzle_service.loadbalancer.server.port=8080" + + # WhoAmI - For Testing and Troubleshooting + whoami: + image: traefik/whoami + security_opt: + - no-new-privileges:true + restart: unless-stopped + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.whoami-rtr.entrypoints=web-secure" + - "traefik.http.routers.whoami-rtr.rule=Host(`whoami.$DOMAINNAME`)" + - "traefik.http.routers.whoami-rtr.middlewares=csrf@file" + - "traefik.http.routers.whoami-rtr.tls.certresolver=letsencrypt" + - "traefik.http.routers.whoami-rtr.service=whoami-svc" + - "traefik.http.services.whoami-svc.loadbalancer.server.port=80" + + # kestra: + # image: kestra/kestra:latest-full + # container_name: kestra + # # pull_policy: always + # # Note that this is meant for development only. Refer to the documentation for production deployments of Kestra which runs without a root user. + # user: "root" + # command: server standalone --worker-thread=128 + # environment: + # KESTRA_CONFIGURATION: | + # datasources: + # postgres: + # url: jdbc:postgresql://postgres:5432/kestra + # driverClassName: org.postgresql.Driver + # username: ${POSTGRES_USER} + # password: ${POSTGRES_PASSWORD} + # kestra: + # server: + # basic-auth: + # enabled: true + # username: ${EMAIL_FROM} # it must be a valid email address + # password: ${EMAIL_PASSWORD} + # repository: + # type: postgres + # storage: + # type: local + # local: + # base-path: "/app/storage" + # queue: + # type: postgres + # tasks: + # tmp-dir: + # path: /tmp/kestra-wd/tmp + # url: http://kestra.${DOMAINNAME}/ + # volumes: + # - kestra_data:/app/storage + # - /var/run/docker.sock:/var/run/docker.sock + # # - /tmp/kestra-wd:/tmp/kestra-wd + # depends_on: + # - postgres + # expose: + # - "8080" + # - "8081" + # networks: + # - net + + adminer: + image: adminer + environment: + PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL} + PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD} + PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + PYTHONPATH: "/pgadmin4" + TZ: Asia/Singapore + DOMAINNAME: ${DOMAINNAME} + volumes: + - pgadmin:/var/lib/pgadmin + restart: unless-stopped + depends_on: + - postgres + expose: + - 8080 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.adminer.entrypoints=web-secure" + - "traefik.http.routers.adminer.rule=Host(`adminer.${DOMAINNAME}`) || Host(`dbadmin.${DOMAINNAME}`)" + - "traefik.http.routers.adminer.middlewares=csrf@file" + - "traefik.http.routers.adminer.tls.certresolver=letsencrypt" + - "traefik.http.routers.adminer.service=adminer_app" + - "traefik.http.services.adminer_app.loadbalancer.server.port=8080" + + cheatsheets_app: + image: furyhawk/cheatsheets:${CHEATSHEETSTAG:-latest} + restart: unless-stopped + expose: + - 80 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.cheatsheets.entrypoints=web-secure" + - "traefik.http.routers.cheatsheets.rule=Host(`cheat.${DOMAINNAME}`)" + - "traefik.http.routers.cheatsheets.middlewares=csrf@file" + - "traefik.http.routers.cheatsheets.tls.certresolver=letsencrypt" + - "traefik.http.routers.cheatsheets.service=cheatsheets_app" + - "traefik.http.services.cheatsheets_app.loadbalancer.server.port=80" + + ghost-db: + image: mysql:8 + security_opt: + - seccomp:unconfined + restart: always + command: --mysql-native-password=ON + environment: + MYSQL_ROOT_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - ghost_mysql:/var/lib/mysql + expose: + - 3306 + networks: + - net + + ghost-server: + image: ghost + cap_add: + - CAP_SYS_NICE + security_opt: + - seccomp:unconfined + restart: always + depends_on: + - ghost-db + environment: + url: https://ghost.${DOMAINNAME} + database__client: mysql + database__connection__host: ghost-db + database__connection__user: root + database__connection__password: ${POSTGRES_PASSWORD} + database__connection__database: ghost + DOMAINNAME: ${DOMAINNAME} + volumes: + - ghost_content:/var/lib/ghost/content + expose: + - 2368 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.ghost.entrypoints=web-secure" + - "traefik.http.routers.ghost.rule=Host(`ghost.${DOMAINNAME}`)" + - "traefik.http.routers.ghost.middlewares=csrf@file" + - "traefik.http.routers.ghost.tls.certresolver=letsencrypt" + - "traefik.http.routers.ghost.service=ghost_app" + - "traefik.http.services.ghost_app.loadbalancer.server.port=2368" + + heynote_app: + image: furyhawk/heynote:${HEYNOTETAG:-latest} + restart: unless-stopped + environment: + NODE_ENV: production + DOMAINNAME: ${DOMAINNAME} + expose: + - 5173 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.heynote.entrypoints=web-secure" + - "traefik.http.routers.heynote.rule=HostRegexp(`note[0-9]{0,2}.${DOMAINNAME}`) || Host(`pad.${DOMAINNAME}`)" + - "traefik.http.routers.heynote.middlewares=csrf@file" + - "traefik.http.routers.heynote.tls.certresolver=letsencrypt" + - "traefik.http.routers.heynote.service=heynote_app" + - "traefik.http.services.heynote_app.loadbalancer.server.port=5173" + + jellyfin: + image: jellyfin/jellyfin + user: 1000:1000 + volumes: + - jellyfin_config:/config + - jellyfin_cache:/cache + - type: bind + source: ~/media + target: /media + read_only: false + restart: 'unless-stopped' + # Optional - alternative address used for autodiscovery + environment: + - DOMAINNAME=${DOMAINNAME} + - JELLYFIN_PublishedServerUrl=https://media.${DOMAINNAME} + expose: + - 8096 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.jellyfin.entrypoints=web-secure" + - "traefik.http.routers.jellyfin.rule=Host(`media.${DOMAINNAME}`)" + - "traefik.http.routers.jellyfin.middlewares=csrf@file" + - "traefik.http.routers.jellyfin.tls.certresolver=letsencrypt" + - "traefik.http.routers.jellyfin.service=jellyfin_app" + - "traefik.http.services.jellyfin_app.loadbalancer.server.port=8096" + + meshtastic_web: + image: ghcr.io/meshtastic/web + restart: unless-stopped + expose: + - 8080 + - 8443 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.meshtastic.entrypoints=web-secure" + - "traefik.http.routers.meshtastic.rule=Host(`mesh.${DOMAINNAME}`)" + - "traefik.http.routers.meshtastic.middlewares=csrf@file" + - "traefik.http.routers.meshtastic.tls.certresolver=letsencrypt" + - "traefik.http.routers.meshtastic.service=meshtastic_app" + - "traefik.http.services.meshtastic_app.loadbalancer.server.port=8080" + + pgadmin: + image: dpage/pgadmin4 + environment: + PGADMIN_DEFAULT_EMAIL: "${PGADMIN_DEFAULT_EMAIL}" + PGADMIN_DEFAULT_PASSWORD: "${PGADMIN_DEFAULT_PASSWORD}" + volumes: + - pgadmin_data:/var/lib/pgadmin + restart: unless-stopped + depends_on: + - postgres + expose: + - 80 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.pgadmin.entrypoints=web-secure" + - "traefik.http.routers.pgadmin.rule=Host(`pgadmin.${DOMAINNAME}`)" + - "traefik.http.routers.pgadmin.middlewares=csrf@file" + - "traefik.http.routers.pgadmin.tls.certresolver=letsencrypt" + - "traefik.http.routers.pgadmin.service=pgadmin_app" + - "traefik.http.services.pgadmin_app.loadbalancer.server.port=80" + + privatebin: + image: privatebin/nginx-fpm-alpine:latest + read_only: true + user: "1000:1000" + volumes: + - privatebin_data:/srv/data # data volume for pastes allows pastes + # to persist after container stop or restart + - "~/config/conf.php:/srv/cfg/conf.php:ro" # second volume for custom configuration file + expose: + - 8080 + restart: unless-stopped + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.privatebin.entrypoints=web-secure" + - "traefik.http.routers.privatebin.rule=Host(`bin.${DOMAINNAME}`) || Host(`paste.${DOMAINNAME}`)" + - "traefik.http.routers.privatebin.middlewares=csrf@file" + - "traefik.http.routers.privatebin.tls.certresolver=letsencrypt" + - "traefik.http.routers.privatebin.service=privatebin_app" + - "traefik.http.services.privatebin_app.loadbalancer.server.port=8080" + + redlib: + # disable container temporarily + profiles: + - donotstart + image: quay.io/redlib/redlib:latest-arm + restart: unless-stopped + user: nobody + read_only: true + security_opt: + - no-new-privileges:true + # - seccomp=seccomp-redlib.json + cap_drop: + - ALL + env_file: .env + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "--tries=1", "http://127.0.0.1:3080/settings"] + interval: 5m + timeout: 3s + expose: + - 3080 # Specify `127.0.0.1:8080:3080` instead if using a reverse proxy + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.redlib.entrypoints=web-secure" + - "traefik.http.routers.redlib.rule=Host(`redlib.${DOMAINNAME}`)" + - "traefik.http.routers.redlib.middlewares=csrf@file" + - "traefik.http.routers.redlib.tls.certresolver=letsencrypt" + - "traefik.http.routers.redlib.service=redlib_app" + - "traefik.http.services.redlib_app.loadbalancer.server.port=3080" + + thelounge: + image: ghcr.io/thelounge/thelounge:latest + restart: unless-stopped + volumes: + - thelounge_data:/var/opt/thelounge # bind lounge config from the host's file system + expose: + - 9000 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.thelounge.entrypoints=web-secure" + - "traefik.http.routers.thelounge.rule=Host(`irc.${DOMAINNAME}`)" + - "traefik.http.routers.thelounge.middlewares=csrf@file" + - "traefik.http.routers.thelounge.tls.certresolver=letsencrypt" + - "traefik.http.routers.thelounge.service=thelounge_app" + - "traefik.http.services.thelounge_app.loadbalancer.server.port=9000" + + streamlit-bai: + environment: + <<: *default-environment + image: furyhawk/beyondallinfo:latest + restart: unless-stopped + command: streamlit run --server.port=$STREAMLIT_BAI_SERVER_PORT --server.address=0.0.0.0 --server.baseUrlPath=$BAI_LOCATION src/app.py + volumes: + - bai_cache:/app/cache + expose: + - ${STREAMLIT_BAI_SERVER_PORT} + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.streamlit-bai.entrypoints=web-secure" + - "traefik.http.routers.streamlit-bai.rule=Host(`bai.${DOMAINNAME}`)" + - "traefik.http.routers.streamlit-bai.middlewares=csrf@file" + - "traefik.http.routers.streamlit-bai.tls.certresolver=letsencrypt" + - "traefik.http.routers.streamlit-bai.service=streamlit_bai_app" + - "traefik.http.services.streamlit_bai_app.loadbalancer.server.port=${STREAMLIT_BAI_SERVER_PORT}" + + streamlit-fin: + environment: + <<: *default-environment + image: furyhawk/llama3toolsfin:main + restart: unless-stopped + expose: + - ${STREAMLIT_FIN_SERVER_PORT} + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.streamlit-fin.entrypoints=web-secure" + - "traefik.http.routers.streamlit-fin.rule=Host(`fin.${DOMAINNAME}`)" + - "traefik.http.routers.streamlit-fin.middlewares=csrf@file" + - "traefik.http.routers.streamlit-fin.tls.certresolver=letsencrypt" + - "traefik.http.routers.streamlit-fin.service=streamlit_fin_app" + - "traefik.http.services.streamlit_fin_app.loadbalancer.server.port=${STREAMLIT_FIN_SERVER_PORT}" + + site_server: + image: nginx:alpine + restart: unless-stopped + volumes: + - ~/site:/usr/share/nginx/html:ro + expose: + - 80 + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.site_server.entrypoints=web-secure" + - "traefik.http.routers.site_server.rule=Host(`${DOMAINNAME}`) || Host(`www.${DOMAINNAME}`) || Host(`info.${DOMAINNAME}`) || Host(`124c41.${DOMAINNAME}`)" + - "traefik.http.routers.site_server.middlewares=csrf@file, no-www@file" + - "traefik.http.routers.site_server.tls.certresolver=letsencrypt" + - "traefik.http.routers.site_server.service=site_server_app" + - "traefik.http.services.site_server_app.loadbalancer.server.port=80" + - "traefik.http.routers.resume_router.entrypoints=web-secure" + - "traefik.http.routers.resume_router.rule=Host(`resume.${DOMAINNAME}`)" + - "traefik.http.routers.resume_router.middlewares=csrf@file, redirect-resume@file" + - "traefik.http.routers.resume_router.tls.certresolver=letsencrypt" + - "traefik.http.routers.resume_router.service=resume_server" + - "traefik.http.services.resume_server.loadbalancer.server.port=80" + - "traefik.http.routers.blog_router.entrypoints=web-secure" + - "traefik.http.routers.blog_router.rule=Host(`blog.${DOMAINNAME}`)" + - "traefik.http.routers.blog_router.middlewares=redirect-blog@file" + - "traefik.http.routers.blog_router.tls.certresolver=letsencrypt" + - "traefik.http.routers.blog_router.service=blog_server" + - "traefik.http.services.blog_server.loadbalancer.server.port=80" + + emqx1: + image: emqx:latest + # environment: + # - "EMQX_NODE_NAME=emqx@node1.emqx.io" + # - "EMQX_CLUSTER__DISCOVERY_STRATEGY=static" + # - "EMQX_CLUSTER__STATIC__SEEDS=[emqx@node1.emqx.io,emqx@node2.emqx.io]" + healthcheck: + test: ["CMD", "/opt/emqx/bin/emqx", "ctl", "status"] + interval: 60s + timeout: 25s + retries: 5 + networks: + net: + # emqx-bridge: + # aliases: + # - node1.emqx.io + ports: + - "1883:1883" + # - 8083:8083 + # - 8084:8084 + # - 8883:8883 + # - 18083:18083 + volumes: + - vol-emqx-data1:/opt/emqx/data + labels: + - "traefik.enable=true" + - "traefik.http.routers.emqx1.entrypoints=web-secure" + - "traefik.http.routers.emqx1.rule=Host(`mqtt.${DOMAINNAME}`)" + - "traefik.http.routers.emqx1.tls.certresolver=letsencrypt" + - "traefik.http.routers.emqx1.service=emqx-dashboard" + - "traefik.http.services.emqx-dashboard.loadbalancer.server.port=18083" + + # emqx2: + # image: emqx:latest + # container_name: emqx2 + # environment: + # - "EMQX_NODE_NAME=emqx@node2.emqx.io" + # - "EMQX_CLUSTER__DISCOVERY_STRATEGY=static" + # - "EMQX_CLUSTER__STATIC__SEEDS=[emqx@node1.emqx.io,emqx@node2.emqx.io]" + # healthcheck: + # test: ["CMD", "/opt/emqx/bin/emqx", "ctl", "status"] + # interval: 60s + # timeout: 25s + # retries: 5 + # networks: + # net: + # emqx-bridge: + # aliases: + # - node2.emqx.io + # volumes: + # - vol-emqx-data2:/opt/emqx/data + + mqttx-web: + image: emqx/mqttx-web:latest + restart: unless-stopped + networks: + - net + labels: + - "traefik.enable=true" + - "traefik.http.routers.mqttx-web.entrypoints=web-secure" + - "traefik.http.routers.mqttx-web.rule=Host(`mqttx.${DOMAINNAME}`)" + - "traefik.http.routers.mqttx-web.tls.certresolver=letsencrypt" + - "traefik.http.routers.mqttx-web.service=mqttx-web-service" + - "traefik.http.services.mqttx-web-service.loadbalancer.server.port=80" + + librechat_api: + ports: + - "${PORT}:${PORT}" + depends_on: + - mongodb + - rag_api + image: ghcr.io/danny-avila/librechat-dev:latest + restart: always + user: "${UID}:${GID}" + extra_hosts: + - "host.docker.internal:host-gateway" + environment: + - HOST=0.0.0.0 + - MONGO_URI=mongodb://mongodb:27017/LibreChat + - MEILI_HOST=http://meilisearch:7700 + - RAG_PORT=${RAG_PORT:-8000} + - RAG_API_URL=http://rag_api:${RAG_PORT:-8000} + - DOMAINNAME=${DOMAINNAME} + volumes: + - type: bind + source: ~/config/.env + target: /app/.env + - libre-images:/app/client/public/images + - libre-logs:/app/api/logs + - type: bind + source: ./config/librechat.yaml + target: /app/librechat.yaml + labels: + - "traefik.enable=true" + - "traefik.http.routers.librechat.entrypoints=web-secure" + - "traefik.http.routers.librechat.rule=Host(`chat.${DOMAINNAME}`) || Host(`bot.${DOMAINNAME}`)" + - "traefik.http.routers.librechat.middlewares=csrf@file" + - "traefik.http.routers.librechat.tls.certresolver=letsencrypt" + - "traefik.http.routers.librechat.service=librechat_app" + - "traefik.http.services.librechat_app.loadbalancer.server.port=${PORT}" + mongodb: + image: mongo + restart: always + user: "${UID}:${GID}" + volumes: + - data-node:/data/db + command: mongod --noauth + meilisearch: + image: getmeili/meilisearch:v1.7.3 + restart: always + user: "${UID}:${GID}" + environment: + - MEILI_HOST=http://meilisearch:7700 + - MEILI_NO_ANALYTICS=true + volumes: + - meili_data:/meili_data + vectordb: + image: ankane/pgvector:latest + environment: + POSTGRES_DB: mydatabase + POSTGRES_USER: myuser + POSTGRES_PASSWORD: mypassword + restart: always + volumes: + - pgdata2:/var/lib/postgresql/data + rag_api: + image: ghcr.io/danny-avila/librechat-rag-api-dev:latest + environment: + POSTGRES_DB: mydatabase + POSTGRES_USER: myuser + POSTGRES_PASSWORD: mypassword + DB_HOST: vectordb + RAG_PORT: ${RAG_PORT:-8000} + restart: always + depends_on: + - vectordb + env_file: + - ~/config/.env + + +