@envsync-cloud/deploy-cli 0.8.16 → 0.9.1

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +133 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -148,4 +148,4 @@ bun run src/index.ts plan-topology /etc/envsync/deploy.yaml
148
148
  - `upgrade` and `deploy` reconcile managed versioned artifacts from `release.version`.
149
149
  - Custom image overrides are still preserved for advanced self-host setups.
150
150
  - Enterprise package publication now targets NPM Packages rather than the public npm registry.
151
- - The full deployment guide lives in [SELFHOSTING.md](/Users/bravo68web/Projects/OSS/EnvSync/monorepo/SELFHOSTING.md).
151
+ - The full deployment guide lives in [SELFHOSTING.md](../../SELFHOSTING.md).
package/dist/index.js CHANGED
@@ -4117,6 +4117,11 @@ var deployConfigSchema = external_exports.object({
4117
4117
  frontend: external_exports.object({
4118
4118
  dashboard_variant: external_exports.enum(["oss", "enterprise"]).optional(),
4119
4119
  include_manage_subtree: external_exports.boolean().optional()
4120
+ }).default({}),
4121
+ vpn: external_exports.object({
4122
+ provider: external_exports.enum(["netbird", "none"]).default("none"),
4123
+ internal_domain: external_exports.string().default("envsync.local"),
4124
+ nb_setup_key: external_exports.string().default("")
4120
4125
  }).default({})
4121
4126
  });
4122
4127
  function readDeployConfigFile(filePath) {
@@ -4475,7 +4480,9 @@ function buildRuntimeEnv2(config, generated) {
4475
4480
  OTEL_SERVICE_NAME: "envsync-api",
4476
4481
  OTEL_SDK_DISABLED: "false",
4477
4482
  CLICKSTACK_URL: publicHttpsUrl(config, hosts.obs),
4478
- KEYCLOAK_IMAGE_TAG: keycloakImageTag(config.images.keycloak)
4483
+ KEYCLOAK_IMAGE_TAG: keycloakImageTag(config.images.keycloak),
4484
+ // Is this too hacky? We go Shawn way.
4485
+ ...config.vpn?.provider && config.vpn.provider !== "none" && config.vpn.nb_setup_key ? { NB_SETUP_KEY: config.vpn.nb_setup_key } : {}
4479
4486
  };
4480
4487
  }
4481
4488
  function renderEnvFile(env) {
@@ -4789,6 +4796,104 @@ function renderNetutilsService(config) {
4789
4796
  ${ports}
4790
4797
  networks: [envsync]`;
4791
4798
  }
4799
+ var VPN_SERVICE_RENDERERS = {
4800
+ none: () => null,
4801
+ netbird: renderNetbirdService
4802
+ };
4803
+ function renderNetbirdService(config, paths, runtimeEnv) {
4804
+ const nbSetupKey = runtimeEnv.NB_SETUP_KEY ?? "";
4805
+ return {
4806
+ serviceBlock: `
4807
+ netbird_nginx:
4808
+ image: ghcr.io/envsync-cloud/netbird-nginx
4809
+ cap_add:
4810
+ - NET_ADMIN
4811
+ - SYS_ADMIN
4812
+ - SYS_RESOURCE
4813
+ networks: [envsync]
4814
+ environment:
4815
+ ${renderEnvList({ NB_SETUP_KEY: nbSetupKey })}
4816
+ volumes:
4817
+ - netbird_client:/var/lib/netbird
4818
+ - ${paths.nginxVpnConf}:/etc/nginx/nginx.conf:ro`,
4819
+ // Adding comment for readability, extra volume below. We gotta do something about too many ` bhaiya.
4820
+ extraVolumes: ["netbird_client"]
4821
+ };
4822
+ }
4823
+ function renderVpnService(config, paths, runtimeEnv) {
4824
+ const provider = config.vpn?.provider ?? "none";
4825
+ const renderer = VPN_SERVICE_RENDERERS[provider];
4826
+ if (!renderer) return null;
4827
+ return renderer(config, paths, runtimeEnv);
4828
+ }
4829
+ function renderNginxVpnConf(config) {
4830
+ const domain = config.vpn?.internal_domain ?? "envsync.local";
4831
+ return `events {}
4832
+
4833
+ stream {
4834
+ server {
4835
+ listen 5432;
4836
+ proxy_pass postgres:5432;
4837
+ }
4838
+ server {
4839
+ listen 6379;
4840
+ proxy_pass redis:6379;
4841
+ }
4842
+ server {
4843
+ listen 50051;
4844
+ proxy_pass minikms:50051;
4845
+ }
4846
+ server {
4847
+ listen 5544;
4848
+ proxy_pass minikms_db:5432;
4849
+ }
4850
+ server {
4851
+ listen 8091;
4852
+ proxy_pass openfga:8091;
4853
+ }
4854
+ }
4855
+
4856
+ http {
4857
+ server {
4858
+ listen 80;
4859
+ server_name keycloak.${domain};
4860
+ location / {
4861
+ proxy_pass http://keycloak:8080/;
4862
+ proxy_set_header Host $host;
4863
+ proxy_set_header X-Real-IP $remote_addr;
4864
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
4865
+ }
4866
+ }
4867
+ server {
4868
+ listen 80;
4869
+ server_name openfga.${domain};
4870
+ location / {
4871
+ proxy_pass http://openfga:8090/;
4872
+ proxy_set_header Host $host;
4873
+ proxy_set_header X-Real-IP $remote_addr;
4874
+ }
4875
+ }
4876
+ server {
4877
+ listen 80;
4878
+ server_name clickstack.${domain};
4879
+ location / {
4880
+ proxy_pass http://clickstack:8080/;
4881
+ proxy_set_header Host $host;
4882
+ proxy_set_header X-Real-IP $remote_addr;
4883
+ }
4884
+ }
4885
+ server {
4886
+ listen 80;
4887
+ server_name rustfs.${domain};
4888
+ location / {
4889
+ proxy_pass http://rustfs:9001/;
4890
+ proxy_set_header Host $host;
4891
+ proxy_set_header X-Real-IP $remote_addr;
4892
+ }
4893
+ }
4894
+ }
4895
+ `;
4896
+ }
4792
4897
  function renderOtelAgentConfig(config) {
4793
4898
  return [
4794
4899
  "receivers:",
@@ -4846,6 +4951,7 @@ function renderStack(config, runtimeEnv, generated, mode, paths) {
4846
4951
  const s3ConsoleRouterName = `${stackName}-s3-console-router`;
4847
4952
  const s3ConsoleServiceName = `${stackName}-s3-console-service`;
4848
4953
  const netutilsService = renderNetutilsService(config);
4954
+ const vpnResult = renderVpnService(config, paths, runtimeEnv);
4849
4955
  const apiEnvironment = {
4850
4956
  ...runtimeEnv,
4851
4957
  OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-agent:4318",
@@ -5113,7 +5219,7 @@ ${renderEnvList({
5113
5219
  ${apiLicenseVolume}
5114
5220
  networks: [envsync]
5115
5221
  deploy:
5116
- replicas: ${slotHasApiDeployment(deployment.slots.green) ? 1 : 0}` : ""}${netutilsService}
5222
+ replicas: ${slotHasApiDeployment(deployment.slots.green) ? 1 : 0}` : ""}${netutilsService}${vpnResult?.serviceBlock ?? ""}
5117
5223
 
5118
5224
  networks:
5119
5225
  envsync:
@@ -5130,6 +5236,8 @@ volumes:
5130
5236
  clickstack_data:
5131
5237
  clickstack_ch_data:
5132
5238
  clickstack_ch_logs:
5239
+ ${vpnResult?.extraVolumes.map((v) => `
5240
+ ${v}:`).join("") ?? ""}
5133
5241
 
5134
5242
  configs:
5135
5243
  keycloak_realm:
@@ -5231,6 +5339,7 @@ var KEYCLOAK_REALM_FILE = path3.join(DEPLOY_ROOT, "keycloak-realm.envsync.json")
5231
5339
  var NGINX_WEB_CONF = path3.join(DEPLOY_ROOT, "nginx-web.conf");
5232
5340
  var NGINX_LANDING_CONF = path3.join(DEPLOY_ROOT, "nginx-landing.conf");
5233
5341
  var NGINX_API_MAINTENANCE_CONF = path3.join(DEPLOY_ROOT, "nginx-api-maintenance.conf");
5342
+ var NGINX_VPN_CONF = path3.join(DEPLOY_ROOT, "nginx-vpn.conf");
5234
5343
  var OTEL_AGENT_CONF = path3.join(DEPLOY_ROOT, "otel-agent.yaml");
5235
5344
  var CLICKSTACK_CLICKHOUSE_CONF = path3.join(DEPLOY_ROOT, "clickhouse-listen.xml");
5236
5345
  var INTERNAL_CONFIG_JSON = path3.join(DEPLOY_ROOT, "config.json");
@@ -5248,7 +5357,8 @@ var DEPLOY_RENDER_PATHS = {
5248
5357
  otelAgentConf: OTEL_AGENT_CONF,
5249
5358
  nginxLandingConf: NGINX_LANDING_CONF,
5250
5359
  nginxWebConf: NGINX_WEB_CONF,
5251
- nginxApiMaintenanceConf: NGINX_API_MAINTENANCE_CONF
5360
+ nginxApiMaintenanceConf: NGINX_API_MAINTENANCE_CONF,
5361
+ nginxVpnConf: NGINX_VPN_CONF
5252
5362
  };
5253
5363
  var REMOVE_TARGETS = [
5254
5364
  DEPLOY_ROOT,
@@ -6137,6 +6247,11 @@ function normalizeConfig(raw) {
6137
6247
  keep_failed_upgrade_db_snapshot: raw.upgrade?.keep_failed_upgrade_db_snapshot ?? true
6138
6248
  },
6139
6249
  netutils: normalizeNetutilsForwards(raw.netutils?.forwards, stackName, raw.netutils?.enabled ?? false),
6250
+ vpn: {
6251
+ provider: raw.vpn?.provider ?? "none",
6252
+ internal_domain: raw.vpn?.internal_domain ?? "envsync.local",
6253
+ nb_setup_key: raw.vpn?.nb_setup_key ?? ""
6254
+ },
6140
6255
  license: raw.license ? {
6141
6256
  server_url: raw.license.server_url,
6142
6257
  key: raw.license.key,
@@ -6470,6 +6585,9 @@ function writeDeployArtifacts(config, generated) {
6470
6585
  writeFileMaybe(NGINX_API_MAINTENANCE_CONF, renderApiMaintenanceConf());
6471
6586
  writeFileMaybe(OTEL_AGENT_CONF, renderOtelAgentConfig(config));
6472
6587
  writeFileMaybe(CLICKSTACK_CLICKHOUSE_CONF, renderClickstackClickHouseConfig());
6588
+ if (config.vpn?.provider && config.vpn.provider !== "none") {
6589
+ writeFileMaybe(NGINX_VPN_CONF, renderNginxVpnConf(config));
6590
+ }
6473
6591
  logSuccess(currentOptions.dryRun ? "Deploy artifacts previewed" : "Deploy artifacts written");
6474
6592
  }
6475
6593
  function saveDesiredConfig(config) {
@@ -7585,6 +7703,13 @@ async function cmdSetup() {
7585
7703
  }
7586
7704
  }
7587
7705
  const licenseServerUrl = await ask("Enterprise license server URL", DEFAULT_ENTERPRISE_LICENSE_SERVER_URL);
7706
+ const vpnProvider = (await ask("VPN provider for internal service access (netbird/none)", "none")).toLowerCase();
7707
+ let vpnInternalDomain = "envsync.local";
7708
+ let vpnNbSetupKey = "";
7709
+ if (vpnProvider !== "none") {
7710
+ vpnInternalDomain = await ask("Internal root domain", "envsync.local");
7711
+ vpnNbSetupKey = await ask("Netbird setup key", "");
7712
+ }
7588
7713
  const licenseKey = licenseServerUrl ? await ask("Enterprise license key", "") : "";
7589
7714
  const certificateBundleFile = licenseServerUrl ? "" : await ask("Enterprise certificate bundle file (optional)", "");
7590
7715
  const installFingerprint = deterministicInstallFingerprint(rootDomain, "envsync");
@@ -7664,6 +7789,11 @@ async function cmdSetup() {
7664
7789
  netutils: {
7665
7790
  enabled: netutilsEnabled,
7666
7791
  forwards: netutilsForwards
7792
+ },
7793
+ vpn: {
7794
+ provider: vpnProvider,
7795
+ internal_domain: vpnInternalDomain,
7796
+ nb_setup_key: vpnNbSetupKey
7667
7797
  }
7668
7798
  };
7669
7799
  saveDesiredConfig(config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@envsync-cloud/deploy-cli",
3
- "version": "0.8.16",
3
+ "version": "0.9.1",
4
4
  "description": "CLI for self-hosted EnvSync deployment on Docker Swarm",
5
5
  "type": "module",
6
6
  "bin": {