Manage domains without CLI #24

Open
opened 2020-01-07 13:21:05 +00:00 by Ghost · 24 comments

Is it possible with greenlock v3 to manage the domains without the command line like in v2 where I could just pass the list of domains when serving the application?

I couldn't find any way to do it.

Is it possible with greenlock v3 to manage the domains without the command line like in v2 where I could just pass the list of domains when serving the application? I couldn't find any way to do it.
Owner

Yeah, you can manage without the CLI.

To keep things simple and clean (and to work in cloud environments) the config now lives in its own file, not muddled in the code.

You can look at the examples in the README, but the easiest thing is just run the CLI and the copy the format of the file it creates.

Yeah, you can manage without the CLI. To keep things simple and clean (and to work in cloud environments) the config now lives in its own file, not muddled in the code. You can look at the examples in the README, but the easiest thing is just run the CLI and the copy the format of the file it creates.
Author

Ok, I think I did it. Can you tell me if this is the most straight forward way to do it without the CLI:

  require('greenlock-express').init(() => {
    const pkg = require('./package.json');
    const greenlock = require('@root/greenlock').create({
      // name & version for ACME client user agent
      packageAgent: pkg.name + '/' + pkg.version,

      // contact for security and critical bug notices
      maintainerEmail: <email>,

      // where to find .greenlockrc and set default paths
      packageRoot: __dirname,
    });
    greenlock.manager.defaults({
      subscriberEmail: <email>,
      agreeToTerms: true
    });
    greenlock.sites.add({
      subject: <domain>,
      altnames: [<domain>, <subdomain.domain>]
    }));
    return {
      greenlock,
      // whether or not to run at cloudscale
      cluster: false
    };
  }).ready(glx => glx.serveApp(app));
Ok, I think I did it. Can you tell me if this is the most straight forward way to do it without the CLI: ```javascript require('greenlock-express').init(() => { const pkg = require('./package.json'); const greenlock = require('@root/greenlock').create({ // name & version for ACME client user agent packageAgent: pkg.name + '/' + pkg.version, // contact for security and critical bug notices maintainerEmail: <email>, // where to find .greenlockrc and set default paths packageRoot: __dirname, }); greenlock.manager.defaults({ subscriberEmail: <email>, agreeToTerms: true }); greenlock.sites.add({ subject: <domain>, altnames: [<domain>, <subdomain.domain>] })); return { greenlock, // whether or not to run at cloudscale cluster: false }; }).ready(glx => glx.serveApp(app)); ```
Author

It'd be great to have an example of this in the README. Where would I copy the CLI output to?

Also I'd argue that it's simpler to keep config in the code - at the very least it's subjective.

It'd be great to have an example of this in the README. Where would I copy the CLI output to? Also I'd argue that it's simpler to keep config in the code - at the very least it's subjective.
Author

@homerjam Did you try what I did above? Did it work for you?
For me it works despite showing me an error, which is why I think there is probably a way to provide the data directly inside the create(). Any idea how @solderjs ?

@homerjam Did you try what I did above? Did it work for you? For me it works despite showing me an error, which is why I think there is probably a way to provide the data directly inside the create(). Any idea how @solderjs ?
Author

Yes, I tried the above but I get the error complaining about sites. I'm running an express app inside a docker container - I was passing greenlock email/domain config to the container via env vars but this is no longer possible using this manager.json config file.

Yes, I tried the above but I get the error complaining about sites. I'm running an express app inside a docker container - I was passing greenlock email/domain config to the container via env vars but this is no longer possible using this manager.json config file.
Author

Personally, with the above, I indeed got the error message about the missing sites, but then the server starts running the challenges and ends up serving the app correctly. Is it not what's happening to you?

Obviously, you would need to change a little the way you provide your domains, or make a small code to tied them up. Something like that (not tested yet):

const subjects = domains.filter(domain => domain.split('\\.').length===2);
const others = domains.filter(domain => domain.split('\\.').length>2);
subjects.forEach(domain => {
  const subDomains = others.filter(sub => sub.endsWith(domain));
  greenlock.sites.add({
    subject: domain,
    altnames: [domain, ...subDomains]
  });
}
Personally, with the above, I indeed got the error message about the missing sites, but then the server starts running the challenges and ends up serving the app correctly. Is it not what's happening to you? Obviously, you would need to change a little the way you provide your domains, or make a small code to tied them up. Something like that (not tested yet): const subjects = domains.filter(domain => domain.split('\\.').length===2); const others = domains.filter(domain => domain.split('\\.').length>2); subjects.forEach(domain => { const subDomains = others.filter(sub => sub.endsWith(domain)); greenlock.sites.add({ subject: domain, altnames: [domain, ...subDomains] }); }
Owner

I just released v4 which changes the config path to be a directory rather than a file. Update to that.

Where would I copy the CLI output to?

I meant the files that the CLI creates - server.js, app.js, greenlock.d, as listed in the REDME - not the debug output that it prints to the screen.

  greenlock.sites.add({
    subject: domain,
    altnames: [domain, ...subDomains]
  });

The API is intended for DYNAMIC updates - like when you get a new user sign up, not for static config.

If you try to use the API as a config file, it won't work as you expect and you'll probably hit rate limits. The manager callbacks allow you to use a database or whatever instead of the file system, but for the simplest case, just write the JSON or use the CLI.

I was passing greenlock email/domain config to the container via env vars but this is no longer possible using this manager.json config file.

If you're using Docker, you need to mount the config directory as read-write (or use a database), otherwise it can't save the certificates or refresh timestamps and you'll hit your the let's encrypt rate limits.

Docker is meant for ephemeral systems, not for things that need persistent state.

I'm working on some cloud account stuff that will make it easier to get around Docker's oddities, but the config file on a mounted volume will at least make it easy to use without anti-pattern hacks that lead to bugs and unexpected behaviors.

I just released v4 which changes the config path to be a directory rather than a file. Update to that. > Where would I copy the CLI output to? I meant the files that the CLI creates - `server.js`, `app.js`, `greenlock.d`, as listed in the REDME - not the debug output that it prints to the screen. ```js greenlock.sites.add({ subject: domain, altnames: [domain, ...subDomains] }); ``` The API is intended for DYNAMIC updates - like when you get a new user sign up, not for static config. If you try to use the API as a config file, it won't work as you expect and you'll probably hit rate limits. The manager callbacks allow you to use a database or whatever instead of the file system, but for the simplest case, just write the JSON or use the CLI. > I was passing greenlock email/domain config to the container via env vars but this is no longer possible using this manager.json config file. If you're using Docker, you need to mount the config directory as read-write (or use a database), otherwise it can't save the certificates or refresh timestamps and you'll hit your the let's encrypt rate limits. Docker is meant for ephemeral systems, not for things that need persistent state. I'm working on some cloud account stuff that will make it easier to get around Docker's oddities, but the config file on a mounted volume will at least make it easy to use without anti-pattern hacks that lead to bugs and unexpected behaviors.
Author

I was mounting a directory for the certificates previously (v1/2?) which is straightforward enough and not strictly necessary as hitting rate limits depends how often you restart the container.

What is non trivial/a bit of a pain is having to run the cli on the docker host machine - this wouldn't be possible on Google Cloud Run for example (yes that come with SSL anyway).

A simple config API would be more helpful. I would like to only supply domains and maintainer email (plus optional store) and have it "just work".

I was mounting a directory for the certificates previously (v1/2?) which is straightforward enough and not strictly necessary as hitting rate limits depends how often you restart the container. What is non trivial/a bit of a pain is having to run the cli on the docker host machine - this wouldn't be possible on Google Cloud Run for example (yes that come with SSL anyway). A simple config API would be more helpful. I would like to only supply domains and maintainer email (plus optional store) and have it "just work".
Author

I couldn't agree more. When I see greenlock-express, what I expect would be something like that:

const greenlock = require('greenlock-express');

greenlock({
  app,             //Your express application
  maintainerEmail, //The maintainer email
  domains          //The list of domain we want a certificate for
});

And that's it. This should be all I have to care for to get my app running.

Optionaly, I would expect to describe the way I want to store my certificates. Something along these lines:

const greenlock = require('greenlock-express');

greenlock({
  ...
  storage: {
    type: 'local',
    location: './certificates'
  }
});

Can't we make something like that? I can help if needed.

I couldn't agree more. When I see greenlock-express, what I expect would be something like that: ```javascript const greenlock = require('greenlock-express'); greenlock({ app, //Your express application maintainerEmail, //The maintainer email domains //The list of domain we want a certificate for }); ``` And that's it. This should be all I have to care for to get my app running. Optionaly, I would expect to describe the way I want to store my certificates. Something along these lines: ```javascript const greenlock = require('greenlock-express'); greenlock({ ... storage: { type: 'local', location: './certificates' } }); ``` Can't we make something like that? I can help if needed.
Owner

Why are you using the CLI and the API?

What is it that you're trying to do that isn't accomplished with the basic example in the README?

server.js

"use strict";

var app = require("./app.js");

require("greenlock-express")
    .init({
        packageRoot: __dirname,
        configDir: "./greenlock.d",

        // contact for security and critical bug notices
        maintainerEmail: "jon@example.com",

        // whether or not to run at cloudscale
        cluster: false
    })
    // Serves on 80 and 443
    // Get's SSL certificates magically!
    .serve(app);

greenlock.d/config.json

{ "sites": [{ "subject": "example.com", "altnames": ["example.com"] }] }
Why are you using the CLI and the API? What is it that you're trying to do that isn't accomplished with the basic example in the README? `server.js` ```js "use strict"; var app = require("./app.js"); require("greenlock-express") .init({ packageRoot: __dirname, configDir: "./greenlock.d", // contact for security and critical bug notices maintainerEmail: "jon@example.com", // whether or not to run at cloudscale cluster: false }) // Serves on 80 and 443 // Get's SSL certificates magically! .serve(app); ``` `greenlock.d/config.json` ```json { "sites": [{ "subject": "example.com", "altnames": ["example.com"] }] } ```
Owner

I removed the CLI from the top-level example and moved the walthrough to its own page rather than being in a <details> dropdown. Perhaps that will help with reading it?

I removed the CLI from the top-level example and moved the walthrough to its own page rather than being in a `<details>` dropdown. Perhaps that will help with reading it?
Author

Ok, let me check if I understand correctly.

Let's assume that I have an object like this:

const sites = [{ "subject": "example.com", "altnames": ["example.com"] }] };

Now, if I want to serve them, is this what I should do:

const packageRoot = __dirname,
const configDir = "greenlock.d",

//Creates the greenlock folder if needed
fs.mkdirSync(path.normalize(path.join(packageRoot, configDir)), { recursive: true });

//Creates the config.json file
fs.writeFileSync(path.normalize(path.join(packageRoot, configDir, 'config.json')), JSON.stringify({ sites }, null, 4));

require("greenlock-express").init({
    packageRoot,
    configDir,
    maintainerEmail,
    cluster: false
}).serve(app);

Am I all right?

If I am, indeed, I'm fine with it and you did a great job with the v4.

Ok, let me check if I understand correctly. Let's assume that I have an object like this: ```javascript const sites = [{ "subject": "example.com", "altnames": ["example.com"] }] }; ``` Now, if I want to serve them, is this what I should do: ```javascript const packageRoot = __dirname, const configDir = "greenlock.d", //Creates the greenlock folder if needed fs.mkdirSync(path.normalize(path.join(packageRoot, configDir)), { recursive: true }); //Creates the config.json file fs.writeFileSync(path.normalize(path.join(packageRoot, configDir, 'config.json')), JSON.stringify({ sites }, null, 4)); require("greenlock-express").init({ packageRoot, configDir, maintainerEmail, cluster: false }).serve(app); ``` Am I all right? If I am, indeed, I'm fine with it and you did a great job with the v4.
Author

I tried the above and it looks promising however the connection seems to timeout at the point of the TLS handshake. Something to do with agreeToTerms?

$ curl -v *.*.*
---
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
<-- HANGS HERE? -->
2020-01-13 12:51:31,025 DEBG 'forever' stdout output:
Listening on 0.0.0.0:80 for ACME challenges, and redirecting to HTTPS

2020-01-13 12:51:31,027 DEBG 'forever' stdout output:
Listening on 0.0.0.0:443 for secure traffic

2020-01-13 12:51:31,036 DEBG 'forever' stdout output:
Ready to Serve:

2020-01-13 12:51:31,036 DEBG 'forever' stdout output:
	 *.*.*

2020-01-13 12:51:41,241 DEBG 'forever' stdout output:
[default] store.module: greenlock-store-fs

2020-01-13 12:51:41,243 DEBG 'forever' stdout output:
[default] challenges.http-01.module: acme-http-01-standalone

2020-01-13 12:51:41,244 DEBG 'forever' stdout output:
[default] renewOffset: -45d

2020-01-13 12:51:41,244 DEBG 'forever' stdout output:
[default] renewStagger: 3d
[default] accountKeyType: EC-P256

2020-01-13 12:51:41,245 DEBG 'forever' stdout output:
[default] serverKeyType: RSA-2048

[default] subscriberEmail: *@*.*
[default] agreeToTerms: (show notice on use)

2020-01-13 12:51:41,245 DEBG 'forever' stdout output:


2020-01-13 12:51:41,252 DEBG 'forever' stdout output:
ACME Directory URL: https://acme-v02.api.letsencrypt.org/directory

2020-01-13 12:51:41,750 DEBG 'forever' stdout output:

By using this software you (*@*.*) are agreeing to the following:

2020-01-13 12:51:41,751 DEBG 'forever' stdout output:
ACME Subscriber Agreement: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Greenlock/ACME.js Terms of Use: https://rootprojects.org/legal/#terms
I tried the above and it looks promising however the connection seems to timeout at the point of the TLS handshake. Something to do with `agreeToTerms`? ``` $ curl -v *.*.* --- * ALPN, offering h2 * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: * CAfile: /etc/ssl/cert.pem CApath: none * TLSv1.2 (OUT), TLS handshake, Client hello (1): <-- HANGS HERE? --> ``` ``` 2020-01-13 12:51:31,025 DEBG 'forever' stdout output: Listening on 0.0.0.0:80 for ACME challenges, and redirecting to HTTPS 2020-01-13 12:51:31,027 DEBG 'forever' stdout output: Listening on 0.0.0.0:443 for secure traffic 2020-01-13 12:51:31,036 DEBG 'forever' stdout output: Ready to Serve: 2020-01-13 12:51:31,036 DEBG 'forever' stdout output: *.*.* 2020-01-13 12:51:41,241 DEBG 'forever' stdout output: [default] store.module: greenlock-store-fs 2020-01-13 12:51:41,243 DEBG 'forever' stdout output: [default] challenges.http-01.module: acme-http-01-standalone 2020-01-13 12:51:41,244 DEBG 'forever' stdout output: [default] renewOffset: -45d 2020-01-13 12:51:41,244 DEBG 'forever' stdout output: [default] renewStagger: 3d [default] accountKeyType: EC-P256 2020-01-13 12:51:41,245 DEBG 'forever' stdout output: [default] serverKeyType: RSA-2048 [default] subscriberEmail: *@*.* [default] agreeToTerms: (show notice on use) 2020-01-13 12:51:41,245 DEBG 'forever' stdout output: 2020-01-13 12:51:41,252 DEBG 'forever' stdout output: ACME Directory URL: https://acme-v02.api.letsencrypt.org/directory 2020-01-13 12:51:41,750 DEBG 'forever' stdout output: By using this software you (*@*.*) are agreeing to the following: 2020-01-13 12:51:41,751 DEBG 'forever' stdout output: ACME Subscriber Agreement: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf Greenlock/ACME.js Terms of Use: https://rootprojects.org/legal/#terms ```
Owner

@sharcoux

fs.writeFileSync(path.normalize(path.join(packageRoot, configDir, 'config.json')), JSON.stringify({ sites }, null, 4));

If you do that then you'll overwrite the persistent storage every time this runs, and it'll lose renewAt.

I'd recommend that you just create the file on the mounted volume.

Or that you use the command line:

npx greenlock add --subject "$SITENAME" --altnames "$SITENAME"

Or edit your Dockerfile:

RUN npx greenlock add --subject "$SITENAME" --altnames "$SITENAME"

Or you use the API in an init script:

var greenlock = require('greenlock').create({
  packageRoot: __dirname,
  configDir: "./greenlock.d",

  // contact for security and critical bug notices
  maintainerEmail: "jon@example.com",
});
greenlock.sites.add({
  subject: sitename,
  altnames: [sitename]
});

If you only have one or two sites and you're setting things up semi-manually, I'd recommend just using the CLI. You don't have to have anything extra installed (it's just an npm script, nothing more, nothing less).

If you've got hundreds or thousands of sites, then writing the four callbacks for the standard list, read, write, remove functions and using the API makes a lot of sense.

@sharcoux ```js fs.writeFileSync(path.normalize(path.join(packageRoot, configDir, 'config.json')), JSON.stringify({ sites }, null, 4)); ``` If you do that then you'll overwrite the persistent storage every time this runs, and it'll lose `renewAt`. I'd recommend that you just create the file on the mounted volume. Or that you use the command line: ```bash npx greenlock add --subject "$SITENAME" --altnames "$SITENAME" ``` Or edit your Dockerfile: ```dockerfile RUN npx greenlock add --subject "$SITENAME" --altnames "$SITENAME" ``` Or you use the API in an init script: ```js var greenlock = require('greenlock').create({ packageRoot: __dirname, configDir: "./greenlock.d", // contact for security and critical bug notices maintainerEmail: "jon@example.com", }); greenlock.sites.add({ subject: sitename, altnames: [sitename] }); ``` If you only have one or two sites and you're setting things up semi-manually, I'd recommend just using the CLI. You don't have to have anything extra installed (it's just an npm script, nothing more, nothing less). If you've got hundreds or thousands of sites, then writing the four callbacks for the standard list, read, write, remove functions and using the API makes a lot of sense.
Owner

@homerjam Not sure what that's about. However, I'd suggest testing it without forever or pm2 and opening a separate issue. Whatever issue you're having there is unrelated to the CLI.

@homerjam Not sure what that's about. However, I'd suggest testing it without forever or pm2 and opening a separate issue. Whatever issue you're having there is unrelated to the CLI.
Owner

How many users are you actually talking about?

Is it enough users that you have a database to manage them and their domains? Or is this a onesy-twosy sort of thing?

Are you deploying a server per user? Or multiple users on a single server?

I just need the user to provide the necessary data only, and not care about anything complicated like running commands.

Then just ask the user for what you need and create the template file with the command or environment that you need.

I don't get what you're trying to do because on the one hand it sounds like you've got some sort of big complex system and on the other hand it sounds like you want to not do any integration with your system.

I'm building a system that handles many users. I'm going to be storing that info in a database and using the API.

I have a friend who manages a few users here and there. He logs into his server and adds a new domain and updates his app.js to serve that domain in a particular way each time he needs to add a user, and the CLI works great for that.

I don't understand what your use case is or what you're trying to do. What is your stack, and why?

How many users are you actually talking about? Is it enough users that you have a database to manage them and their domains? Or is this a onesy-twosy sort of thing? Are you deploying a server per user? Or multiple users on a single server? > I just need the user to provide the necessary data only, and not care about anything complicated like running commands. Then just ask the user for what you need and create the template file with the command or environment that you need. I don't get what you're trying to do because on the one hand it sounds like you've got some sort of big complex system and on the other hand it sounds like you want to not do any integration with your system. I'm building a system that handles many users. I'm going to be storing that info in a database and using the API. I have a friend who manages a few users here and there. He logs into his server and adds a new domain and updates his app.js to serve that domain in a particular way each time he needs to add a user, and the CLI works great for that. I don't understand what your use case is or what you're trying to do. What is your stack, and why?
Author

What I don't understand is why the focus on a config file instead of an API. It's relatively trivial to read and write JSON if the need arose. Why does that functionality need to be baked-in in an opaque way?

I don't mean to sound ungrateful - there literally isn't a single alternative project out there so thank for your work. I just feel that presently the simplest use case has been overlooked.

What I don't understand is why the focus on a config file instead of an API. It's relatively trivial to read and write JSON if the need arose. Why does that functionality need to be baked-in in an opaque way? I don't mean to sound ungrateful - there literally isn't a single alternative project out there so thank for your work. I just feel that presently the simplest use case has been overlooked.
Author

I'm providing a server framework. If you really want to know, you can check my project and especially this part

In the end, my user have a simple configuration file that will create a whole server running with a database, ssl certificates thanks to greenlock, default security rules thanks to helmet, login system with OAuth or login/pwd + jwt, access rules for every piece of data in the database...

So, in the end, I'm not managing users. I'm providing a wrapper that will do everything for them. To enable https and helmet, this is the only thing they have to do:

securityPlugin({
  app,
  domains: ['mydomain.com', 'www.mydomain.com'],
  webmaster: 'webmaster@mydomain.com',
})

What I don't really get is that I was able to implement this very easily with greenlock v2. Why can't I do it with v3 and v4? I feel as if the process was becoming more complex with each version... I agree with @homerjam on this one.
(and I also agree on the big thank you for your work!)

So, how about my previous piece of code? Will it work as I expect?

If it does, maybe I could help make a PR to provide a function that will make greenlock as simple to implement as it is for the users of my framework?

I'm providing a server framework. If you really want to know, you can check [my project](https://github.com/Sharcoux/SimpleQL) and especially [this part](https://github.com/Sharcoux/SimpleQL/blob/master/docs/plugins/security.md) In the end, my user have a simple configuration file that will create a whole server running with a database, ssl certificates thanks to greenlock, default security rules thanks to helmet, login system with OAuth or login/pwd + jwt, access rules for every piece of data in the database... So, in the end, I'm not managing users. I'm providing a wrapper that will do everything for them. To enable https and helmet, this is the only thing they have to do: ```javascript securityPlugin({ app, domains: ['mydomain.com', 'www.mydomain.com'], webmaster: 'webmaster@mydomain.com', }) ``` What I don't really get is that I was able to implement this very easily with greenlock v2. Why can't I do it with v3 and v4? I feel as if the process was becoming more complex with each version... I agree with @homerjam on this one. (and I also agree on the big thank you for your work!) So, how about my previous piece of code? Will it work as I expect? If it does, maybe I could help make a PR to provide a function that will make greenlock as simple to implement as it is for the users of my framework?
Author

I deleted my previous post by mistake.

I tried the following code:

//The data provided by the user
const sites = [
        {
            "subject": "mydomain.ovh",
            "altnames": [
                "mydomain.ovh"
            ]
        },
        {
            "subject": "mydomain.fr",
            "altnames": [
                "mydomain.fr",
                "www.mydomain.fr"
            ]
        },
        {
            "subject": "mydomain.education",
            "altnames": [
                "mydomain.education",
                "www.mydomain.education"
            ]
        }
    ];

//Read the current config file
let configRawContent = null;
try {
  configRawContent = fs.readFileSync(path.normalize(path.join(packageRoot, configDir, 'config.json')));
} catch(err) {
  if(err.code!=='ENOENT') { console.error(err.code, err); process.exit(); }
}

//Update sites with available data if exist
let configFile = { sites };
if(configRawContent) {
  configFile = JSON.parse(configRawContent);
  configFile.sites = sites.map(({subject, altNames}) => {
    const configSiteData = configFile.sites.find(site => site.subject===subject)) || {};
    return {...configSiteData, subject, altNames}
  }
}

//Write the updated file content
fs.writeFileSync(path.normalize(path.join(packageRoot, configDir, 'config.json')), JSON.stringify(configFile, null, 4));

It seems to be working, but I have weird logs:

ACME Directory URL: https://acme-v02.api.letsencrypt.org/directory
debug: ignoring servername "usunkonto.jzon.pl"
       (it's probably either missing from your config, or a bot)
set greenlockOptions.notify to override the default logger
servername_unknown (more info available: servername)
debug: ignoring servername "xx.xx.xx.xx:443"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
debug: invalid servername "xx.xx.xx.xx:443"
       (it's probably just a bot trolling for vulnerable servers)
servername_invalid (more info available: servername)
debug: ignoring servername "xx.xx.xx.xx:443"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
debug: ignoring servername "ovh53.filmac.com"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
debug: invalid servername "xx.xx.xx.xx:443"
       (it's probably just a bot trolling for vulnerable servers)
servername_invalid (more info available: servername)
debug: ignoring servername "xx.xx.xx.xx:443"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
debug: ignoring servername "blog.jzon.pl"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
debug: ignoring servername "www.mydomain.ovh"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
debug: invalid servername "xx.xx.xx.xx:443"
       (it's probably just a bot trolling for vulnerable servers)
servername_invalid (more info available: servername)
debug: ignoring servername "xx.xx.xx.xx:443"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
debug: invalid servername "xx.xx.xx.xx:443"
       (it's probably just a bot trolling for vulnerable servers)
servername_invalid (more info available: servername)
debug: ignoring servername "xx.xx.xx.xx:443"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
debug: ignoring servername "www.google-analytics.com"
       (it's probably either missing from your config, or a bot)
servername_unknown (more info available: servername)
Listening on 0.0.0.0:80 for ACME challenges, and redirecting to HTTPS
Listening on 0.0.0.0:443 for secure traffic
Ready to Serve:
         mydomain.ovh
         mydomain.fr www.mydomain.fr
         mydomain.education www.mydomain.education

xx.xx.xx.xx being the ip of my server.

What is all this stuff?

I deleted my previous post by mistake. I tried the following code: ```javascript //The data provided by the user const sites = [ { "subject": "mydomain.ovh", "altnames": [ "mydomain.ovh" ] }, { "subject": "mydomain.fr", "altnames": [ "mydomain.fr", "www.mydomain.fr" ] }, { "subject": "mydomain.education", "altnames": [ "mydomain.education", "www.mydomain.education" ] } ]; //Read the current config file let configRawContent = null; try { configRawContent = fs.readFileSync(path.normalize(path.join(packageRoot, configDir, 'config.json'))); } catch(err) { if(err.code!=='ENOENT') { console.error(err.code, err); process.exit(); } } //Update sites with available data if exist let configFile = { sites }; if(configRawContent) { configFile = JSON.parse(configRawContent); configFile.sites = sites.map(({subject, altNames}) => { const configSiteData = configFile.sites.find(site => site.subject===subject)) || {}; return {...configSiteData, subject, altNames} } } //Write the updated file content fs.writeFileSync(path.normalize(path.join(packageRoot, configDir, 'config.json')), JSON.stringify(configFile, null, 4)); ``` It seems to be working, but I have weird logs: ``` ACME Directory URL: https://acme-v02.api.letsencrypt.org/directory debug: ignoring servername "usunkonto.jzon.pl" (it's probably either missing from your config, or a bot) set greenlockOptions.notify to override the default logger servername_unknown (more info available: servername) debug: ignoring servername "xx.xx.xx.xx:443" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) debug: invalid servername "xx.xx.xx.xx:443" (it's probably just a bot trolling for vulnerable servers) servername_invalid (more info available: servername) debug: ignoring servername "xx.xx.xx.xx:443" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) debug: ignoring servername "ovh53.filmac.com" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) debug: invalid servername "xx.xx.xx.xx:443" (it's probably just a bot trolling for vulnerable servers) servername_invalid (more info available: servername) debug: ignoring servername "xx.xx.xx.xx:443" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) debug: ignoring servername "blog.jzon.pl" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) debug: ignoring servername "www.mydomain.ovh" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) debug: invalid servername "xx.xx.xx.xx:443" (it's probably just a bot trolling for vulnerable servers) servername_invalid (more info available: servername) debug: ignoring servername "xx.xx.xx.xx:443" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) debug: invalid servername "xx.xx.xx.xx:443" (it's probably just a bot trolling for vulnerable servers) servername_invalid (more info available: servername) debug: ignoring servername "xx.xx.xx.xx:443" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) debug: ignoring servername "www.google-analytics.com" (it's probably either missing from your config, or a bot) servername_unknown (more info available: servername) Listening on 0.0.0.0:80 for ACME challenges, and redirecting to HTTPS Listening on 0.0.0.0:443 for secure traffic Ready to Serve: mydomain.ovh mydomain.fr www.mydomain.fr mydomain.education www.mydomain.education ``` xx.xx.xx.xx being the ip of my server. What is all this stuff?
Author

@solderjs ? Is it ok what I'm doing?

@solderjs ? Is it ok what I'm doing?
Owner

It's odd that you're getting spammed by bots before the server even prints out to the screen that it's listening. However, it is very normal to be spammed by bots.

I should remove the debugs and update the default logger.

I think that what you really should do is to create the two site manager callbacks that work the way that you want them to work and store the files where you want them to be stored rather than trying to work around how the default site manager callbacks work in Greenlock Express.

I've been meaning to publish some howto videos, but I got caught up in the meta of having a nice recording setup and didn't finish them yet...

I'll have them done this week though. I'm pretty darn close.

It's odd that you're getting spammed by bots before the server even prints out to the screen that it's listening. However, it is very normal to be spammed by bots. I should remove the `debug`s and update the default logger. I think that what you really should do is to create the two site manager callbacks that work the way that you want them to work and store the files where you want them to be stored rather than trying to work around how the default site manager callbacks work in Greenlock Express. I've been meaning to publish some howto videos, but I got caught up in the meta of having a nice recording setup and didn't finish them yet... I'll have them done this week though. I'm pretty darn close.
Owner

@homerjam If you're using Docker then you should just put the CLI command to init the config directory and add your domain(s) in your Dockerfile and have it read from the environment variable(s).

Re-initializing with the same values each time is a no-op and won't cause any issues, so as long as you have your config directory in a mounted volume that will work just fine.

@homerjam If you're using Docker then you should just put the CLI command to init the config directory and add your domain(s) in your Dockerfile and have it read from the environment variable(s). Re-initializing with the same values each time is a no-op and won't cause any issues, so as long as you have your config directory in a mounted volume that will work just fine.
Author

@solderjs Thank you for your answer, but I have to confess that I am not sure to understand what you mean... Maybe you could answer these few questions to help me understand better.

  1. Is what I'm doing enough and will it make greenlock work as expected?

  2. "create the two site manager callbacks" -> What do you mean?

  3. "store the files where you want them to be stored" -> Which files are you talking about exactly? The certificates, or the config?

@solderjs Thank you for your answer, but I have to confess that I am not sure to understand what you mean... Maybe you could answer these few questions to help me understand better. 1. Is what I'm doing enough and will it make greenlock work as expected? 2. "create the two site manager callbacks" -> What do you mean? 3. "store the files where you want them to be stored" -> Which files are you talking about exactly? The certificates, or the config?
Author

@solderjs , could you precise your thoughts?

@solderjs , could you precise your thoughts?
Sign in to join this conversation.
No Label
No Milestone
No Assignees
2 Participants
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: root/greenlock-express.js#24
No description provided.