mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
feat: add subpath config (#1236)
Co-authored-by: Warren <5959690+wrn14897@users.noreply.github.com>
This commit is contained in:
parent
658728318b
commit
b806116d73
9 changed files with 211 additions and 2 deletions
9
.changeset/feat-subpath-config.md
Normal file
9
.changeset/feat-subpath-config.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
'@hyperdx/app': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: Add subpath configuration support
|
||||||
|
|
||||||
|
This change allows the HyperDX frontend to be served from a subpath (e.g.,
|
||||||
|
`/hyperdx`). It includes updated Next.js, NGINX, and Traefik configurations,
|
||||||
|
along with documentation for the new setup.
|
||||||
1
.env
1
.env
|
|
@ -20,6 +20,7 @@ HYPERDX_APP_PORT=8080
|
||||||
HYPERDX_APP_URL=http://localhost
|
HYPERDX_APP_URL=http://localhost
|
||||||
HYPERDX_LOG_LEVEL=debug
|
HYPERDX_LOG_LEVEL=debug
|
||||||
HYPERDX_OPAMP_PORT=4320
|
HYPERDX_OPAMP_PORT=4320
|
||||||
|
HYPERDX_BASE_PATH=
|
||||||
|
|
||||||
# Otel/Clickhouse config
|
# Otel/Clickhouse config
|
||||||
HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE=default
|
HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE=default
|
||||||
|
|
|
||||||
|
|
@ -83,5 +83,29 @@ services:
|
||||||
interval: 1s
|
interval: 1s
|
||||||
timeout: 1s
|
timeout: 1s
|
||||||
retries: 60
|
retries: 60
|
||||||
|
|
||||||
|
# nginx:
|
||||||
|
# image: nginx:alpine
|
||||||
|
# ports:
|
||||||
|
# - '4040:4040'
|
||||||
|
# volumes:
|
||||||
|
# - ./proxy/nginx/nginx.conf.template:/etc/nginx/templates/default.conf.template:ro
|
||||||
|
# environment:
|
||||||
|
# HYPERDX_BASE_PATH: ${HYPERDX_BASE_PATH:-/}
|
||||||
|
# network_mode: host
|
||||||
|
# restart: always
|
||||||
|
|
||||||
|
# traefik:
|
||||||
|
# image: traefik:latest
|
||||||
|
# ports:
|
||||||
|
# - '4040:4040'
|
||||||
|
# volumes:
|
||||||
|
# - ./proxy/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
|
||||||
|
# - ./proxy/traefik/config.yml:/etc/traefik/dynamic/config.yml:ro
|
||||||
|
# environment:
|
||||||
|
# HYPERDX_BASE_PATH: ${HYPERDX_BASE_PATH:-/}
|
||||||
|
# network_mode: host
|
||||||
|
# restart: always
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
internal:
|
internal:
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,4 @@ OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
|
||||||
OTEL_SERVICE_NAME="hdx-oss-dev-app"
|
OTEL_SERVICE_NAME="hdx-oss-dev-app"
|
||||||
PORT=${HYPERDX_APP_PORT}
|
PORT=${HYPERDX_APP_PORT}
|
||||||
NODE_OPTIONS="--max-http-header-size=131072"
|
NODE_OPTIONS="--max-http-header-size=131072"
|
||||||
|
NEXT_PUBLIC_HYPERDX_BASE_PATH=
|
||||||
|
|
@ -8,7 +8,10 @@ const withNextra = require('nextra')({
|
||||||
themeConfig: './src/nextra.config.tsx',
|
themeConfig: './src/nextra.config.tsx',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const basePath = process.env.NEXT_PUBLIC_HYPERDX_BASE_PATH;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
basePath: basePath,
|
||||||
experimental: {
|
experimental: {
|
||||||
instrumentationHook: true,
|
instrumentationHook: true,
|
||||||
// External packages to prevent bundling issues with Next.js 14
|
// External packages to prevent bundling issues with Next.js 14
|
||||||
|
|
@ -57,8 +60,8 @@ module.exports = {
|
||||||
productionBrowserSourceMaps: false,
|
productionBrowserSourceMaps: false,
|
||||||
...(process.env.NEXT_OUTPUT_STANDALONE === 'true'
|
...(process.env.NEXT_OUTPUT_STANDALONE === 'true'
|
||||||
? {
|
? {
|
||||||
output: 'standalone',
|
output: 'standalone',
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
74
proxy/README.md
Normal file
74
proxy/README.md
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Proxy Configuration
|
||||||
|
|
||||||
|
This directory contains configurations for running the HyperDX frontend behind a
|
||||||
|
reverse proxy that serves the application under a specific subpath. This is
|
||||||
|
useful for deployments where HyperDX is not at the root of a domain (e.g.,
|
||||||
|
`http://example.com/hyperdx`).
|
||||||
|
|
||||||
|
We provide configurations for two popular reverse proxies:
|
||||||
|
|
||||||
|
- [Nginx](./nginx/nginx.conf.template)
|
||||||
|
- [Traefik](./traefik/config.yml)
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
To configure the subpath, you need to set the following environment variables in
|
||||||
|
your `.env` file.
|
||||||
|
|
||||||
|
### `HYPERDX_BASE_PATH` and `NEXT_PUBLIC_HYPERDX_BASE_PATH`
|
||||||
|
|
||||||
|
To serve the application from a subpath, two environment variables must be set
|
||||||
|
to the **same value**:
|
||||||
|
|
||||||
|
1. `HYPERDX_BASE_PATH`: This is used by the reverse proxy (Nginx or Traefik) to
|
||||||
|
handle path routing and rewriting.
|
||||||
|
2. `NEXT_PUBLIC_HYPERDX_BASE_PATH`: This is used by the Next.js application to
|
||||||
|
generate correct asset links and API routes.
|
||||||
|
|
||||||
|
- The value **must** start with a `/` if it's not an empty string (ex:
|
||||||
|
`/hyperdx`).
|
||||||
|
- If you want to serve from the root, you can omit these variables or set them
|
||||||
|
to `/`.
|
||||||
|
|
||||||
|
### `FRONTEND_URL`
|
||||||
|
|
||||||
|
This variable should be set to the full public URL of the frontend, including
|
||||||
|
the subpath. The API server uses this URL for various purposes such as
|
||||||
|
generating absolute URLs for redirects, links in emails, or alerts.
|
||||||
|
|
||||||
|
- It should be a full URL, including the protocol (`http` or `https`).
|
||||||
|
- It should include the subpath defined in `HYPERDX_BASE_PATH`.
|
||||||
|
|
||||||
|
**Example `.env` Configuration:**
|
||||||
|
|
||||||
|
For local development with the subpath `/hyperdx`, your configuration would look
|
||||||
|
like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
HYPERDX_BASE_PATH=/hyperdx
|
||||||
|
NEXT_PUBLIC_HYPERDX_BASE_PATH=/hyperdx
|
||||||
|
FRONTEND_URL=http://localhost:4040/hyperdx
|
||||||
|
```
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
The proxy configurations are designed to handle subpath routing with minimal
|
||||||
|
changes to the application code. Here's a high-level overview of the logic:
|
||||||
|
|
||||||
|
1. **Root Redirect**: If a subpath is configured (e.g., `/hyperdx`), any
|
||||||
|
requests to the root (`/`) are automatically redirected to that subpath.
|
||||||
|
This ensures users always land on the correct URL.
|
||||||
|
|
||||||
|
2. **Path Rewriting**: The application's frontend code sometimes makes requests
|
||||||
|
to root-level paths (e.g., `/api/...` or `/_next/...`). The proxy intercepts
|
||||||
|
these requests, prepends the configured subpath, and forwards them to the
|
||||||
|
Next.js server. For example, a request for `/_next/static/chunk.js` becomes
|
||||||
|
a request for `/hyperdx/_next/static/chunk.js` before being sent to the
|
||||||
|
application.
|
||||||
|
|
||||||
|
3. **Direct Proxy**: Any requests that already include the correct subpath are
|
||||||
|
passed directly to the Next.js application, which is configured via
|
||||||
|
`basePath` to handle them correctly.
|
||||||
|
|
||||||
|
This setup allows the frontend application to be developed as if it were running
|
||||||
|
at the root, while the proxy transparently manages the subpath routing.
|
||||||
43
proxy/nginx/nginx.conf.template
Normal file
43
proxy/nginx/nginx.conf.template
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
upstream app {
|
||||||
|
server 127.0.0.1:8080;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 4040;
|
||||||
|
|
||||||
|
set $base_path "${HYPERDX_BASE_PATH}";
|
||||||
|
if ($base_path = "/") {
|
||||||
|
set $base_path "";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Common proxy headers
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
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 $scheme;
|
||||||
|
|
||||||
|
# Redirect root to base path, if a base path is set
|
||||||
|
location = / {
|
||||||
|
if ($base_path != "") {
|
||||||
|
return 301 $base_path;
|
||||||
|
}
|
||||||
|
# If no base path, just proxy to the app
|
||||||
|
proxy_pass http://app;
|
||||||
|
}
|
||||||
|
|
||||||
|
# This handles assets and api calls made to the root and rewrites them to include the base path
|
||||||
|
location ~ ^(/api/|/_next/|/__ENV\.js$|/Icon32\.png$) {
|
||||||
|
# Note: $request_uri includes the original full path including query string
|
||||||
|
proxy_pass http://app$base_path$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Proxy requests that are already prefixed with the base path to the app
|
||||||
|
location ${HYPERDX_BASE_PATH} {
|
||||||
|
# The full request URI (e.g., /hyperdx/settings) is passed to the upstream
|
||||||
|
proxy_pass http://app;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
proxy/traefik/config.yml
Normal file
46
proxy/traefik/config.yml
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
# This handles the main app at the basepath
|
||||||
|
app-router:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: 'PathPrefix(`{{ env "HYPERDX_BASE_PATH" }}`)'
|
||||||
|
service: app-service
|
||||||
|
|
||||||
|
# This handles assets and api calls at the root and rewrites them
|
||||||
|
assets-api-router:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule:
|
||||||
|
'PathPrefix(`/api`) || PathPrefix(`/_next`) || Path(`/__ENV.js`) ||
|
||||||
|
Path(`/Icon32.png`)'
|
||||||
|
service: app-service
|
||||||
|
middlewares:
|
||||||
|
- add-basepath
|
||||||
|
|
||||||
|
# This redirects from / to the basepath
|
||||||
|
root-redirect:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: 'Path(`/`)'
|
||||||
|
service: app-service # service is required, but redirect will happen first
|
||||||
|
middlewares:
|
||||||
|
- redirect-to-basepath
|
||||||
|
|
||||||
|
middlewares:
|
||||||
|
add-basepath:
|
||||||
|
addPrefix:
|
||||||
|
prefix: '{{ env "HYPERDX_BASE_PATH" }}'
|
||||||
|
|
||||||
|
redirect-to-basepath:
|
||||||
|
redirectRegex:
|
||||||
|
regex: '^/$'
|
||||||
|
replacement: '{{ env "HYPERDX_BASE_PATH" }}'
|
||||||
|
permanent: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
app-service:
|
||||||
|
loadBalancer:
|
||||||
|
passHostHeader: true
|
||||||
|
servers:
|
||||||
|
- url: 'http://127.0.0.1:8080'
|
||||||
8
proxy/traefik/traefik.yml
Normal file
8
proxy/traefik/traefik.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
entryPoints:
|
||||||
|
web:
|
||||||
|
address: ':4040'
|
||||||
|
|
||||||
|
providers:
|
||||||
|
file:
|
||||||
|
filename: /etc/traefik/dynamic/config.yml
|
||||||
|
watch: true
|
||||||
Loading…
Reference in a new issue