Skip to content

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

@mscdex

Description

@mscdex

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',
  });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions