diff --git a/.github/workflows/deploy-cloud.yaml b/.github/workflows/deploy-cloud.yaml index 36e64199..43a75915 100644 --- a/.github/workflows/deploy-cloud.yaml +++ b/.github/workflows/deploy-cloud.yaml @@ -128,6 +128,9 @@ jobs: # Replace placeholder with actual domain from secrets sed -i "s|__CUBE_DOMAIN__|${{ secrets.CUBE_DOMAIN }}|g" docker/traefik/dynamic.toml + # Accept EULA for Cube UI Docker image + sed -i "s|UV_CUBE_UI_DOCKER_ACCEPT_EULA=no|UV_CUBE_UI_DOCKER_ACCEPT_EULA=yes|g" docker/.env + echo "Pulling latest Docker images" docker compose -f docker/compose.yaml --profile cloud pull 2>&1 diff --git a/docker/.env b/docker/.env index 374ee090..a7da1268 100644 --- a/docker/.env +++ b/docker/.env @@ -228,21 +228,6 @@ UV_CUBE_AGENT_ATTESTED_TLS=true UV_CUBE_AGENT_ATTESTATION_POLICY=/etc/cube/tdx_policy.json UV_CUBE_AGENT_PRODUCT_NAME=Milan -#UI -MG_MAILCHIMP_API_KEY=__MG_MAILCHIMP_API_KEY__ -MG_MAILCHIMP_SERVER_PREFIX=__MG_MAILCHIMP_SERVER_PREFIX__ -MG_MAILCHIMP_AUDIENCE_ID=__MG_MAILCHIMP_AUDIENCE_ID__ -UV_CUBE_UI_NAME="Cube AI" -UI_PORT=6193 -UV_RUNTIME_ENV=production -UV_CUBE_UI_BASE_PATH=/ -UV_CUBE_PUBLIC_BASE_PATH=/ -MG_UI_TYPE=cube-ai -UV_CUBE_UI_NEXTAUTH_SECRET="cZAcFIdjxebC1XDULvfoXs_sO7ufCTRo3hW2lXtMoCvcSKkTyP" -# change IP address to your local IP address -UV_CUBE_NEXTAUTH_URL=https://__CUBE_PUBLIC_URL__ -UV_CUBE_UI_DOCKER_ACCEPT_EULA=yes -UV_CUBE_NODE_ENV= #vllm NVIDIA_VISIBLE_DEVICES=all @@ -262,6 +247,7 @@ UV_GUARDRAILS_DB_PORT=5432 UV_GUARDRAILS_DB_USER=guardrails UV_GUARDRAILS_DB_PASS=guardrails UV_GUARDRAILS_DB_NAME=guardrails +GUARDRAILS_BASE_URL=http://guardrails:8001 ## Traefik Configuration TRAEFIK_HTTP_PORT=__TRAEFIK_HTTP_PORT__ @@ -322,6 +308,23 @@ AM_CERTS_DB_MAX_CONNECTIONS=100 # Cube Agent Certs Token UV_CUBE_AGENT_CERTS_TOKEN=__CUBE_AGENT_CERTS_TOKEN__ +#UI +MG_MAILCHIMP_API_KEY=__MG_MAILCHIMP_API_KEY__ +MG_MAILCHIMP_SERVER_PREFIX=__MG_MAILCHIMP_SERVER_PREFIX__ +MG_MAILCHIMP_AUDIENCE_ID=__MG_MAILCHIMP_AUDIENCE_ID__ +UI_PORT=6193 +UV_CUBE_UI_BASE_PATH=/ +MG_UI_TYPE=cube-ai +NEXTAUTH_SECRET= +# change IP address to your local IP address +NEXTAUTH_URL=https://__CUBE_PUBLIC_URL__ +UV_CUBE_UI_DOCKER_ACCEPT_EULA=no +MG_UI_BASE_PATH=/ +MG_NEXTAUTH_BASE_PATH=/api/auth +MG_HOST_URL=https://__CUBE_PUBLIC_URL__ +MG_UI_BASEURL=https://__CUBE_PUBLIC_URL__ +MG_UI_IMAGE_URL=http://magistrala-backend:9097 + ## Magistrala-UI-Backend Env Var MG_BACKEND_LOG_LEVEL=debug MG_BACKEND_HTTP_HOST=magistrala-backend @@ -355,11 +358,8 @@ MG_BACKEND_OBJECT_STORAGE_SECRET_KEY=localSecret MG_BACKEND_OBJECT_STORAGE_WRITE_TTL=1m MG_BACKEND_OBJECT_STORAGE_READ_TTL=15m MG_POSTGRES_MAX_CONNECTIONS=100 -MG_UI_DOCKER_ACCEPT_EULA=yes -MG_UI_RELEASE_TAG=latest -MG_BACKEND_RELEASE_TAG=latest +MG_RELEASE_TAG=latest MG_BACKEND_URL=http://magistrala-backend:9097 -MG_UI_IMAGE_URL=http://magistrala-backend:9097 # LLM response timeouts UV_CUBE_PROXY_SERVER_WRITE_TIMEOUT=120s diff --git a/docker/config.json b/docker/config.json index 68c4f1e6..d58fa2f1 100644 --- a/docker/config.json +++ b/docker/config.json @@ -95,4 +95,4 @@ "min_version": 771, "max_version": 772 } -} \ No newline at end of file +} diff --git a/docker/cube-compose.yaml b/docker/cube-compose.yaml index 30f1131f..0f37bdb4 100644 --- a/docker/cube-compose.yaml +++ b/docker/cube-compose.yaml @@ -386,8 +386,54 @@ services: entrypoint: /bin/sh command: /entrypoint.sh + ui: + image: ghcr.io/absmach/magistrala/ui-cube-ai:${MG_RELEASE_TAG} + container_name: cube-ui + restart: always + depends_on: + - auth + - users + - domains + networks: + - cube-network + environment: + PORT: ${UI_PORT} + MG_DOMAINS_URL: ${SMQ_DOMAINS_URL} + MG_USERS_URL: ${SMQ_USERS_URL} + MG_BACKEND_URL: ${MG_BACKEND_URL} + MG_AUTH_URL: ${SMQ_AUTH_URL} + MG_UI_IMAGE_URL: ${MG_UI_IMAGE_URL} + MG_UI_BASE_PATH: ${UV_CUBE_UI_BASE_PATH} + MG_NEXTAUTH_BASE_PATH: ${MG_NEXTAUTH_BASE_PATH} + MG_UI_TYPE: cube-ai + NEXTAUTH_SECRET: ${NEXTAUTH_SECRET} + NEXTAUTH_URL: ${NEXTAUTH_URL} + MG_HOST_URL: ${MG_HOST_URL} + MG_UI_BASEURL: ${MG_UI_BASEURL} + MG_ACCESS_TOKEN_EXPIRY: ${SMQ_AUTH_ACCESS_TOKEN_DURATION} + MG_REFRESH_TOKEN_EXPIRY: ${SMQ_AUTH_REFRESH_TOKEN_DURATION} + MG_UI_SMTP_HOST: ${SMQ_EMAIL_HOST} + MG_UI_SMTP_PORT: ${SMQ_EMAIL_PORT} + MG_UI_SMTP_SECURE: ${MG_UI_SMTP_SECURE} + MG_UI_SUPPORT_FROM: ${SMQ_EMAIL_FROM_ADDRESS} + MG_SUPPORT_EMAIL: ${SMQ_EMAIL_USERNAME} + MG_SUPPORT_EMAIL_PASS: ${SMQ_EMAIL_PASSWORD} + MG_GOOGLE_CLIENT_ID: ${SMQ_GOOGLE_CLIENT_ID} + MG_GOOGLE_CLIENT_SECRET: ${SMQ_GOOGLE_CLIENT_SECRET} + MG_GOOGLE_REDIRECT_URL: ${SMQ_GOOGLE_REDIRECT_URL} + MG_GOOGLE_STATE: ${SMQ_GOOGLE_STATE} + MG_MAILCHIMP_API_KEY: ${MG_MAILCHIMP_API_KEY} + MG_MAILCHIMP_SERVER_PREFIX: ${MG_MAILCHIMP_SERVER_PREFIX} + MG_MAILCHIMP_AUDIENCE_ID: ${MG_MAILCHIMP_AUDIENCE_ID} + MG_UI_ALLOW_UNVERIFIED_USER: ${SMQ_ALLOW_UNVERIFIED_USER} + MG_UI_DOCKER_ACCEPT_EULA: ${UV_CUBE_UI_DOCKER_ACCEPT_EULA} + CUBE_AI_PROXY_URL: ${CUBE_AI_PROXY_URL} + OLLAMA_BASE_URL: ${UV_CUBE_UI_LLM_BASE_URL} + OLLAMA_DEFAULT_MODEL: ${UV_CUBE_UI_LLM_DEFAULT_MODEL} + GUARDRAILS_BASE_URL: ${GUARDRAILS_BASE_URL} + magistrala-backend: - image: ghcr.io/absmach/magistrala/ui-backend:${MG_BACKEND_RELEASE_TAG} + image: ghcr.io/absmach/magistrala/ui-backend:${MG_RELEASE_TAG} container_name: magistrala-backend restart: on-failure networks: @@ -415,7 +461,7 @@ services: MG_AUTH_GRPC_SERVER_CA_CERTS: ${MG_AUTH_GRPC_SERVER_CA_CERTS:+/auth-grpc-server-ca.crt} MG_UI_VERIFICATION_TLS: ${MG_UI_VERIFICATION_TLS} MG_UI_CONTENT_TYPE: ${MG_UI_CONTENT_TYPE} - MG_UI_DOCKER_ACCEPT_EULA: ${MG_UI_DOCKER_ACCEPT_EULA} + MG_UI_DOCKER_ACCEPT_EULA: ${UV_CUBE_UI_DOCKER_ACCEPT_EULA} MG_BACKEND_OBJECT_STORAGE_REGION: ${MG_BACKEND_OBJECT_STORAGE_REGION} MG_BACKEND_OBJECT_STORAGE_BUCKET: ${MG_BACKEND_OBJECT_STORAGE_BUCKET} MG_BACKEND_OBJECT_STORAGE_ENDPOINT: ${MG_BACKEND_OBJECT_STORAGE_ENDPOINT} @@ -453,7 +499,6 @@ services: target: /etc/ssl/certs/ca.crt read_only: true - magistrala-ui-backend-db: image: postgres:16.2-alpine container_name: magistrala-ui-backend-db @@ -470,39 +515,39 @@ services: command: postgres -c "max_connections=${MG_POSTGRES_MAX_CONNECTIONS}" magistrala-seaweedfs-s3: - image: chrislusf/seaweedfs:${SEAWEEDFS_VERSION:-3.68} + image: chrislusf/seaweedfs:4.16 container_name: magistrala-seaweedfs-s3 - command: server -s3 -dir=/data + command: server -s3 -s3.config=/etc/seaweedfs/s3.json -dir=/data + restart: on-failure:5 ports: - "8333:8333" # S3 endpoint volumes: - ./data/seaweedfs:/data + - ./seaweedfs/s3.json:/etc/seaweedfs/s3.json:ro networks: - cube-network magistrala-seaweedfs-init: - image: curlimages/curl + image: amazon/aws-cli container_name: magistrala-seaweedfs-init + entrypoint: /bin/sh depends_on: - magistrala-seaweedfs-s3 - command: > - /bin/sh -c " - echo \"Creating bucket $${BUCKET}, wait for 25s...\"; - sleep 25; - HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' -f -X PUT http://magistrala-seaweedfs-s3:8333/$${BUCKET}); - if [ $${HTTP_CODE} = '200' ] || [ $${HTTP_CODE} = '201' ] || [ $${HTTP_CODE} = '409' ]; then - if [ $${HTTP_CODE} = '409' ]; then - echo \"[INIT] Bucket $${BUCKET} already exists.\"; + command: + - -c + - | + echo "[INIT] Waiting 20s for SeaweedFS S3 to be ready..."; + sleep 20; + OUT=$(aws --endpoint-url http://magistrala-seaweedfs-s3:8333 s3api create-bucket --bucket $${BUCKET} 2>&1); + EXIT=$$?; + if [ $$EXIT -eq 0 ]; then + echo "[INIT] Bucket $${BUCKET} created successfully."; + elif echo "$$OUT" | grep -q 'BucketAlreadyOwnedByYou\|BucketAlreadyExists'; then + echo "[INIT] Bucket $${BUCKET} already exists, skipping."; else - echo \"[INIT] Bucket $${BUCKET} created successfully!\"; + echo "[INIT] Failed to create bucket $${BUCKET}: $$OUT" >&2; + exit 1; fi - curl -s http://magistrala-seaweedfs-s3:8333/ | grep -o '[^<]*'; - exit 0; - else - echo \"[INIT] Failed to create bucket $${BUCKET}! HTTP code $${HTTP_CODE}.\" >&2; - exit 1; - fi - " networks: - cube-network environment: diff --git a/docker/seaweedfs/s3.json b/docker/seaweedfs/s3.json index 98b5e34e..321024df 100644 --- a/docker/seaweedfs/s3.json +++ b/docker/seaweedfs/s3.json @@ -1,7 +1,7 @@ { "identities": [ { - "name": "localuser", + "name": "magistrala", "credentials": [ { "accessKey": "localKey", @@ -10,8 +10,5 @@ ], "actions": ["Admin", "Read", "Write"] } - ], - "s3": { - "region": "fra1" - } + ] } diff --git a/docker/supermq-compose.yaml b/docker/supermq-compose.yaml index 5349e5e9..4a23a521 100644 --- a/docker/supermq-compose.yaml +++ b/docker/supermq-compose.yaml @@ -319,47 +319,6 @@ services: networks: - cube-network - ui: - image: ghcr.io/absmach/magistrala/ui-cube-ai:${MG_UI_RELEASE_TAG} - container_name: cube-ui - restart: on-failure - depends_on: - - auth - - users - - domains - networks: - - cube-network - environment: - PORT: ${UI_PORT} - RUNTIME_ENV: ${UV_RUNTIME_ENV} - MG_DOMAINS_URL: ${SMQ_DOMAINS_URL} - MG_USERS_URL: ${SMQ_USERS_URL} - MG_INVITATIONS_URL: ${SMQ_INVITATIONS_URL} - MG_AUTH_URL: ${SMQ_AUTH_URL} - MG_UI_NAME: ${UV_CUBE_UI_NAME} - MG_UI_BASE_PATH: ${UV_CUBE_UI_BASE_PATH} - MG_UI_DOCKER_ACCEPT_EULA: ${UV_CUBE_UI_DOCKER_ACCEPT_EULA} - NEXT_PUBLIC_SMQ_UI_BASE_PATH: ${UV_CUBE_PUBLIC_BASE_PATH} - MG_UI_TYPE: ${MG_UI_TYPE} - NEXTAUTH_SECRET: ${UV_CUBE_UI_NEXTAUTH_SECRET} - NEXTAUTH_URL: ${UV_CUBE_NEXTAUTH_URL} - NODE_ENV: ${UV_CUBE_NODE_ENV} - OLLAMA_BASE_URL: ${UV_CUBE_UI_LLM_BASE_URL} - OLLAMA_DEFAULT_MODEL: ${UV_CUBE_UI_LLM_DEFAULT_MODEL} - CUBE_AI_PROXY_URL: ${CUBE_AI_PROXY_URL} - MG_GOOGLE_CLIENT_ID: ${SMQ_GOOGLE_CLIENT_ID} - MG_GOOGLE_CLIENT_SECRET: ${SMQ_GOOGLE_CLIENT_SECRET} - MG_GOOGLE_REDIRECT_URL: ${SMQ_GOOGLE_REDIRECT_URL} - MG_GOOGLE_STATE: ${SMQ_GOOGLE_STATE} - MG_HOST_URL: ${UV_CUBE_NEXTAUTH_URL} - MG_MAILCHIMP_API_KEY: ${MG_MAILCHIMP_API_KEY} - MG_MAILCHIMP_SERVER_PREFIX: ${MG_MAILCHIMP_SERVER_PREFIX} - MG_MAILCHIMP_AUDIENCE_ID: ${MG_MAILCHIMP_AUDIENCE_ID} - MG_UI_ALLOW_UNVERIFIED_USER: ${SMQ_ALLOW_UNVERIFIED_USER} - MG_BACKEND_URL: ${MG_BACKEND_URL} - MG_UI_IMAGE_URL: ${MG_UI_IMAGE_URL} - - domains-db: image: postgres:16.2-alpine container_name: supermq-domains-db