Skip to content

Add private-network VM install modes (DNS-01, self-signed)#1106

Open
RAVEENSR wants to merge 2 commits into
wso2:mainfrom
RAVEENSR:vm-private-install
Open

Add private-network VM install modes (DNS-01, self-signed)#1106
RAVEENSR wants to merge 2 commits into
wso2:mainfrom
RAVEENSR:vm-private-install

Conversation

@RAVEENSR

@RAVEENSR RAVEENSR commented Jun 18, 2026

Copy link
Copy Markdown
Member

Purpose

Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.

The VM installer has two entry points today — the simple installer (install-vm.sh, sslip.io + Let's Encrypt on :443) and the advanced installer (install-advanced.sh with letsencrypt | byoc | upstream). Both assume the VM is reachable from the public internet. Many companies will not expose the console/API publicly and want Agent Manager reachable only from their private network. The blocker is TLS: public letsencrypt (TLS-ALPN-01) needs the ACME CA to connect inbound to the VM on :443, which a private VM cannot accept.

Related to #1017 (VM standalone install).
Resolves #1081

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Add two TLS modes to the advanced installer so a VM with private ingress and internet egress can run Agent Manager without ever being publicly reachable:

  • letsencrypt-dns (recommended) — public-trusted certificates via the ACME DNS-01 challenge. The CA validates a DNS TXT record and never connects to the VM, so it works behind a firewall. A records may point at the VM's private IP (split-horizon).
  • selfsigned — fully offline: a generated local CA + leaf for teams with neither a public DNS zone nor an internal CA.

byoc (internal-CA cert) and upstream (internal LB) already cover the remaining private variants and are unchanged.

Approach

Describe how you are implementing the solutions.

Both new modes only produce a cert/key on disk and then reuse the existing byoc serving path (Caddyfile rendering, container cert mounts, and validate_cert's SAN/wildcard coverage checks) — so lib-vm.sh is untouched and the serving logic is shared.

  • New deployments/vm/lib-tls.sh: pure helpers (tls_san_list, build_lego_args, render_renewal_units) plus side-effecting issuance (issue_dns01_cert via the dockerized goacme/lego image, generate_selfsigned_ca via openssl, install_renewal_timer).
  • letsencrypt-dns issues a cert covering every service host + the *.<AGENTS_BASE> wildcard, copies it to /opt/amp/certs/, and installs a daily systemd timer (lego renew + caddy reload).
  • selfsigned generates a local CA + leaf and writes the CA to /opt/amp/certs/ca.crt for distribution to client trust stores.
  • validate_config learns the two modes (letsencrypt-dns requires DNS_PROVIDER + ACME_EMAIL; selfsigned requires nothing extra), the --init template documents them, and --dry-run previews the issuance/generation plan without doing it.

User stories

Summary of user stories addressed by this change

As a platform operator at a security-conscious company, I can install Agent Manager on a private-network-only VM with trustworthy TLS — either public-trusted certificates via DNS-01 (no public ingress) or a generated local CA when fully offline.

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

The advanced VM installer now supports private-network-only deployments via two new TLS modes: letsencrypt-dns (public-trusted certificates through the ACME DNS-01 challenge, with automatic renewal) and selfsigned (a generated local CA for fully offline installs).

Documentation

Link(s) to product documentation that addresses the changes of this PR.

Updated documentation/docs/getting-started/on-a-vm.mdx: new "Private network (no public exposure)" section, the two new modes added to the TLS-modes and config-key tables, DNS split-horizon guidance for DNS-01, and troubleshooting entries.

Training

Link to the PR for changes to the training content, if applicable

N/A — no training content impact.

Certification

N/A — no impact on certification exams.

Marketing

N/A — no marketing content for this change.

Automation tests

  • Unit tests

    Code coverage information

Extended deployments/vm/tests/run.sh (SAN list, lego arg builder, renewal-unit rendering, validate_config for both modes, --init template, and --dry-run for both modes) and deployments/vm/tests/preflight.sh (local-CA generation produces a cert whose SANs cover every host + the agent wildcard, verified via validate_cert + openssl). Both suites pass; the changed scripts are shellcheck-clean.

  • Integration tests

    Details about the test cases and coverage

The suites are hermetic (no Docker/cluster). A live DNS-01 issuance against a real zone and a selfsigned browser-trust check on a GCP VM are planned as an out-of-band smoke test, mirroring the earlier VM-install smoke tests (this PR is a draft pending that).

Security checks

  • Followed secure coding standards in http://wso2.com/technical-reports/wso2-secure-engineering-guidelines? yes
  • Ran FindSecurityBugs plugin and verified report? N/A — shell scripts only, no Java.
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets? yes — DNS-provider credentials are supplied by the operator in amp-config.env at install time and the renewal config copy is written 0600; none are committed.

Samples

Provide high-level details about the samples related to this feature

N/A — no new samples. The docs include a DNS-01 (AWS Route 53) walkthrough.

Related PRs

List any other related PRs

Builds on the VM standalone (#1017) and advanced-install work in deployments/vm/.

Migrations (if applicable)

N/A — additive feature; no migration required. Switching TLS_MODE on an existing install only re-renders Caddy and re-issues/regenerates the certificate.

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Unit + preflight suites run locally on macOS (bash 3.2). The installer targets Linux VMs (Ubuntu/Debian, bash 4+); the real-VM smoke test is pending (see Automation tests).

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

Key insight: the ACME DNS-01 challenge validates a DNS TXT record rather than connecting to the host, so it can issue public-trusted (and wildcard) certificates for a server with no public ingress. Used lego (single-binary ACME client, ~150 DNS providers) to keep the stock caddy:2 image and reuse the existing byoc serving path rather than building a custom Caddy image with DNS plugins.

Summary by CodeRabbit

  • New Features

    • Added Let's Encrypt DNS-01 automatic certificate issuance with daily renewal
    • Added self-signed certificate generation mode with local CA support
    • Automatic system kernel optimization during installation for improved stability
  • Improvements

    • Enhanced DNS preflight validation with improved advisory messaging
    • Improved certificate validation with comprehensive SAN inspection
    • Better error reporting for TLS configuration validation
  • Documentation

    • Updated VM deployment guide with clearer TLS configuration and networking instructions
    • Expanded troubleshooting section with certificate validation and DNS diagnostics

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@RAVEENSR, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 38 minutes and 26 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 67cb1ccd-4bb6-44de-a6fd-a7cce4f70516

📥 Commits

Reviewing files that changed from the base of the PR and between 551b969 and 8a943e5.

📒 Files selected for processing (8)
  • deployments/vm/install-advanced.sh
  • deployments/vm/install-vm.sh
  • deployments/vm/lib-advanced.sh
  • deployments/vm/lib-bootstrap.sh
  • deployments/vm/lib-tls.sh
  • deployments/vm/tests/preflight.sh
  • deployments/vm/tests/run.sh
  • documentation/docs/getting-started/on-a-vm.mdx
📝 Walkthrough

Walkthrough

Adds two new TLS modes (letsencrypt-dns via LEGO DNS-01 and selfsigned via local OpenSSL CA) to the advanced VM installer. A new lib-tls.sh library provides SAN computation, certificate generation, DNS-01 issuance, and a systemd daily renewal timer. inotify kernel limits are now enforced in both installers. Config validation, Caddyfile rendering, Caddy container bind-mounts, DNS advisory messaging, and documentation are updated accordingly, with comprehensive new tests.

Changes

New TLS Modes for Advanced VM Installer

Layer / File(s) Summary
inotify kernel limit helpers and bootstrap wiring
deployments/vm/lib-bootstrap.sh, deployments/vm/install-vm.sh, deployments/vm/install-advanced.sh
Adds inotify_bump_target and ensure_inotify_limits to raise fs.inotify sysctl floors and persist them; wires the call into both installer Phase 1 and the advanced install workflow.
lib-tls.sh: SAN list, LEGO arg builder, self-signed CA generation
deployments/vm/lib-tls.sh
New library providing tls_san_list(), build_lego_args(), and generate_selfsigned_ca(); pins LEGO image to goacme/lego:v4.35.2; produces ca.crt, fullchain.pem, and privkey.pem via OpenSSL.
lib-tls.sh: DNS-01 issuance, credential env forwarding, renewal timer
deployments/vm/lib-tls.sh
Adds _lego_cred_env_args(), issue_dns01_cert(), render_renewal_units(), and install_renewal_timer(); runs LEGO in Docker with forwarded provider credentials and installs a systemd daily renewal timer that reloads Caddy.
lib-advanced.sh: letsencrypt-dns config validation and DNS advisory
deployments/vm/lib-advanced.sh
Extends validate_config to accept letsencrypt-dns and require DNS_PROVIDER/ACME_EMAIL; updates allowed-mode error messages; revises DNS advisory text to reference the active TLS_MODE.
install-advanced.sh: TLS mode wiring, Caddyfile, cert mounts, renewal, output
deployments/vm/install-advanced.sh
Sources lib-tls.sh; expands --init template; sets default cert paths; routes byoc/letsencrypt-dns/selfsigned through the byoc Caddy template; broadens cert bind-mount condition; adds cert generation before cluster work; installs renewal timer after Caddy start; expands dry-run and final output messaging.
Tests: lib-tls helpers, dry-run modes, validate_config, renewal units, inotify
deployments/vm/tests/run.sh, deployments/vm/tests/preflight.sh
Adds unit tests for tls_san_list, build_lego_args, --dry-run for both new TLS modes, validate_config for letsencrypt-dns/selfsigned/invalid, render_renewal_units, inotify_bump_target, and generate_selfsigned_ca file/SAN assertions.
Documentation: VM guide updates
documentation/docs/getting-started/on-a-vm.mdx
Updates prerequisites, TLS/ACME mechanics, login/RBAC guidance, private-network TLS mode examples, upstream LB mode, teardown constraints, and troubleshooting bullets.

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant install_advanced as install-advanced.sh
  participant lib_tls as lib-tls.sh
  participant OpenSSL
  participant Docker_LEGO as Docker / LEGO
  participant Caddy
  participant systemd

  Operator->>install_advanced: run --config amp-config.env

  rect rgba(100, 149, 237, 0.5)
    Note over install_advanced: selfsigned mode
    install_advanced->>lib_tls: generate_selfsigned_ca(cert_dir)
    lib_tls->>OpenSSL: generate CA key + cert
    lib_tls->>OpenSSL: generate leaf CSR + sign with SANs
    OpenSSL-->>lib_tls: ca.crt, fullchain.pem, privkey.pem
    lib_tls->>install_advanced: validate_cert → abort on failure
  end

  rect rgba(60, 179, 113, 0.5)
    Note over install_advanced: letsencrypt-dns mode
    install_advanced->>lib_tls: issue_dns01_cert(cert_dir)
    lib_tls->>Docker_LEGO: docker run goacme/lego:v4.35.2 --dns provider run
    Docker_LEGO-->>lib_tls: AMP_HOST_CONSOLE.crt/.key
    lib_tls-->>install_advanced: fullchain.pem, privkey.pem
  end

  install_advanced->>Caddy: start container with cert bind-mount
  Caddy-->>install_advanced: up

  rect rgba(60, 179, 113, 0.5)
    Note over install_advanced: letsencrypt-dns renewal
    install_advanced->>lib_tls: install_renewal_timer(cert_dir, env_file)
    lib_tls->>systemd: write amp-cert-renew.service + .timer
    lib_tls->>systemd: daemon-reload + enable + start
  end

  install_advanced-->>Operator: Access URLs (+ CA import note for selfsigned)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • wso2/agent-manager#1051: Directly modifies install-advanced.sh and lib-advanced.sh with TLS-mode-driven installer logic that the current PR extends with two new modes (letsencrypt-dns and selfsigned).

Suggested reviewers

  • menakaj
  • rasika2012

🐇 Two new TLS paths now bloom,
From LEGO's DNS to a self-signed room.
Inotify floors are raised up neat,
A daily timer keeps certs complete.
The rabbit hops—secure and fleet! 🔐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding two new TLS modes (DNS-01 and self-signed) for private-network VM deployments, which is the core objective of the PR.
Description check ✅ Passed The description comprehensively covers all required template sections including Purpose (with issue link #1081), Goals, Approach, User stories, Release note, Documentation, Automation tests, and Security checks.
Linked Issues check ✅ Passed The PR directly resolves issue #1081 by implementing two new TLS modes (letsencrypt-dns and selfsigned) that enable private-network-only VM deployments without public exposure, exactly as requested in the linked issue.
Out of Scope Changes check ✅ Passed All changes align with the stated objectives: new TLS modes, lib-tls.sh utilities, config validation, documentation updates, and bootstrap improvements (inotify limits) to support private deployments. No unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@RAVEENSR RAVEENSR force-pushed the vm-private-install branch 2 times, most recently from 808e33b to 551b969 Compare June 23, 2026 16:20
@RAVEENSR RAVEENSR marked this pull request as ready for review June 23, 2026 16:21

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
deployments/vm/lib-tls.sh (2)

49-65: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Add serverAuth EKU and reconsider the 10-year leaf validity for the self-signed leaf.

The leaf only carries subjectAltName. Two interop gaps for the selfsigned mode:

  • Missing extendedKeyUsage = serverAuth (and keyUsage). Apple platforms (Safari/macOS/iOS) reject TLS server certs without serverAuth even when the CA is trusted.
  • The default days=3650 leaf exceeds Apple's 398-day maximum validity for TLS leaf certificates, so such clients will reject the cert regardless of trust.

If the target audience is browser/HTTPS clients, consider emitting serverAuth EKU on the leaf and using a shorter leaf validity (long-lived CA, short-lived leaf).

♻️ Proposed extension tweak
   openssl x509 -req -in "${dir}/leaf.csr" -CA "${dir}/ca.crt" -CAkey "${dir}/ca.key" \
     -CAcreateserial -days "$days" \
-    -extfile <(printf 'subjectAltName=%s\n' "$san") \
+    -extfile <(printf 'subjectAltName=%s\nbasicConstraints=CA:FALSE\nkeyUsage=digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth\n' "$san") \
     -out "${dir}/leaf.crt" >/dev/null 2>&1 || die "leaf signing failed"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deployments/vm/lib-tls.sh` around lines 49 - 65, The generate_selfsigned_ca
function's leaf certificate generation is missing critical extensions required
by Apple platforms. The openssl x509 command that creates the leaf certificate
(which currently only includes subjectAltName via the extfile parameter) needs
to be enhanced to also include extendedKeyUsage with serverAuth and appropriate
keyUsage extensions in the same extfile. Additionally, the default leaf validity
of 3650 days exceeds Apple's 398-day maximum limit for TLS certificates, so
consider reducing the leaf certificate validity to a shorter duration (such as
90 or 365 days) while keeping the CA validity long, since the days parameter is
currently being applied uniformly to both. Update the printf command that
generates the extension file content to include the additional required
extensions alongside the existing subjectAltName.

102-134: 🩺 Stability & Availability | 🔵 Trivial

Add validation for docker --env-file format compatibility in amp-config.env.

The template format is docker-compatible (plain KEY=value lines), but users could manually add export prefixes or quoted values during editing. Docker's --env-file parser silently treats these as literal variable names (e.g., export FOO=bar becomes a var named export FOO), causing lego to receive malformed or missing credentials without obvious error. Consider adding a pre-flight check or validation function to ensure the file format matches docker's parser expectations before passing it to the renewal job.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deployments/vm/lib-tls.sh` around lines 102 - 134, The render_renewal_units
function uses the env_file parameter directly in the docker run command without
validating that it conforms to Docker's --env-file format expectations. Create a
validation function that checks the env_file for lines containing export
prefixes or quoted values that Docker's parser will silently treat as literal
variable names, causing credential delivery failures. Call this validation
function before the env_file is passed to the docker run command in the
ExecStart directive to ensure users receive explicit errors rather than silent
credential failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deployments/vm/lib-tls.sh`:
- Around line 82-95: The issue_dns01_cert function only binds the cert_dir
directory into the lego container but does not mount file-based DNS provider
credentials that may be referenced in environment variables such as
GCE_SERVICE_ACCOUNT_FILE. Add logic to detect when credential environment
variables reference file paths and bind-mount those files (or their parent
directories) into the container using additional -v arguments in the docker run
command, similar to how envargs is already being passed. The same fix should
also be applied to the renewal service function at line 118.
- Around line 71-76: The _lego_cred_env_args function uses compgen -e to list
only exported variables, but the load_config function sources configuration
files without using set -a, so credential variables like AWS_ACCESS_KEY_ID and
CF_DNS_API_TOKEN are not exported. Fix this by ensuring variables are exported
when sourcing the configuration file: either modify the load_config function to
wrap the source command with set -a before and set +a after sourcing the config
file, or require that credential variables in amp-config.env use export
statements. Additionally, in the _lego_cred_env_args function, simplify the grep
regex pattern by removing the redundant AWS_REGION$ condition since the AWS_
prefix already matches it.

In `@deployments/vm/tests/run.sh`:
- Line 671: The assertion checking for the renew action uses a broad substring
match that can false-pass when matching text like "renewal" instead of just the
"renew" command token. Replace the current check using `has "$units" ' renew'`
with a more specific assertion that verifies the ExecStart= command line ends
with the "renew" action token rather than doing a simple substring match,
ensuring the lego action is correctly set to renew and not matching partial
words.

In `@documentation/docs/getting-started/on-a-vm.mdx`:
- Line 303: The selfsigned/TLS section header is ambiguous because it describes
a private install that needs outbound internet (line 303) but also mentions
"Fully offline" (line 395), which could be misinterpreted as requiring no
internet access. Reword the section header from its current phrasing to
explicitly state "offline TLS / no external CA" to clarify that "offline" refers
to not requiring an external Certificate Authority, not an air-gapped network
with no internet. Update both the header at line 303 and the related text at
line 395 to use this clearer terminology.

---

Nitpick comments:
In `@deployments/vm/lib-tls.sh`:
- Around line 49-65: The generate_selfsigned_ca function's leaf certificate
generation is missing critical extensions required by Apple platforms. The
openssl x509 command that creates the leaf certificate (which currently only
includes subjectAltName via the extfile parameter) needs to be enhanced to also
include extendedKeyUsage with serverAuth and appropriate keyUsage extensions in
the same extfile. Additionally, the default leaf validity of 3650 days exceeds
Apple's 398-day maximum limit for TLS certificates, so consider reducing the
leaf certificate validity to a shorter duration (such as 90 or 365 days) while
keeping the CA validity long, since the days parameter is currently being
applied uniformly to both. Update the printf command that generates the
extension file content to include the additional required extensions alongside
the existing subjectAltName.
- Around line 102-134: The render_renewal_units function uses the env_file
parameter directly in the docker run command without validating that it conforms
to Docker's --env-file format expectations. Create a validation function that
checks the env_file for lines containing export prefixes or quoted values that
Docker's parser will silently treat as literal variable names, causing
credential delivery failures. Call this validation function before the env_file
is passed to the docker run command in the ExecStart directive to ensure users
receive explicit errors rather than silent credential failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 393f3b00-bb03-4405-87eb-36ff4d76e812

📥 Commits

Reviewing files that changed from the base of the PR and between 4805356 and 551b969.

📒 Files selected for processing (8)
  • deployments/vm/install-advanced.sh
  • deployments/vm/install-vm.sh
  • deployments/vm/lib-advanced.sh
  • deployments/vm/lib-bootstrap.sh
  • deployments/vm/lib-tls.sh
  • deployments/vm/tests/preflight.sh
  • deployments/vm/tests/run.sh
  • documentation/docs/getting-started/on-a-vm.mdx

Comment thread deployments/vm/lib-tls.sh
Comment thread deployments/vm/lib-tls.sh
Comment thread deployments/vm/tests/run.sh Outdated
Comment thread documentation/docs/getting-started/on-a-vm.mdx
RAVEENSR added 2 commits June 23, 2026 22:12
The advanced VM installer only supported public-facing TLS (ACME
HTTP-01/TLS-ALPN-01 and an upstream-terminated mode), none of which
work on a VM with no public ingress. Add two modes for private
networks with internet egress, both of which only produce a cert and
then reuse the existing byoc serving path (Caddy cert mounts,
validate_cert) so lib-vm.sh is untouched:

- letsencrypt-dns: public-trusted certs via ACME DNS-01 (the CA reads
  a TXT record and never connects to the VM, so split-horizon A
  records are fine). Issued by a dockerized lego with a daily systemd
  renewal timer.
- selfsigned: an offline local CA + leaf for fully air-gapped hosts.

load_config exports the sourced config so DNS-provider credentials
(CF_*, AWS_*, GCE_*, ...) actually reach the dockerized lego, which
forwards only exported vars via docker run -e; without this,
token-based providers would silently get no credentials.

Also folds in robustness fixes found during real-VM testing: the
advisory DNS pre-flight no longer reports success when no hostname
resolves; lego is pinned to v4.x (v5 dropped the global flags the
installer passes, breaking issuance); and bootstrap raises
fs.inotify.max_user_{instances,watches} so a clean k3d install does
not exhaust the default ceiling ("Too many open files").

All three TLS modes verified end-to-end on real GCP VMs.
Restructure the Advanced VM install docs around the network the VM
lives on, so a reader follows one self-contained path instead of
cross-referencing. Split into per-network tabs (public vs private),
document the letsencrypt-dns and selfsigned modes inline, and update
the intro to frame private-network installs as a first-class option.
@RAVEENSR RAVEENSR force-pushed the vm-private-install branch from 551b969 to 8a943e5 Compare June 23, 2026 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide option to run agent manager in a VM without exposing console like components to the public

1 participant