[GH-ISSUE #1219] Dependency on external HTTP services #433

Closed
opened 2026-02-27 08:17:16 +03:00 by kerem · 6 comments
Owner

Originally created by @selfhoster1312 on GitHub (Jul 17, 2025).
Original GitHub issue: https://github.com/lldap/lldap/issues/1219

I personally find that it's a problem (especially for a critical service managing auth), but even if that's a deliberate choice it should be documented.

Image

From a first look it looks like this is due to:

  • bootstrap (JSDelivr)
  • darkmode.js (JSDelivr)
  • FontAwesome (CloudFlare)
  • Bebas Neue font (Google Fonts)

The main problem problem is that these CDN can be used to inject arbitrary javascript. The secondary problem is that lldap would not work (or not great) without internet access on the client side (LAN setup).

It would be interesting to see in those dependencies what can be served locally, and what can be entirely removed:

  • bootstrap can be easily packaged with the app and served from localhost
  • darkmode.js: why do we have this? can't we just respect browser preferences? doesn't bootstrap do that by default?
  • font awesome: we use little of it, could it maybe be packaged with the WASM blob via a build-time macro?
  • Bebas Neue: is it really useful to have a custom font for such a basic app? (it looks nice, yes :D)

If we don't want to change the status quo, it should be mentioned in the docs.

Originally created by @selfhoster1312 on GitHub (Jul 17, 2025). Original GitHub issue: https://github.com/lldap/lldap/issues/1219 I personally find that it's a problem (especially for a critical service managing auth), but even if that's a deliberate choice it should be documented. <img width="1908" height="296" alt="Image" src="https://github.com/user-attachments/assets/d6924302-f051-45c0-8073-63644d18eb08" /> From a first look it looks like this is due to: - bootstrap (JSDelivr) - darkmode.js (JSDelivr) - FontAwesome (CloudFlare) - Bebas Neue font (Google Fonts) The main problem problem is that these CDN can be used to inject arbitrary javascript. The secondary problem is that lldap would not work (or not great) without internet access on the client side (LAN setup). It would be interesting to see in those dependencies what can be served locally, and what can be entirely removed: - bootstrap can be easily packaged with the app and served from localhost - darkmode.js: why do we have this? can't we just respect browser preferences? doesn't bootstrap do that by default? - font awesome: we use little of it, could it maybe be packaged with the WASM blob via a build-time macro? - Bebas Neue: is it really useful to have a custom font for such a basic app? (it looks nice, yes :D) If we don't want to change the status quo, it should be mentioned in the docs.
kerem closed this issue 2026-02-27 08:17:16 +03:00
Author
Owner

@nitnelave commented on GitHub (Jul 17, 2025):

A couple of comments:

On security: all the JS that is downloaded is checksummed, so there is no risk of arbitrary JS injection.

On darkmode.js: it is part of bootstrap, but not the default.

On making things local by default: external requests can be cached by the client browser and fetched in parallel when not cached, rather than having to download a big chunk of data from a single server, so I don't think it should be the default.

The use case of being able to serve LLDAP without internet access is valid, though a bit unusual, and definitely not the main target of LLDAP. However, you're not the first one to have this concern, and there is a "index_local.html" file that can be used to reference locally-downloaded versions of all the external assets. As mentioned above, it is not and will not be the default. I don't quite remember how to package LLDAP to use that file though. The simplest way would be to use the main docker image and mount a local "static" folder with the right assets (and the index_local.html overwriting the index.html)

<!-- gh-comment-id:3083565527 --> @nitnelave commented on GitHub (Jul 17, 2025): A couple of comments: On security: all the JS that is downloaded is checksummed, so there is no risk of arbitrary JS injection. On darkmode.js: it is part of bootstrap, but not the default. On making things local by default: external requests can be cached by the client browser and fetched in parallel when not cached, rather than having to download a big chunk of data from a single server, so I don't think it should be the default. The use case of being able to serve LLDAP without internet access is valid, though a bit unusual, and definitely not the main target of LLDAP. However, you're not the first one to have this concern, and there is a "index_local.html" file that can be used to reference locally-downloaded versions of all the external assets. As mentioned above, it is not and will not be the default. I don't quite remember how to package LLDAP to use that file though. The simplest way would be to use the main docker image and mount a local "static" folder with the right assets (and the index_local.html overwriting the index.html)
Author
Owner

@selfhoster1312 commented on GitHub (Jul 17, 2025):

all the JS that is downloaded is checksummed

That's good :)

having to download a big chunk of data from a single server

Well right now that is the case that the 3MB wasm blob is the main thing to download. Multiplexing HTTP requests and caching works exactly the same whether we download from JSDelivr or from the LLDAP server. The only differences are:

  • the file from JSDelivr may already be cached if you have browsed other sites using the same CDN
  • downloading a fresh copy will usually be faster from your LLDAP server than from a CDN: because the CDN has no PoP in your region, because extra DNS resolution and TLS/HTTP connections requires more TCP round-trips, because your uplink is really slow, or because the CDN is having an outage

I think the benefits of selfhosting the assets far outweight the downsides. I also think it's possible to reduce their footprints quite a bit (i'm also looking into reducing the WASM side but not having great success so far). In my case it looks like outside of the WASM blob it's "only" 500KB of CSS/JS/fonts (uncompressed).

it is not and will not be the default

I believe imho it's worth taking time to think it through. Making lldap more lightweight and more resilient sounds aligned with the philosophy of the project, and i'd be willing to contribute PRs for that. But of course, if you are sure things should remain this way, my offer to make a PR documenting this still stands.

I will of course let you decide on the course of action 👍

<!-- gh-comment-id:3083683891 --> @selfhoster1312 commented on GitHub (Jul 17, 2025): > all the JS that is downloaded is checksummed That's good :) > having to download a big chunk of data from a single server Well right now that is the case that the 3MB wasm blob is the main thing to download. Multiplexing HTTP requests and caching works exactly the same whether we download from JSDelivr or from the LLDAP server. The only differences are: - the file from JSDelivr may already be cached if you have browsed other sites using the same CDN - downloading a fresh copy will usually be faster from your LLDAP server than from a CDN: because the CDN has no PoP in your region, because extra DNS resolution and TLS/HTTP connections requires more TCP round-trips, because your uplink is really slow, or because the CDN is having an outage I think the benefits of selfhosting the assets far outweight the downsides. I also think it's possible to reduce their footprints quite a bit (i'm also looking into reducing the WASM side but not having great success so far). In my case it looks like outside of the WASM blob it's "only" 500KB of CSS/JS/fonts (uncompressed). > it is not and will not be the default I believe imho it's worth taking time to think it through. Making lldap more lightweight and more resilient sounds aligned with the philosophy of the project, and i'd be willing to contribute PRs for that. But of course, if you are sure things should remain this way, my offer to make a PR documenting this still stands. I will of course let you decide on the course of action 👍
Author
Owner

@martadinata666 commented on GitHub (Jul 17, 2025):

I assume this is not docker deployment? afaik, docker already use local method by default long ago? #311 and #310.

<!-- gh-comment-id:3083752943 --> @martadinata666 commented on GitHub (Jul 17, 2025): I assume this is not docker deployment? afaik, docker already use local method by default long ago? #311 and #310.
Author
Owner

@nitnelave commented on GitHub (Jul 17, 2025):

Hmm, I may still be convinced, I don't want to unconditionally say no :)

Another concern is ease of development: any solution put in place should not require much dev effort to change the resources.

I was hoping that bootstrap would be common enough to be in the cache, and that a CDN would have a close enough server otherwise, but for most people LLDAP is localhost or just about, you can't really get much closer. You may have a point there. But really, at this point we're splitting hairs, time to first render is not going to make a difference to any LLDAP use, I'd wager. So as long as the development process doesn't get more complicated, feel free to send PRs to make index_local the default (and only option).

I'm all for minimizing the size of the assets, and for wasm there are some rust packers that I wanted to try but haven't had time. Any progress in this area is welcome.

<!-- gh-comment-id:3083759996 --> @nitnelave commented on GitHub (Jul 17, 2025): Hmm, I may still be convinced, I don't want to unconditionally say no :) Another concern is ease of development: any solution put in place should not require much dev effort to change the resources. I was hoping that bootstrap would be common enough to be in the cache, and that a CDN would have a close enough server otherwise, but for most people LLDAP is localhost or just about, you can't really get much closer. You may have a point there. But really, at this point we're splitting hairs, time to first render is not going to make a difference to _any_ LLDAP use, I'd wager. So as long as the development process doesn't get more complicated, feel free to send PRs to make index_local the default (and only option). I'm all for minimizing the size of the assets, and for wasm there are some rust packers that I wanted to try but haven't had time. Any progress in this area is welcome.
Author
Owner

@Masgalor commented on GitHub (Jul 17, 2025):

As a small side-note, all the Linux packages I maintain use exclusively index_local.html.

  • Because all the use-cases I had for LLDAP were in isolated networks without internet access.
  • I don't want to think about GDPR compliance when external resources are loaded.
<!-- gh-comment-id:3083831851 --> @Masgalor commented on GitHub (Jul 17, 2025): As a small side-note, all the Linux packages I maintain use exclusively `index_local.html`. - Because all the use-cases I had for LLDAP were in isolated networks without internet access. - I don't want to think about GDPR compliance when external resources are loaded.
Author
Owner

@nitnelave commented on GitHub (Oct 4, 2025):

I'll close this, but feel free to reopen if you have a concrete proposal.

<!-- gh-comment-id:3368547626 --> @nitnelave commented on GitHub (Oct 4, 2025): I'll close this, but feel free to reopen if you have a concrete proposal.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/lldap-lldap#433
No description provided.