Skip to content
Open
588 changes: 577 additions & 11 deletions deploy/common/common.sh

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions deploy/docker/assets/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Nexent HTTPS reverse proxy (Nginx)
# Terminates TLS on a dedicated HTTPS port (3100) and proxies to nexent-web,
# which keeps serving plain HTTP on port 3000.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

server {
listen 3100 ssl;
server_name _;

# TLS termination (cert/key mounted read-only by the deployment script)
ssl_certificate /etc/nginx/ssl/server.pem;
ssl_certificate_key /etc/nginx/ssl/server.key;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

client_max_body_size 1024M;

# SSE: disable buffering; keep long-lived streams stable
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 60s;

location / {
proxy_pass http://nexent-web:3000;
proxy_http_version 1.1;

# WebSocket upgrade
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

# Forwarded headers (Supabase callbacks and backend URL building rely on these)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
22 changes: 21 additions & 1 deletion deploy/docker/compose/docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ services:
networks:
- nexent
ports:
- "3000:3000"
- "${NEXENT_WEB_PORT:-3000}:3000"
volumes:
- ${ROOT_DIR}/project-config:/mnt/nexent-data/project-config
environment:
Expand All @@ -225,6 +225,26 @@ services:
max-size: "10m" # Maximum size of a single log file
max-file: "3" # Maximum number of log files to keep


nexent-nginx:
image: ${NGINX_IMAGE:-nginx:alpine}
container_name: nexent-nginx
restart: always
profiles:
- https
networks:
- nexent
ports:
- "${NEXENT_HTTPS_PORT:-3100}:3100"
volumes:
- ${ROOT_DIR}/nginx/ssl:/etc/nginx/ssl:ro
- ../assets/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

nexent-data-process:
image: ${NEXENT_DATA_PROCESS_IMAGE}
container_name: nexent-data-process
Expand Down
22 changes: 21 additions & 1 deletion deploy/docker/compose/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ services:
networks:
- nexent
ports:
- "3000:3000"
- "${NEXENT_WEB_PORT:-3000}:3000"
volumes:
- ${ROOT_DIR}/project-config:/mnt/nexent-data/project-config
env_file:
Expand All @@ -247,6 +247,26 @@ services:
max-size: "10m" # Maximum size of a single log file
max-file: "3" # Maximum number of log files to keep


nexent-nginx:
image: ${NGINX_IMAGE:-nginx:alpine}
container_name: nexent-nginx
restart: always
profiles:
- https
networks:
- nexent
ports:
- "3100:3100"
volumes:
- ${ROOT_DIR}/nginx/ssl:/etc/nginx/ssl:ro
- ../assets/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

nexent-data-process:
image: ${NEXENT_DATA_PROCESS_IMAGE}
container_name: nexent-data-process
Expand Down
41 changes: 39 additions & 2 deletions deploy/docker/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,31 @@
fi
}

deploy_https_nginx() {
# Start the Nginx HTTPS reverse proxy when HTTPS is enabled.
if [ "$DEPLOYMENT_HTTPS_MODE" = "disabled" ] || [ -z "$DEPLOYMENT_HTTPS_MODE" ]; then

Check failure on line 1237 in deploy/docker/deploy.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=ModelEngine-Group_nexent&issues=AaDnmAuGhhbE1zwLoYW7&open=AaDnmAuGhhbE1zwLoYW7&pullRequest=4026
# Stop and remove the HTTPS profile service when HTTPS is disabled so a
# previously enabled deployment does not keep the proxy running.
if ${docker_compose_command} --env-file "$ROOT_ENV_FILE" -p nexent --profile https -f "$COMPOSE_DIR/docker-compose${COMPOSE_FILE_SUFFIX}" ps -q nexent-nginx 2>/dev/null | grep -q .; then
echo "Stopping Nginx HTTPS reverse proxy (HTTPS disabled)..."
if ! ${docker_compose_command} --env-file "$ROOT_ENV_FILE" -p nexent --profile https -f "$COMPOSE_DIR/docker-compose${COMPOSE_FILE_SUFFIX}" rm -sf nexent-nginx 2>/dev/null; then
docker rm -f nexent-nginx 2>/dev/null || true
fi
fi
export NEXENT_WEB_PORT="${NEXENT_WEB_PORT:-3000}"
return 0
Comment on lines +1237 to +1247
fi

deployment_https_prepare || return 1

echo "🔒 Starting Nginx HTTPS reverse proxy (nexent-nginx)..."
if ! ${docker_compose_command} --env-file "$ROOT_ENV_FILE" -p nexent --profile https -f "$COMPOSE_DIR/docker-compose${COMPOSE_FILE_SUFFIX}" up -d nexent-nginx; then
echo " ❌ ERROR Failed to start nexent-nginx"

Check warning on line 1254 in deploy/docker/deploy.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Redirect this error message to stderr (>&2).

See more on https://sonarcloud.io/project/issues?id=ModelEngine-Group_nexent&issues=AaDnmAuGhhbE1zwLoYW9&open=AaDnmAuGhhbE1zwLoYW9&pullRequest=4026
return 1
fi
echo " ✅ Nginx HTTPS reverse proxy started"
}

stop_unselected_data_process_service() {
deployment_csv_contains "$DEPLOYMENT_COMPONENTS" "data-process" && return 0

Expand Down Expand Up @@ -1973,6 +1998,17 @@
return 0
fi

# Configure HTTPS state before core services start so nexent-web is created
# with the right port mapping on the first run (avoids a recreate cycle).
deploy_https_nginx || {
if [ "$DEPLOYMENT_LANGUAGE" = "zh" ]; then
echo "❌ HTTPS 反向代理部署失败"
else
echo "HTTPS reverse proxy deployment failed"
fi
exit 1
}

# Start core services
deploy_core_services || {
if [ "$DEPLOYMENT_LANGUAGE" = "zh" ]; then
Expand All @@ -1983,6 +2019,7 @@
exit 1
}


if [ "$DEPLOYMENT_LANGUAGE" = "zh" ]; then
echo " ✅ 核心服务启动成功"
else
Expand Down Expand Up @@ -2015,10 +2052,10 @@

if [ "$DEPLOYMENT_LANGUAGE" = "zh" ]; then
echo "🎉 部署完成!"
echo "🌐 现在可以访问应用:http://localhost:3000"
echo "🌐 现在可以访问应用:http://localhost:${NEXENT_WEB_PORT:-3000}"
else
echo "🎉 Deployment completed successfully!"
echo "🌐 You can now access the application at http://localhost:3000"
echo "🌐 You can now access the application at http://localhost:${NEXENT_WEB_PORT:-3000}"
fi
}

Expand Down
16 changes: 16 additions & 0 deletions deploy/env/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,22 @@ SUPABASE_POSTGRES_PORT=5436

# Supabase Auth Config
SITE_URL=http://localhost:3011

# HTTPS Termination Config (optional)
# HTTPS mode: disabled (default), self-signed, or custom
NEXENT_HTTPS_MODE=disabled
# HTTP entry port (host side): default 3000 for Docker, 30000 for Kubernetes
NEXENT_WEB_PORT=
# HTTPS entry port (host side): default 3100 for Docker, 31000 for Kubernetes
NEXENT_HTTPS_PORT=
# Certificate and private key paths (PEM) for custom mode
NEXENT_HTTPS_CERT_FILE=
NEXENT_HTTPS_KEY_FILE=
# Private key passphrase (stored in plain text, only needed for encrypted custom keys)
NEXENT_HTTPS_KEY_PASSPHRASE=
# Comma-separated SAN addresses (IPs or domains) for self-signed certificates
# Leave empty to auto-detect from the deployment host network interfaces
NEXENT_HTTPS_SAN=
SUPABASE_URL=http://nexent-supabase-kong:8000
API_EXTERNAL_URL=http://nexent-supabase-kong:8000
DISABLE_SIGNUP=false
Expand Down
1 change: 1 addition & 0 deletions deploy/k8s/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ update_values_yaml() {

deployment_apply_image_source
deployment_prepare_monitoring_env k8s || exit 1
deployment_https_prepare || exit 1
deployment_render_helm_values "$GENERATED_VALUES"
deployment_render_helm_values "$INFRASTRUCTURE_GENERATED_VALUES"
render_k8s_runtime_config_values "$GENERATED_RUNTIME_VALUES"
Expand Down
6 changes: 6 additions & 0 deletions deploy/k8s/helm/nexent/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ dependencies:
repository: "file://./charts/nexent-openssh"
condition: nexent-openssh.enabled

# Optional Nginx HTTPS reverse proxy (terminates TLS on the web NodePort)
- name: nexent-nginx
version: 0.1.0
repository: "file://./charts/nexent-nginx"
condition: nexent-nginx.enabled

# Optional OpenTelemetry monitoring stack
- name: nexent-monitoring
version: 0.1.0
Expand Down
7 changes: 7 additions & 0 deletions deploy/k8s/helm/nexent/charts/nexent-nginx/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: v2
name: nexent-nginx
description: Nginx HTTPS reverse proxy for the Nexent web entry
type: application
version: 0.1.0
appVersion: "latest"

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{{- if .Values.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: nexent-nginx-config
namespace: {{ .Values.global.namespace }}
data:
default.conf: |
{{ .Values.config | indent 4 }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{{- if .Values.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: nexent-nginx
namespace: {{ .Values.global.namespace }}
labels:
app: nexent-nginx
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: nexent-nginx
template:
metadata:
labels:
app: nexent-nginx
spec:
containers:
- name: nginx
image: {{ .Values.images.nginx.repository }}:{{ .Values.images.nginx.tag }}
imagePullPolicy: {{ .Values.images.nginx.pullPolicy }}
ports:
- containerPort: 3000
name: https
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
readOnly: true
- name: nginx-tls
mountPath: /etc/nginx/ssl
readOnly: true
resources:
requests:
memory: {{ .Values.resources.nginx.requests.memory }}
cpu: {{ .Values.resources.nginx.requests.cpu }}
limits:
memory: {{ .Values.resources.nginx.limits.memory }}
cpu: {{ .Values.resources.nginx.limits.cpu }}
volumes:
- name: nginx-config
configMap:
name: nexent-nginx-config
- name: nginx-tls
secret:
secretName: nexent-nginx-tls
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{- if .Values.enabled }}
{{- if and .Values.tls.cert .Values.tls.key }}
apiVersion: v1
kind: Secret
metadata:
name: nexent-nginx-tls
namespace: {{ .Values.global.namespace }}
type: Opaque
data:
server.pem: {{ .Values.tls.cert | b64enc | quote }}
server.key: {{ .Values.tls.key | b64enc | quote }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{- if .Values.enabled }}
apiVersion: v1
kind: Service
metadata:
name: nexent-nginx
namespace: {{ .Values.global.namespace }}
spec:
type: {{ .Values.services.nginx.type }}
ports:
- port: 3000
targetPort: 3000
name: https
{{- if eq .Values.services.nginx.type "NodePort" }}
nodePort: {{ .Values.services.nginx.nodePort }}
{{- end }}
selector:
app: nexent-nginx
{{- end }}

Loading
Loading