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',
});
}
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
ALPNCallbackin the https server config object, which allows you to do the tls-alpn-01 validation completely within node. Example: