roster-server 2.1.10 → 2.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +49 -9
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -5,6 +5,7 @@ const https = require('https');
5
5
  const tls = require('tls');
6
6
  const { EventEmitter } = require('events');
7
7
  const Greenlock = require('./vendor/greenlock-express/greenlock-express.js');
8
+ const GreenlockShim = require('./vendor/greenlock-express/greenlock-shim.js');
8
9
  const log = require('lemonlog')('roster');
9
10
 
10
11
  // CRC32 implementation for deterministic port assignment
@@ -707,7 +708,7 @@ class Roster {
707
708
  return this.startLocalMode();
708
709
  }
709
710
 
710
- const greenlock = Greenlock.init({
711
+ const greenlockOptions = {
711
712
  packageRoot: __dirname,
712
713
  configDir: this.greenlockStorePath,
713
714
  maintainerEmail: this.email,
@@ -724,6 +725,13 @@ class Roster {
724
725
  else if (event === 'warning') log.warn(msg);
725
726
  else log.info(msg);
726
727
  }
728
+ };
729
+ // Keep a direct greenlock runtime handle so we can call get() explicitly under Bun
730
+ // before binding :443, avoiding invalid non-TLS responses on startup.
731
+ const greenlockRuntime = GreenlockShim.create(greenlockOptions);
732
+ const greenlock = Greenlock.init({
733
+ ...greenlockOptions,
734
+ greenlock: greenlockRuntime
727
735
  });
728
736
 
729
737
  return greenlock.ready(async glx => {
@@ -845,14 +853,46 @@ class Roster {
845
853
  }
846
854
  return null;
847
855
  };
856
+ const issueAndReloadPemsForServername = async (servername) => {
857
+ const host = normalizeHostInput(servername).trim().toLowerCase();
858
+ if (!host) return null;
859
+
860
+ let pems = resolvePemsForServername(host);
861
+ if (pems) return pems;
862
+
863
+ try {
864
+ await greenlockRuntime.get({ servername: host });
865
+ } catch (error) {
866
+ log.warn(`⚠️ Greenlock issuance failed for ${host}: ${error?.message || error}`);
867
+ }
868
+
869
+ pems = resolvePemsForServername(host);
870
+ if (pems) return pems;
871
+
872
+ // For wildcard zones, try a valid subdomain bootstrap host so Greenlock can
873
+ // resolve the wildcard site without relying on invalid "*.domain" servername input.
874
+ const wildcardSubject = wildcardSubjectForHost(host);
875
+ const zone = wildcardSubject ? wildcardRoot(wildcardSubject) : null;
876
+ if (zone) {
877
+ const bootstrapHost = `bun-bootstrap.${zone}`;
878
+ try {
879
+ await greenlockRuntime.get({ servername: bootstrapHost });
880
+ } catch (error) {
881
+ log.warn(`⚠️ Greenlock wildcard bootstrap failed for ${bootstrapHost}: ${error?.message || error}`);
882
+ }
883
+ pems = resolvePemsForServername(host);
884
+ }
885
+
886
+ return pems;
887
+ };
848
888
  const ensureBunDefaultPems = async (primaryDomain) => {
849
- let pems = resolvePemsForServername(primaryDomain);
889
+ let pems = await issueAndReloadPemsForServername(primaryDomain);
850
890
  if (pems) return pems;
851
891
 
852
892
  const certSubject = primaryDomain.startsWith('*.') ? wildcardRoot(primaryDomain) : primaryDomain;
853
893
  log.warn(`⚠️ Bun runtime detected and cert files missing for ${primaryDomain}; requesting certificate via Greenlock before HTTPS bind`);
854
894
  try {
855
- await greenlock.get({ servername: certSubject });
895
+ await greenlockRuntime.get({ servername: certSubject });
856
896
  } catch (error) {
857
897
  log.error(`❌ Failed to obtain certificate for ${certSubject} under Bun:`, error?.message || error);
858
898
  }
@@ -883,12 +923,12 @@ class Roster {
883
923
  key: defaultPems.key,
884
924
  cert: defaultPems.cert,
885
925
  SNICallback: (servername, callback) => {
886
- try {
887
- const pems = resolvePemsForServername(servername) || defaultPems;
888
- callback(null, tls.createSecureContext({ key: pems.key, cert: pems.cert }));
889
- } catch (error) {
890
- callback(error);
891
- }
926
+ issueAndReloadPemsForServername(servername)
927
+ .then((pems) => {
928
+ const selected = pems || defaultPems;
929
+ callback(null, tls.createSecureContext({ key: selected.key, cert: selected.cert }));
930
+ })
931
+ .catch(callback);
892
932
  }
893
933
  }, dispatcher);
894
934
  log.warn(`⚠️ Bun runtime detected: using file-based TLS with SNI for ${primaryDomain} on port ${portNum}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roster-server",
3
- "version": "2.1.10",
3
+ "version": "2.1.14",
4
4
  "description": "👾 RosterServer - A domain host router to host multiple HTTPS.",
5
5
  "main": "index.js",
6
6
  "scripts": {