@envsync-cloud/deploy-cli 0.8.15 → 0.9.0
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.
- package/README.md +1 -1
- package/dist/index.js +251 -10
- 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](
|
|
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:
|
|
@@ -5181,6 +5289,30 @@ function validateStaticBundle(kind, targetDir) {
|
|
|
5181
5289
|
}
|
|
5182
5290
|
|
|
5183
5291
|
// src/index.ts
|
|
5292
|
+
var NETUTILS_EXPOSE_ALL_START_PORT = 15e3;
|
|
5293
|
+
var NETUTILS_EXPOSE_ALL_PORTS = [
|
|
5294
|
+
{ service: "postgres", service_port: 5432, protocol: "tcp" },
|
|
5295
|
+
{ service: "envsync_api_blue", service_port: 4e3, protocol: "tcp" },
|
|
5296
|
+
{ service: "envsync_api_green", service_port: 4e3, protocol: "tcp" },
|
|
5297
|
+
{ service: "envsync-management-api", service_port: 4001, protocol: "tcp" },
|
|
5298
|
+
{ service: "keycloak", service_port: 8080, protocol: "tcp" },
|
|
5299
|
+
{ service: "openfga", service_port: 8090, protocol: "tcp" },
|
|
5300
|
+
{ service: "minikms", service_port: 50051, protocol: "tcp" },
|
|
5301
|
+
{ service: "keycloak_db", service_port: 5432, protocol: "tcp" },
|
|
5302
|
+
{ service: "openfga_db", service_port: 5432, protocol: "tcp" },
|
|
5303
|
+
{ service: "minikms_db", service_port: 5432, protocol: "tcp" },
|
|
5304
|
+
{ service: "redis", service_port: 6379, protocol: "tcp" },
|
|
5305
|
+
{ service: "rustfs", service_port: 9e3, protocol: "tcp" },
|
|
5306
|
+
{ service: "rustfs", service_port: 9001, protocol: "tcp" },
|
|
5307
|
+
{ service: "clickstack", service_port: 8080, protocol: "tcp" },
|
|
5308
|
+
{ service: "otel-agent", service_port: 4317, protocol: "tcp" },
|
|
5309
|
+
{ service: "otel-agent", service_port: 4318, protocol: "tcp" },
|
|
5310
|
+
{ service: "traefik", service_port: 80, protocol: "tcp" },
|
|
5311
|
+
{ service: "traefik", service_port: 443, protocol: "tcp" },
|
|
5312
|
+
{ service: "web_nginx", service_port: 80, protocol: "tcp" },
|
|
5313
|
+
{ service: "landing_nginx", service_port: 80, protocol: "tcp" },
|
|
5314
|
+
{ service: "api_maintenance", service_port: 80, protocol: "tcp" }
|
|
5315
|
+
];
|
|
5184
5316
|
var HOST_ROOT = process.env.ENVSYNC_HOST_ROOT ?? "/opt/envsync";
|
|
5185
5317
|
var ETC_ROOT = process.env.ENVSYNC_ETC_ROOT ?? "/etc/envsync";
|
|
5186
5318
|
var TRAEFIK_STATE_ROOT = process.env.ENVSYNC_TRAEFIK_STATE_ROOT ?? "/var/lib/envsync/traefik";
|
|
@@ -5207,6 +5339,7 @@ var KEYCLOAK_REALM_FILE = path3.join(DEPLOY_ROOT, "keycloak-realm.envsync.json")
|
|
|
5207
5339
|
var NGINX_WEB_CONF = path3.join(DEPLOY_ROOT, "nginx-web.conf");
|
|
5208
5340
|
var NGINX_LANDING_CONF = path3.join(DEPLOY_ROOT, "nginx-landing.conf");
|
|
5209
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");
|
|
5210
5343
|
var OTEL_AGENT_CONF = path3.join(DEPLOY_ROOT, "otel-agent.yaml");
|
|
5211
5344
|
var CLICKSTACK_CLICKHOUSE_CONF = path3.join(DEPLOY_ROOT, "clickhouse-listen.xml");
|
|
5212
5345
|
var INTERNAL_CONFIG_JSON = path3.join(DEPLOY_ROOT, "config.json");
|
|
@@ -5224,7 +5357,8 @@ var DEPLOY_RENDER_PATHS = {
|
|
|
5224
5357
|
otelAgentConf: OTEL_AGENT_CONF,
|
|
5225
5358
|
nginxLandingConf: NGINX_LANDING_CONF,
|
|
5226
5359
|
nginxWebConf: NGINX_WEB_CONF,
|
|
5227
|
-
nginxApiMaintenanceConf: NGINX_API_MAINTENANCE_CONF
|
|
5360
|
+
nginxApiMaintenanceConf: NGINX_API_MAINTENANCE_CONF,
|
|
5361
|
+
nginxVpnConf: NGINX_VPN_CONF
|
|
5228
5362
|
};
|
|
5229
5363
|
var REMOVE_TARGETS = [
|
|
5230
5364
|
DEPLOY_ROOT,
|
|
@@ -5386,6 +5520,69 @@ ${stderr}` : ""}`);
|
|
|
5386
5520
|
}
|
|
5387
5521
|
return (result.stdout ?? "").toString().trim();
|
|
5388
5522
|
}
|
|
5523
|
+
function chunkByMax(items, max) {
|
|
5524
|
+
if (items.length === 0) return [];
|
|
5525
|
+
const chunks = [];
|
|
5526
|
+
for (let i = 0; i < items.length; i += max) {
|
|
5527
|
+
chunks.push(items.slice(i, i + max));
|
|
5528
|
+
}
|
|
5529
|
+
return chunks;
|
|
5530
|
+
}
|
|
5531
|
+
function formatPortRangesForIptables(ports) {
|
|
5532
|
+
const sortedPorts = Array.from(new Set(ports)).map((port) => parseInt(String(port), 10)).filter((port) => Number.isInteger(port) && port >= 1 && port <= 65535).sort((a, b) => a - b);
|
|
5533
|
+
if (sortedPorts.length === 0) return [];
|
|
5534
|
+
const ranges = [];
|
|
5535
|
+
let rangeStart = sortedPorts[0];
|
|
5536
|
+
let previous = sortedPorts[0];
|
|
5537
|
+
for (let i = 1; i < sortedPorts.length; i++) {
|
|
5538
|
+
const current = sortedPorts[i];
|
|
5539
|
+
if (current === previous + 1) {
|
|
5540
|
+
previous = current;
|
|
5541
|
+
continue;
|
|
5542
|
+
}
|
|
5543
|
+
ranges.push(rangeStart === previous ? `${rangeStart}` : `${rangeStart}:${previous}`);
|
|
5544
|
+
rangeStart = current;
|
|
5545
|
+
previous = current;
|
|
5546
|
+
}
|
|
5547
|
+
ranges.push(rangeStart === previous ? `${rangeStart}` : `${rangeStart}:${previous}`);
|
|
5548
|
+
return ranges;
|
|
5549
|
+
}
|
|
5550
|
+
function formatNetutilsFirewallRules(config) {
|
|
5551
|
+
if (!config?.netutils?.enabled || !Array.isArray(config.netutils.forwards) || config.netutils.forwards.length === 0) {
|
|
5552
|
+
return [];
|
|
5553
|
+
}
|
|
5554
|
+
const tcpPorts = config.netutils.forwards.filter((item) => item.protocol === "tcp").map((item) => item.host_port);
|
|
5555
|
+
const udpPorts = config.netutils.forwards.filter((item) => item.protocol === "udp").map((item) => item.host_port);
|
|
5556
|
+
const tcpRanges = formatPortRangesForIptables(tcpPorts);
|
|
5557
|
+
const udpRanges = formatPortRangesForIptables(udpPorts);
|
|
5558
|
+
if (tcpRanges.length === 0 && udpRanges.length === 0) return [];
|
|
5559
|
+
const lines = [];
|
|
5560
|
+
const addRules = (protocol, ranges) => {
|
|
5561
|
+
for (const chunk of chunkByMax(ranges, 15)) {
|
|
5562
|
+
const portSpec = chunk.join(",");
|
|
5563
|
+
lines.push(
|
|
5564
|
+
`PostUp = iptables -I DOCKER-USER -i envsync-wg -p ${protocol} -m multiport --dports ${portSpec} -j ACCEPT`
|
|
5565
|
+
);
|
|
5566
|
+
lines.push(`PostUp = iptables -A DOCKER-USER -p ${protocol} -m multiport --dports ${portSpec} -j DROP`);
|
|
5567
|
+
lines.push(
|
|
5568
|
+
`PostDown = iptables -D DOCKER-USER -p ${protocol} -m multiport --dports ${portSpec} -j DROP`
|
|
5569
|
+
);
|
|
5570
|
+
lines.push(
|
|
5571
|
+
`PostDown = iptables -D DOCKER-USER -i envsync-wg -p ${protocol} -m multiport --dports ${portSpec} -j ACCEPT`
|
|
5572
|
+
);
|
|
5573
|
+
}
|
|
5574
|
+
};
|
|
5575
|
+
addRules("tcp", tcpRanges);
|
|
5576
|
+
addRules("udp", udpRanges);
|
|
5577
|
+
return lines;
|
|
5578
|
+
}
|
|
5579
|
+
function tryLoadOptionalConfig() {
|
|
5580
|
+
try {
|
|
5581
|
+
return loadConfig();
|
|
5582
|
+
} catch {
|
|
5583
|
+
return null;
|
|
5584
|
+
}
|
|
5585
|
+
}
|
|
5389
5586
|
function parseJsonOrDefault(value, fallback) {
|
|
5390
5587
|
try {
|
|
5391
5588
|
return JSON.parse(value);
|
|
@@ -5510,6 +5707,15 @@ function parseNetutilsForwardsFromInput(raw, stackName) {
|
|
|
5510
5707
|
});
|
|
5511
5708
|
return normalizeNetutilsForwards(candidates, stackName, true).forwards;
|
|
5512
5709
|
}
|
|
5710
|
+
function buildNetutilsExposeAllForwards(stackName) {
|
|
5711
|
+
const candidates = NETUTILS_EXPOSE_ALL_PORTS.map((forward, index) => ({
|
|
5712
|
+
service: forward.service,
|
|
5713
|
+
service_port: forward.service_port,
|
|
5714
|
+
host_port: NETUTILS_EXPOSE_ALL_START_PORT + index,
|
|
5715
|
+
protocol: forward.protocol
|
|
5716
|
+
}));
|
|
5717
|
+
return normalizeNetutilsForwards(candidates, stackName, true).forwards;
|
|
5718
|
+
}
|
|
5513
5719
|
function normalizeNetutilsProtocol(raw) {
|
|
5514
5720
|
if (typeof raw === "string") {
|
|
5515
5721
|
const protocol = raw.toLowerCase();
|
|
@@ -5635,6 +5841,8 @@ function wireguardPeerAllowedIp(state) {
|
|
|
5635
5841
|
throw new Error("WireGuard client IP pool exhausted in subnet 10.66.0.0/24.");
|
|
5636
5842
|
}
|
|
5637
5843
|
function writeWireguardConfig(state) {
|
|
5844
|
+
const config = tryLoadOptionalConfig();
|
|
5845
|
+
const netutilsFirewallRules = formatNetutilsFirewallRules(config);
|
|
5638
5846
|
const peersSection = state.peers.map((peer) => `
|
|
5639
5847
|
[Peer]
|
|
5640
5848
|
PublicKey = ${peer.public_key}
|
|
@@ -5647,6 +5855,7 @@ PostUp = iptables -A FORWARD -i envsync-wg -j ACCEPT
|
|
|
5647
5855
|
PostDown = iptables -D FORWARD -i envsync-wg -j ACCEPT
|
|
5648
5856
|
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
|
5649
5857
|
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
|
|
5858
|
+
${netutilsFirewallRules.join("\n")}
|
|
5650
5859
|
${peersSection}
|
|
5651
5860
|
`;
|
|
5652
5861
|
writeFileMaybe(WIREGUARD_CONFIG_FILE, content);
|
|
@@ -6038,6 +6247,11 @@ function normalizeConfig(raw) {
|
|
|
6038
6247
|
keep_failed_upgrade_db_snapshot: raw.upgrade?.keep_failed_upgrade_db_snapshot ?? true
|
|
6039
6248
|
},
|
|
6040
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
|
+
},
|
|
6041
6255
|
license: raw.license ? {
|
|
6042
6256
|
server_url: raw.license.server_url,
|
|
6043
6257
|
key: raw.license.key,
|
|
@@ -6371,6 +6585,9 @@ function writeDeployArtifacts(config, generated) {
|
|
|
6371
6585
|
writeFileMaybe(NGINX_API_MAINTENANCE_CONF, renderApiMaintenanceConf());
|
|
6372
6586
|
writeFileMaybe(OTEL_AGENT_CONF, renderOtelAgentConfig(config));
|
|
6373
6587
|
writeFileMaybe(CLICKSTACK_CLICKHOUSE_CONF, renderClickstackClickHouseConfig());
|
|
6588
|
+
if (config.vpn?.provider && config.vpn.provider !== "none") {
|
|
6589
|
+
writeFileMaybe(NGINX_VPN_CONF, renderNginxVpnConf(config));
|
|
6590
|
+
}
|
|
6374
6591
|
logSuccess(currentOptions.dryRun ? "Deploy artifacts previewed" : "Deploy artifacts written");
|
|
6375
6592
|
}
|
|
6376
6593
|
function saveDesiredConfig(config) {
|
|
@@ -7466,14 +7683,33 @@ async function cmdSetup() {
|
|
|
7466
7683
|
const publicObs = await ask("Expose obs.<domain> publicly (true/false)", "true") === "true";
|
|
7467
7684
|
const mailpitEnabled = await ask("Enable mailpit (true/false)", "false") === "true";
|
|
7468
7685
|
const netutilsEnabled = await ask("Enable WireGuard jump host access (true/false)", "false") === "true";
|
|
7469
|
-
const
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7686
|
+
const netutilsExposeAll = netutilsEnabled ? await ask("Expose all EnvSync service ports over WireGuard (true/false)", "false") === "true" : false;
|
|
7687
|
+
let netutilsForwards = [];
|
|
7688
|
+
if (netutilsEnabled) {
|
|
7689
|
+
if (netutilsExposeAll) {
|
|
7690
|
+
netutilsForwards = buildNetutilsExposeAllForwards("envsync");
|
|
7691
|
+
logInfo("Netutils exposes all preset (auto-generated):");
|
|
7692
|
+
for (const forward of netutilsForwards) {
|
|
7693
|
+
console.log(` ${forward.service}:${forward.service_port} -> ${forward.host_port} (${forward.protocol})`);
|
|
7694
|
+
}
|
|
7695
|
+
} else {
|
|
7696
|
+
netutilsForwards = parseNetutilsForwardsFromInput(
|
|
7697
|
+
await ask(
|
|
7698
|
+
"Netutils forwards (format service:service_port:host_port[:protocol], comma-separated)",
|
|
7699
|
+
"postgres:5432:15432:tcp,keycloak:8080:18080:tcp"
|
|
7700
|
+
),
|
|
7701
|
+
"envsync"
|
|
7702
|
+
);
|
|
7703
|
+
}
|
|
7704
|
+
}
|
|
7476
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
|
+
}
|
|
7477
7713
|
const licenseKey = licenseServerUrl ? await ask("Enterprise license key", "") : "";
|
|
7478
7714
|
const certificateBundleFile = licenseServerUrl ? "" : await ask("Enterprise certificate bundle file (optional)", "");
|
|
7479
7715
|
const installFingerprint = deterministicInstallFingerprint(rootDomain, "envsync");
|
|
@@ -7553,6 +7789,11 @@ async function cmdSetup() {
|
|
|
7553
7789
|
netutils: {
|
|
7554
7790
|
enabled: netutilsEnabled,
|
|
7555
7791
|
forwards: netutilsForwards
|
|
7792
|
+
},
|
|
7793
|
+
vpn: {
|
|
7794
|
+
provider: vpnProvider,
|
|
7795
|
+
internal_domain: vpnInternalDomain,
|
|
7796
|
+
nb_setup_key: vpnNbSetupKey
|
|
7556
7797
|
}
|
|
7557
7798
|
};
|
|
7558
7799
|
saveDesiredConfig(config);
|