Hiya, Thanks for the hamilton package, I'm curren...
# hamilton-help
j
Hiya, Thanks for the hamilton package, I'm currently setting up the hamilton-ui on a domain subpath, using nginx as a reverse proxy. Having some issues getting this to work since the frontend is expecting the main.js and css file to be located under the main path. Has anyone had any success to get this to work? I've done similar with grafana and the following environment variables exist to make it work: - GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s/grafana - GF_SERVER_SERVE_FROM_SUB_PATH=true Thanks for any help :)
s
@Elijah Ben Izzy?
e
Yeah will take a look soon when I’m at my desk — should be straightforward I did something like that for our deployment
j
Thanks so much!
e
Ok — there are afew ways to deploy this. Mind sharing how you’re doing this now? E.G. what commands are you running/what you’re trying? It should be under a simple static URL — all under the /static/ path: https://github.com/DAGWorks-Inc/hamilton/blob/1057a40db370d235fce647d65872221365da6bfa/ui/backend/server/server/settings_mini.py#L115
j
Hi there, sorry for the late reply! deploying the fe and backend using a docker compose file that looks exactly the same as the one found here: https://github.com/DAGWorks-Inc/hamilton/blob/1057a40db370d235fce647d65872221365da6bfa/ui/docker-compose.yml The nginx configuration looks as follows:
location /grafana/ {
auth_request /validate-jwt;  # JWT token validation
auth_request_set $auth_status $upstream_status;
proxy_pass <http://hamilton:8242>;
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 $scheme;
proxy_set_header X-Session-Info $cookie_session;
proxy_set_header X-Username $cookie_username;
proxy_cache my_cache;
proxy_cache_valid any 10m;
error_page 401 /custom401.html;
}
With hamilton being the name of the container. Will have to give your nginx a try but if I understand it correctly, this doesn't actually setup a subpath?
Have a nice weekend all! Will be revisiting next week 🙂
s
@Jonas Meyer-Ohle could you provide some more context please, along with the errors you’re seeing? E.g. are you trying to run the UI routing to it based on the url path? e.g.
Copy code
www.somedomain.com/some_path/
and so you want all URLs in the Hamilton UI to be pre-pended with
/some_path/
? (note I spot
location /grafana/
in your snippet above in case that’s an error) — and have a good weekend!
j
Sorry yes! What you said about url prepending is exactly what I am looking for. Following is the nginx.conf with the correct locations:
Copy code
server {
        listen 443 ssl;
        server_name <http://domain.com|domain.com>;

        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";

        error_page 502 /custom502.html;
        error_page 504 /custom504.html;
        error_page 401 /custom401.html;

        location = /custom502.html {
            root /opt/bitnami/nginx/html;
            internal;
        }

        location = /custom504.html {
            root /opt/bitnami/nginx/html;
            internal;
        }

        location = /custom401.html {
            root /opt/bitnami/nginx/html;
            internal;
        }

        location / {
            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 $scheme;
            add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
            proxy_set_header X-Session-Info $cookie_session;
            proxy_set_header X-Username $cookie_username;

            proxy_pass <http://host.docker.internal:8080>;
            proxy_read_timeout 864000;
            proxy_cache my_cache;
            proxy_cache_revalidate on;

            proxy_cache_min_uses 3;

            proxy_cache_use_stale error timeout updating http_500 http_502

                                http_503 http_504;

            proxy_cache_background_update on;

            proxy_cache_lock on;
        }

        location /grafana/ {
            auth_request /validate-jwt;  # JWT token validation
            auth_request_set $auth_status $upstream_status;

            proxy_pass <http://grafana:3000>;
            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 $scheme;
            proxy_set_header X-Session-Info $cookie_session;
            proxy_set_header X-Username $cookie_username;
            proxy_cache my_cache;
		    proxy_cache_valid any 10m;

            error_page 401 /custom401.html;
        }

        location /hamilton/ {
            auth_request /validate-jwt;  # JWT token validation
            auth_request_set $auth_status $upstream_status;

            proxy_pass <http://hamilton-ui-frontend:8242>;
            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 $scheme;
            proxy_set_header X-Session-Info $cookie_session;
            proxy_set_header X-Username $cookie_username;
            proxy_cache my_cache;
		    proxy_cache_valid any 10m;

            error_page 401 /custom401.html;
        }

        # JWT validation block
        location = /validate-jwt {
            internal;
            proxy_pass <https://authentication:9876/auth>;
            proxy_set_header Host $host;
            proxy_pass_request_body off;
            proxy_set_header Content-Length "";
            proxy_cache_valid 200 10m;
            proxy_set_header X-Session-Info $cookie_session;
            proxy_set_header X-Username $cookie_username;
        }
The docker file looks as such:
Copy code
hamilton-ui-frontend:
    <<: *default-logging
    container_name: hamilton-ui-frontend
    image: tnpatlas/hamilton-ui-frontend:latest
    ports:
      - "8242:8242"
    networks:
      - app-network
    environment:
      - NGINX_PORT=8242 # NB Custom port won't be visible in console & will mean the backend's shortcut will fail
      - NODE_ENV=development
      - REACT_APP_AUTH_MODE=local
      - REACT_APP_USE_POSTHOG=false
      - REACT_APP_API_URL=<http://hamilton-ui-backend:8241>
    depends_on:
      hamilton-ui-backend:
        condition: service_started
grafana:
    container_name: grafana
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    volumes:
      - grafana-storage:/var/lib/grafana
      - ./lgtm/grafana-datasources.yml:/etc/grafana/provisioning/datasources/grafana-datasources.yml
    environment:
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_BASIC_ENABLED=false
      - GF_SECURITY_ALLOW_EMBEDDING=true
      - GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s/grafana
      - GF_SERVER_SERVE_FROM_SUB_PATH=true
domain.com/grafana works but domain.com/hamilton has the following error:
Copy code
GET <https://domain.com/static/css/main.5f18e71d.css> net::ERR_ABORTED 404 (NOT FOUND)
Copy code
GET <https://domain.com/static/js/main.a45999b9.js> net::ERR_ABORTED 404 (NOT FOUND)
FYI, I removed some ssl configuration from the nginx configuration I shared but it's there in the actual package 🙂
s
So assuming you want to serve the Hamilton UI under
/hamilton/
then I think we need to rebuild the container & expose an option for this. Will try get you some pointers on how to do this today / tomorrow. @Elijah Ben Izzy might be able to point to where in the frontend code we need to set this - which if you test out we could then fold back into Hamilton with your help.
e
Yep will take a look a bit later today/early tomorrow
j
Cheers! Happy to help in any way, and no rush 🙂
While I've never touched typescript or react, I'm assuming something like the following has to be done in https://github.com/DAGWorks-Inc/hamilton/blob/main/ui/frontend/src/App.tsx#L102 ?
Copy code
import { BrowserRouter, Route } from 'react-router-dom';

// Then in render
<BrowserRouter basename='/path/to/subfolder/'>
  <Route path='/' component={ Home } exact />
  <Route path='/about' component={ About } exact />
  {/*...*/}
</BrowserRouter>
And then exposing a basename variable that can be set in docker etc.
e
Yep so that’s one option — worth a try. Should be pretty easy to add that in as a variable and expose it. E.G. first try to change
/path/to/subfolder
to
/hamilton/
— then can make it a config variable
j
Thanks, I'll give that a try and open a PR if it works 🙂
e
Yeah! Sorry for the delay in response. I’ll take a look at it as well and see if there are any non-code-change approaches.
j
No worries at all, submitted a PR here, https://github.com/DAGWorks-Inc/hamilton/pull/1284 Getting a docs build failed error but doesn't look like it's related to the changed I made?
e
Saw! Yeah the docs change is probably permissions
Should be able to look/merge today
🙌 1