Skip to content

Conversation

@s4s0l
Copy link

@s4s0l s4s0l commented Dec 8, 2025

Summary

Issue: #88 (changing base context root for hosting behind url rewriting reverse proxy)

Checklist

  • Tested and/or added tests to validate that the changes work as intended, if applicable.
    • make run && make frontend-run, seems to work
    • make docker-build-and-run works also
    • I've allowed myself to add compose file that runs gatus behind caddy, to proove it actually works.
      • While behind proxy installed an 'app' from edge - icons and stuff were present in my 'start' menu
  • Updated documentation in README.md.

Notes:

  • I didn't try to make 'make test' not - fail on my PC. Before and after my changes same 2 tests fail - i assume they have nothing to do with UI anyway (DNS and ICMP tests).
  • For anyone wanting to test it or use my version there is 'ghcr.io/s4s0l/gatus:v0.0.0.0.4' image that contains this PR.

- based on work done here:
    https://github.com/simonhammes/gatus/tree/88-dynamic-base
- Additions:
   - docker compose for testing reverse proxy scenario
   - rolled back 'SERVER_URL' in order to allow hosting ui via node during development
   - updated manifest.json so it will honour relative paths
@s4s0l s4s0l force-pushed the 88-dynamic-base-followup branch from 7c42ced to 10d5114 Compare December 8, 2025 21:55
README.md Outdated
| `ui.dashboard-subheading` | Dashboard description between header and endpoints | `Monitor the health of your endpoints in real-time` |
| `ui.header` | Header at the top of the dashboard. | `Gatus` |
| `ui.logo` | URL to the logo to display. | `""` |
| `ui.base` | `href` attribute of the HTML `<base>` tag. Use this if you want to host Gatus on a subpath (e.g. `/status/`). Has to end with '/'. | `/` |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this option might actually be better fit in the web config section and maybe also renaming it to make it easier to read without the actually reading the docs: web.base-path

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This time I'll ask before doing anything. The value of the 'base path' is needed by the 'UI config' (to render index.html) and by the 'security config' (for proper redirects and cookie paths). Currently, these parts are quite isolated, and I'm about to introduce a dependency from UI & security to web config. I can think of a plethora of ways of doing it, but I get a feeling there will be a few back-and-forth discussions over it 😉. What do you think about passing 'basePath' as an argument to 'ValidateAndSetDefaults' in these different configuration objects that need it? This way it won't introduce dependencies to 'web' config everywhere, will be easily mocked in tests, and this method is mutating everything anyway...or is somewhere else a pattern I can use?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently commited version does that. It is by no means final; still missing some validation and tests, but it works.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about passing 'basePath' as an argument to 'ValidateAndSetDefaults' in these different configuration objects that need it?

I think your suggested solution passing it as argument might not scale very well in case there are more options that have the same problem are added in the future.

I opened a PR on your fork with another solution that so far looks like it is consistent with the MaximumNumberOfResults storage option where we would not need to add any additional arguments or package dependencies.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing this 'your' way has a drawback, that it makes it difficult to validate the RedirectURL in oidc configuration, as validation occurs before settings are distributed. But I'm not entirely sure there is a universe where not including a base-path in redirect url is a desired thing.

Anyway I think I've finished.

README.md Outdated
Comment on lines 3275 to 3277
Currently, you can expose the Gatus UI using a fully qualified domain name (FQDN) such as `status.example.org`. However, it does not support path-based routing, which means you cannot expose it through a URL like `example.org/status/`.

For more information, see https://github.com/TwiN/gatus/issues/88.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be updated

}

func (c *OIDCConfig) loginHandler(ctx *fiber.Ctx) error {
// ??? state and nonce are not 'secure random'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not quite understand what you mean. Can you elaborate on it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to myself to think about it and open separate issue. Didn't intend to push it. Not related to this PR.

What I was wondering was that 'state' in oauth flow is kinda important. This value should not be easily guessable. I don't know how UUID is implemented here but UUIDs are usually quite 'guessable'. By 'secure random' i meant something like https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html. crypto in go probably has something like this.

@PythonGermany
Copy link
Contributor

We missed a location where we need to update the base path:

const setThemeCookie = (theme) => {
document.cookie = `${THEME_COOKIE_NAME}=${theme}; path=/; max-age=${THEME_COOKIE_MAX_AGE}; samesite=strict`
}

@s4s0l
Copy link
Author

s4s0l commented Dec 11, 2025

There is #1430, I think i'll wait with rebase until it gets merged.

},
serverUrl: {
type: String,
default: '..'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the default also be changed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. In my opinion default should be removed. It is used only once, and where it is used it is set explicitly. Default for this kind of stuff does not make much sense to me. If it is not set consequently throughout the application it will not work, but will not fail during type checking / linting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants