Custom .env file in server.json (dotEnv module)

This is the scenario.
I have a folder in which a server has never been started.
And inside this folder two files:

server.json (with “dotenvFile” set):

{
    "profile": "${server.profile}",
    "app": {
        "cfengine": "lucee@5.3.9.133"
    },
    "name": "${server.name}",
    "openBrowser": false,
    "web": {
        "host": "0.0.0.0",
        "http": {
            "port": "${server.port}"
        }
    },
    "dotenvFile": ".custom.env"
}

and a .custom.env file used in server.json in dotenvFile key

server.name = test-dotenv
server.port = 6062
server.profile = development

if I start the server the CLI remains blocked starting the server…

server-start

I have to kill the terminal.

It doesn’t happen if I remove the “dotenvFile” key and use the default env file name (“.env”)
OR
if I had previously started a server inside this folder (without specifying “dotenvFile” in server.json).

The CLI gets freeze, it doesn’t install any servers inside
$user/.CommandBox/server
and I can’t find any log files to understand the error.

There is nothing significant in
$user/.CommandBox/logs/commandbox.log.

Can you help me?

I assume you have ripped a hole in the fabric of the space time continuum by creating an endless loop. It always gets very tricky when you try to use information stored in the server.json to affect the values of the server.json itself due to the chicken-egg problems.

Glancing at the dotenv code, I don’t see the issue right off, but you can get a stack trace of what the CLI is doing with the jstack -l <pid> command (jstack comes with a JDK). You can also tie FusionReactor to the CLI to monitor what’s happening.

Here’s a fun thought, how would this server.json work?

{
    "dotenvFile": "${NameOfFile}.env"
}

In what order should

  • the server.json be read
  • system setting placeholders be expanded in the server.json’s keys
  • the dotenv module read the dotenvfile

And here’s the best part-- no matter what you say, it won’t work for at least some of your user’s workflows! :rofl:

Brad, you are completely right. :sweat_smile:
Even before using it, I thought this feature (dotenvFile for server.json) was a bit problematic …

Here you find the jstack output:
https://justpaste.it/2fw11

This is really a very complicated thing for me :sweat_smile:, but the first error maybe comes from this file:

If you can give me some indication, I can try to play with it a bit, even if I don’t guarantee the result… :grin:

Many thanks, as always :relaxed:

Yes, the dot env file can be a comma-delimited list of file globbing patterns. It would seem you’ve hit some sort of endless loop inside of the Globber library actually. I’d have to see what the actual file path was that’s being processed.

Also note, any server default dotenvfile settings will be added into the mix. It doesn’t appear that there is any logging in the dotenv module that shows the paths pre-globbing.

So in theory, .custom.env in the server.json should turn into /absolute/path/to/webroot/.custom.env which should be pretty cut and dried and wouldn’t be any different than running the following command in CommandBox:

dir /absolute/path/to/webroot/.custom.env

To debug, I’d dump out the serverEnvFile variable to the screen prior to this line

variables.wirebox.getInstance( "Globber" )
1 Like

@Roberto_Marzialetti Did you get any more info on this? I’m quite curious about the resolution.

ok
I investigated a bit.
I added a small log.

I replicated the same function from line 56, step by step:

addLog("serverEnvFile: [#serverEnvFile#]");
//result: [\\.custom.env]
//I tried to remove the double slashes but the problem persists.

//add pattern to Globber...
variables.wirebox.getInstance("Globber").setPattern(serverEnvFile);

//get pattern just entered
addLog('getPattern: [#variables.wirebox.getInstance("Globber").getPattern()#]');
//result: [] (yes, empty)

addLog('matches: #SerializeJSON(variables.wirebox.getInstance("Globber").matches())#');
//this get an error: "Cannot glob empty patter eith no base directory"

//restart with original code from here:
variables.wirebox.getInstance( "Globber" )

It seems the problem is that it can’t set the pattern.

I also tried to set the absolute path of the file by hand before:
variables.wirebox.getInstance( "Globber" )
like this:
serverEnvFile = "/absolute/myhost/code/.custom.env ";

and works :sweat_smile::grin:

I’m not quite sure what you are trying to do with your test code, but every time you run getInstance(), you are getting a brand new fresh Globber instance as it is not a singleton. This is why it appear you cannot set the pattern as you are looking for it in a totally separate CFC instance than the one you set it into.

Oh. So sorry.

Restart:

addLog( "serverEnvFile: [#serverEnvFile#]" );
//serverEnvFile: [\\.custom.env]
//
var glb = variables.wirebox.getInstance( "Globber" )

glb.setPattern( serverEnvFile )

addLog( 'getPattern: [#glb.getPattern()#]' );
//getPattern: [\\.custom.env]

addLog( 'matches: [#glb.matches()#]' );
//here software crashes (infinite loops).

However, serverEnvFile should contain the absolute path.
Right?

Perhaps the problem is in line 48:
serverJSON.dotenvFile.listMap ((f) => variables.fileSystemUtil.resolvePath (f, getDirectoryFromPath (serverInfo.serverConfigFile)))

This comes back: \\. custom.env
and not the absolute path of the .env file.

Can be?