[GH-ISSUE #502] Allow setting environment variables for configuration #182

Closed
opened 2026-02-27 08:15:43 +03:00 by kerem · 19 comments
Owner

Originally created by @onedr0p on GitHub (Mar 27, 2023).
Original GitHub issue: https://github.com/lldap/lldap/issues/502

Hi 👋🏼

I was wondering if it would possible if we could be able to set configuration for LLDAP via environment variables in additional to a configuration file? My thinking is that env would take precedence over the config file options. This is a very common pattern in software development, especially when applications are supported in containers.

The use-case here is that Kubernetes and containers in general have a much easier time configuring applications via env rather than a file that is only on disk. The current configuration file appears to be pretty flat with no nested config, so it shouldn't be too hard to implement... however I am not a rust developer so I am not sure if the current library being used exposes this as an option.

Originally created by @onedr0p on GitHub (Mar 27, 2023). Original GitHub issue: https://github.com/lldap/lldap/issues/502 Hi 👋🏼 I was wondering if it would possible if we could be able to set configuration for LLDAP via environment variables in additional to a configuration file? My thinking is that env would take precedence over the config file options. This is a very common pattern in software development, especially when applications are supported in containers. The use-case here is that Kubernetes and containers in general have a much easier time configuring applications via env rather than a file that is only on disk. The current configuration file appears to be pretty flat with no nested config, so it shouldn't be too hard to implement... however I am not a rust developer so I am not sure if the current library being used exposes this as an option.
kerem closed this issue 2026-02-27 08:15:43 +03:00
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

It's already possible :) : https://github.com/nitnelave/lldap/blob/main/lldap_config.docker_template.toml#L2

<!-- gh-comment-id:1485092539 --> @nitnelave commented on GitHub (Mar 27, 2023): It's already possible :) : https://github.com/nitnelave/lldap/blob/main/lldap_config.docker_template.toml#L2
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

There are also examples of env variables set in the docker-compose sample in the readme.

<!-- gh-comment-id:1485093889 --> @nitnelave commented on GitHub (Mar 27, 2023): There are also examples of env variables set in the docker-compose sample in the readme.
Author
Owner

@onedr0p commented on GitHub (Mar 27, 2023):

I was looking over that config file for a bit and didn't even see that 🤦🏼 . Time to get coffee and actually wake up before Githubbing 😄

<!-- gh-comment-id:1485096699 --> @onedr0p commented on GitHub (Mar 27, 2023): I was looking over that config file for a bit and didn't even see that 🤦🏼 . Time to get coffee and actually wake up before Githubbing 😄
Author
Owner

@onedr0p commented on GitHub (Mar 27, 2023):

Would there be anyway to set the key_file to an actual passphrase instead of a file path? I would like to not write files to disk if it can be avoided.

<!-- gh-comment-id:1485142425 --> @onedr0p commented on GitHub (Mar 27, 2023): Would there be anyway to set the `key_file` to an actual passphrase instead of a file path? I would like to not write files to disk if it can be avoided.
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

Sure, you just remove the _file suffix.

<!-- gh-comment-id:1485149931 --> @nitnelave commented on GitHub (Mar 27, 2023): Sure, you just remove the `_file` suffix.
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

oh, sorry, misunderstood: No, this one is generated by the server, so it has to be written to a file.

<!-- gh-comment-id:1485151324 --> @nitnelave commented on GitHub (Mar 27, 2023): oh, sorry, misunderstood: No, this one is generated by the server, so it has to be written to a file.
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

But you can generate it once (just start the server once) and then have this file replicated in read-only to every instance.

<!-- gh-comment-id:1485152359 --> @nitnelave commented on GitHub (Mar 27, 2023): But you can generate it once (just start the server once) and then have this file replicated in read-only to every instance.
Author
Owner

@onedr0p commented on GitHub (Mar 27, 2023):

Would it be worth opening an issue to request allowing us to generate the key and passing into the container via ENV?

Here's the issue I am facing:

I am deploying LLDAP in Kubernetes and have set replicas to 3, when lldap first starts each one of those replicas is going to generate a new key unless I use something like shared storage between the replicas. However that is not safe guaranteeing that these 3 containers will not try to write to the file at the same time.

The workaround I see:

First start LLDAP with one replica, exec into the container and grab the key value. After that, put that key as a secret and mount it to /data/private_key and then scale up the deployment.

This really isn't ideal and makes the person deploying LLDAP not really aware of these nuances.

The fix:

Allow people to generate the key before-hand and place it in the ENV for all containers to consume. Basically removing the need for the /data directory entirely.

Thanks for hearing me out, please let me know if I got anything wrong or if you would like me to elaborate further!

<!-- gh-comment-id:1485172598 --> @onedr0p commented on GitHub (Mar 27, 2023): Would it be worth opening an issue to request allowing us to generate the key and passing into the container via ENV? #### Here's the issue I am facing: I am deploying LLDAP in Kubernetes and have set replicas to 3, when lldap first starts each one of those replicas is going to generate a new key unless I use something like shared storage between the replicas. However that is not safe guaranteeing that these 3 containers will not try to write to the file at the same time. #### The workaround I see: First start LLDAP with one replica, exec into the container and grab the key value. After that, put that key as a secret and mount it to `/data/private_key` and then scale up the deployment. This really isn't ideal and makes the person deploying LLDAP not really aware of these nuances. #### The fix: Allow people to generate the key before-hand and place it in the ENV for all containers to consume. Basically removing the need for the `/data` directory entirely. Thanks for hearing me out, please let me know if I got anything wrong or if you would like me to elaborate further!
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

It's not that simple to generate a key, it depends on, well a dependency (opaque in this case), it's fairly implementation-specific. I don't really want to factor this out for this specific use-case.

I think the workaround you mentioned is the easiest. Feel free to contribute/check out https://github.com/Evantage-WS/lldap-kubernetes.

<!-- gh-comment-id:1485184245 --> @nitnelave commented on GitHub (Mar 27, 2023): It's not that simple to generate a key, it depends on, well a dependency (opaque in this case), it's fairly implementation-specific. I don't really want to factor this out for this specific use-case. I think the workaround you mentioned is the easiest. Feel free to contribute/check out https://github.com/Evantage-WS/lldap-kubernetes.
Author
Owner

@onedr0p commented on GitHub (Mar 27, 2023):

Yeah even that example uses a persistent volume claim for /data which is what I am trying to avoid. Fully stateless would be 👨🏼‍🍳 💋

The workaround I mentioned is not really straight forward either. From an outsider to LLDAP that wants to take a look at my configs and try to do the same they will not be aware of the manual steps I took which would be something like:

  1. Start LLDAP with one replica
  2. Exec into container and copy the contents of /data/private_key
  3. Create a kubernetes secret with the contents of that file.
  4. Remove /data mount
  5. Mount the secret into the deployment at /data/private_key
  6. Scale LLDAP up to 3 replicas

This really isn't ideal and hard to automate. I realize this is a "one time only" thing, but this can trip people up and bring in confusion around running lldap in high availability.

<!-- gh-comment-id:1485208333 --> @onedr0p commented on GitHub (Mar 27, 2023): Yeah even that example uses a persistent volume claim for `/data` which is what I am trying to avoid. Fully stateless would be 👨🏼‍🍳 💋 The workaround I mentioned is not really straight forward either. From an outsider to LLDAP that wants to take a look at my configs and try to do the same they will not be aware of the manual steps I took which would be something like: 1. Start LLDAP with one replica 2. Exec into container and copy the contents of `/data/private_key` 3. Create a kubernetes secret with the contents of that file. 4. Remove `/data` mount 5. Mount the secret into the deployment at `/data/private_key` 6. Scale LLDAP up to 3 replicas This really isn't ideal and hard to automate. I realize this is a "one time only" thing, but this can trip people up and bring in confusion around running lldap in high availability.
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

Let's say that I added a command lldap create_secret_key that creates a file with the secret key, and you could set the key in env. How would that significantly change the setup you describe? AFAICT, it would only remove step 5, you'd still need to "start lldap" to generate the key and extract it.

Generating it with an outside program is more or less not possible.

<!-- gh-comment-id:1485249648 --> @nitnelave commented on GitHub (Mar 27, 2023): Let's say that I added a command `lldap create_secret_key` that creates a file with the secret key, and you could set the key in env. How would that significantly change the setup you describe? AFAICT, it would only remove step 5, you'd still need to "start lldap" to generate the key and extract it. Generating it with an outside program is more or less not possible.
Author
Owner

@onedr0p commented on GitHub (Mar 27, 2023):

Yeah I don't see that helping out much either.

I guess this is more or less turning into an architectural discussion on why lldap is creating that key for us rather than letting the user pre-configure it via env, surely it could be possible if it matches the correct syntax or cryptography?

If I understand correctly, in theory I could run lldap locally and have it spit out a key and use that in my kubernetes deployment in an env var if it was supported?

<!-- gh-comment-id:1485277297 --> @onedr0p commented on GitHub (Mar 27, 2023): Yeah I don't see that helping out much either. I guess this is more or less turning into an architectural discussion on why lldap is creating that key for us rather than letting the user pre-configure it via env, surely it could be possible if it matches the correct syntax or cryptography? If I understand correctly, in theory I could run lldap locally and have it spit out a key and use that in my kubernetes deployment in an env var if it was supported?
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

Yes. The key is randomly generated by OPAQUE, and it's a struct with fields that are initialized from random data (but not just randomly initialized): https://sourcegraph.com/crates/opaque-ke@a9f9a64246700fcd22ef0f29383711acf2fae543/-/blob/src/opaque.rs?L48%3A12=

Moreover, this is subject to change in a future (breaking) update, so I don't want to externalize the key creation.

But yes, you can run lldap locally (you can grab the binaries from the release https://github.com/nitnelave/lldap/releases/tag/v0.4.2 ) and get it to generate a key for you, which you can then mount in your cluster.

<!-- gh-comment-id:1485284106 --> @nitnelave commented on GitHub (Mar 27, 2023): Yes. The key is randomly generated by OPAQUE, and it's a struct with fields that are initialized from random data (but not just randomly initialized): https://sourcegraph.com/crates/opaque-ke@a9f9a64246700fcd22ef0f29383711acf2fae543/-/blob/src/opaque.rs?L48%3A12= Moreover, this is subject to change in a future (breaking) update, so I don't want to externalize the key creation. But yes, you can run lldap locally (you can grab the binaries from the release https://github.com/nitnelave/lldap/releases/tag/v0.4.2 ) and get it to generate a key for you, which you can then mount in your cluster.
Author
Owner

@onedr0p commented on GitHub (Mar 27, 2023):

No worries and I don't mean to sound rude or anything but I've rarely ever witnessed something like this in an application, the only one that comes to mind is mosquitto (mqtt), but even that lets you generate the user/passwords outside of the app using their mosquitto_passwd command.

FWIW Authelia allows you to set the private keys via env (and also by file if you wanted to) like so:

AUTHELIA_JWT_SECRET: "somelongvalue"
AUTHELIA_SESSION_SECRET: "somelongvalue"
AUTHELIA_STORAGE_ENCRYPTION_KEY: "somelongvalue"

Maybe there's some refactoring to do to support something like this but it would very cool!

<!-- gh-comment-id:1485325839 --> @onedr0p commented on GitHub (Mar 27, 2023): No worries and I don't mean to sound rude or anything but I've rarely ever witnessed something like this in an application, the only one that comes to mind is mosquitto (mqtt), but even that lets you generate the user/passwords outside of the app using their `mosquitto_passwd` command. FWIW Authelia allows you to set the private keys via env (and also by file if you wanted to) like so: ```yaml AUTHELIA_JWT_SECRET: "somelongvalue" AUTHELIA_SESSION_SECRET: "somelongvalue" AUTHELIA_STORAGE_ENCRYPTION_KEY: "somelongvalue" ``` Maybe there's some refactoring to do to support something like this but it would very cool!
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

I mean, I'm open to suggestions, but there's relatively little I can do here :)
If it really helps, I can allow passing the value in env, but you'll still have to generate it manually by starting LLDAP locally.

<!-- gh-comment-id:1485336535 --> @nitnelave commented on GitHub (Mar 27, 2023): I mean, I'm open to suggestions, but there's relatively little I can do here :) If it really helps, I can allow passing the value in env, but you'll still have to generate it manually by starting LLDAP locally.
Author
Owner

@onedr0p commented on GitHub (Mar 27, 2023):

If it really helps, I can allow passing the value in env, but you'll still have to generate it manually by starting LLDAP locally.

That would help a lot! At least I could generate the secret locally and then add it in the env for my k8s deployment. Or, run it as a single replica and grab the value and then put it in env and then scale up. Either way would reduce the steps to get lldap running HA

<!-- gh-comment-id:1485343906 --> @onedr0p commented on GitHub (Mar 27, 2023): > If it really helps, I can allow passing the value in env, but you'll still have to generate it manually by starting LLDAP locally. That would help a lot! At least I could generate the secret locally and then add it in the env for my k8s deployment. Or, run it as a single replica and grab the value and then put it in env and then scale up. Either way would reduce the steps to get lldap running HA
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

Alright, can you create an issue for that then? That way I can track it better.

<!-- gh-comment-id:1485347392 --> @nitnelave commented on GitHub (Mar 27, 2023): Alright, can you create an issue for that then? That way I can track it better.
Author
Owner

@onedr0p commented on GitHub (Mar 27, 2023):

Alright, can you create an issue for that then? That way I can track it better.

Done: https://github.com/nitnelave/lldap/issues/504

I also have a suspicion that if you force people to provide this value in env or the file config it would remove a lot of code since you do not need to worry about generating it. But maybe that's just wishful thinking :D

<!-- gh-comment-id:1485349359 --> @onedr0p commented on GitHub (Mar 27, 2023): > Alright, can you create an issue for that then? That way I can track it better. Done: https://github.com/nitnelave/lldap/issues/504 I also have a suspicion that if you force people to provide this value in env or the file config it would remove a lot of code since you do not need to worry about generating it. But maybe that's just wishful thinking :D
Author
Owner

@nitnelave commented on GitHub (Mar 27, 2023):

Well, no, I have to generate it, that's how they can get the value in the first place! You can't just plug in /dev/urandom in there. But once they have the value, they can set it in env if they really want it (e.g. kube).

<!-- gh-comment-id:1485403326 --> @nitnelave commented on GitHub (Mar 27, 2023): Well, no, I *have* to generate it, that's how they can get the value in the first place! You can't just plug in /dev/urandom in there. But once they have the value, they can set it in env if they really want it (e.g. kube).
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#182
No description provided.