Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tls-alpn-01 docs update for newer node versions #96

Open
mscdex opened this issue Dec 20, 2024 · 0 comments
Open

tls-alpn-01 docs update for newer node versions #96

mscdex opened this issue Dec 20, 2024 · 0 comments

Comments

@mscdex
Copy link

mscdex commented Dec 20, 2024

Since node v20.18.0 and v22.9.0 and newer, you no longer need nginx/haproxy in front in order to do tls-alpn-01 issuance/renewal. Starting with these node versions, you can set the key and certificate for a connection inside the ALPNCallback in the https server config object, which allows you to do the tls-alpn-01 validation completely within node. Example:

let sslRenew = null;

// First define the `ALPNCallback` in your HTTPS server config
const httpsServer = https.createServer({
  // ...
  ALPNCallback: function({ servername, protocols }) {
    if (!Array.isArray(protocols))
      return;
    let http10;
    let http11;
    let acme;
    for (const protocol of protocols) {
      switch (protocol) {
        case 'http/1.0':
          http10 = protocol;
          break;
        case 'http/1.1':
          http11 = protocol;
          break;
        case 'acme-tls/1':
          acme = protocol;
          break;
      }
    }
    if (acme && sslRenew?.type === 'tls-alpn-01') {
      this.setKeyCert(sslRenew.ctx);
      return acme;
    }
    return http11 || http10 || undefined;
  },
});

// Then somewhere else where you are requesting a new certificate
// via `auto()`:
async function renewCert() {
  // ...
  const cert = await client.auto({
    // ...
    challengeCreateFn: async (authz, challenge, keyAuthorization) => {
      const type = challenge.type;
      switch (type) {
        case 'http-01':
          // Handling http-01 is outside the scope of this example
          sslRenew = {
            type,
            url: `/.well-known/acme-challenge/${challenge.token}`,
            data: keyAuthorization,
          };
          break;
        case 'tls-alpn-01': {
          const [ alpnKey, alpnCert ] =
            await acme.crypto.createAlpnCertificate(
              authz,
              keyAuthorization
            );
          sslRenew = {
            type,
            ctx: tls.createSecureContext({
              key: alpnKey,
              cert: alpnCert,
              minVersion: 'TLSv1.2',
            }),
          };
          break;
        }
      }
    },
    challengeRemoveFn: (authz) => {
      sslRenew = null;
    },
  });

  // Store key and obtained cert somewhere ...

  // Update the HTTPS server to use them ...
  httpsServer.setSecureContext({
    key,
    cert,
    minVersion: 'TLSv1.2',
  });
}
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

No branches or pull requests

1 participant