-
Notifications
You must be signed in to change notification settings - Fork 134
feat(coder/modules/boundary): add boundary module #840
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| --- | ||
| display_name: Boundary | ||
| description: Configures boundary for network isolation in Coder workspaces | ||
| icon: ../../../../.icons/coder.svg | ||
| verified: true | ||
| tags: [boundary, coder, AI, agents] | ||
| --- | ||
|
|
||
| # Boundary | ||
|
|
||
| Configures boundary to enable network isolation for workspace processes in Coder. | ||
|
|
||
| ```tf | ||
| module "boundary" { | ||
| count = data.coder_workspace.me.start_count | ||
| source = "registry.coder.com/coder/boundary/coder" | ||
| version = "1.0.0" | ||
| agent_id = coder_agent.main.id | ||
| } | ||
| ``` | ||
|
|
||
| ## Examples | ||
|
|
||
| ### Compile from source | ||
|
|
||
| ```tf | ||
| module "boundary" { | ||
| count = data.coder_workspace.me.start_count | ||
| source = "registry.coder.com/coder/boundary/coder" | ||
| version = "1.0.0" | ||
| agent_id = coder_agent.main.id | ||
| compile_boundary_from_source = true | ||
| boundary_version = "main" | ||
| } | ||
| ``` | ||
|
|
||
| ### Use release binary | ||
|
|
||
| ```tf | ||
| module "boundary" { | ||
| count = data.coder_workspace.me.start_count | ||
| source = "registry.coder.com/coder/boundary/coder" | ||
| version = "1.0.0" | ||
| agent_id = coder_agent.main.id | ||
| use_boundary_directly = true | ||
| boundary_version = "latest" | ||
| } | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # Test for boundary module | ||
|
|
||
| run "plan_with_required_vars" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent-id" | ||
| } | ||
|
|
||
| # Verify the coder_script resource is created with correct agent_id | ||
| assert { | ||
| condition = coder_script.boundary_script.agent_id == "test-agent-id" | ||
| error_message = "boundary_script agent_id should match the input variable" | ||
| } | ||
|
|
||
| assert { | ||
| condition = coder_script.boundary_script.display_name == "Boundary Installation Script" | ||
| error_message = "display_name should be 'Boundary Installation Script'" | ||
| } | ||
| } | ||
|
|
||
| run "plan_with_compile_from_source" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent-id" | ||
| compile_boundary_from_source = true | ||
| boundary_version = "main" | ||
| } | ||
|
|
||
| assert { | ||
| condition = coder_script.boundary_script.agent_id == "test-agent-id" | ||
| error_message = "boundary_script agent_id should match the input variable" | ||
| } | ||
| } | ||
|
|
||
| run "plan_with_use_directly" { | ||
| command = plan | ||
|
|
||
| variables { | ||
| agent_id = "test-agent-id" | ||
| use_boundary_directly = true | ||
| boundary_version = "latest" | ||
| } | ||
|
|
||
| assert { | ||
| condition = coder_script.boundary_script.agent_id == "test-agent-id" | ||
| error_message = "boundary_script agent_id should match the input variable" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| terraform { | ||
| required_version = ">= 1.0" | ||
|
|
||
| required_providers { | ||
| coder = { | ||
| source = "coder/coder" | ||
| version = ">= 2.5" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| # Add required variables for your modules and remove any unneeded variables | ||
| variable "agent_id" { | ||
| type = string | ||
| description = "The ID of a Coder agent." | ||
| } | ||
|
|
||
| variable "boundary_version" { | ||
| type = string | ||
| description = "Boundary version. When use_boundary_directly is true, a release version should be provided or 'latest' for the latest release. When compile_boundary_from_source is true, a valid git reference should be provided (tag, commit, branch)." | ||
| default = "latest" | ||
| } | ||
|
|
||
| variable "compile_boundary_from_source" { | ||
| type = bool | ||
| description = "Whether to compile boundary from source instead of using the official install script." | ||
| default = false | ||
| } | ||
|
|
||
| variable "use_boundary_directly" { | ||
| type = bool | ||
| description = "Whether to use boundary binary directly instead of `coder boundary` subcommand. When false (default), uses `coder boundary` subcommand. When true, installs and uses boundary binary from release." | ||
| default = false | ||
| } | ||
|
|
||
| locals { | ||
| boundary_script = file("${path.module}/scripts/install.sh") | ||
| module_directory = "$HOME/.coder-modules/coder/boundary" | ||
| boundary_script_destination = "${local.module_directory}/install.sh" | ||
| } | ||
|
|
||
| resource "coder_script" "boundary_script" { | ||
| agent_id = var.agent_id | ||
| display_name = "Boundary Installation Script" | ||
| script = <<-EOT | ||
| #!/bin/bash | ||
| set -o errexit | ||
| set -o pipefail | ||
| mkdir -p "$(dirname "${local.boundary_script_destination}")" | ||
| echo -n '${base64encode(local.boundary_script)}' | base64 -d > "${local.boundary_script_destination}" | ||
| chmod +x "${local.boundary_script_destination}" | ||
|
|
||
| ARG_BOUNDARY_VERSION="${var.boundary_version}" \ | ||
| ARG_COMPILE_BOUNDARY_FROM_SOURCE="${var.compile_boundary_from_source}" \ | ||
| ARG_USE_BOUNDARY_DIRECTLY="${var.use_boundary_directly}" \ | ||
| ARG_MODULE_DIR="${local.module_directory}" \ | ||
| "${local.boundary_script_destination}" | ||
| EOT | ||
35C4n0r marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,102 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #!/bin/bash | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Exports AGENTAPI_BOUNDARY_PREFIX for use by module start scripts. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set -o nounset | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BOUNDARY_VERSION="${ARG_BOUNDARY_VERSION:-latest}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| COMPILE_BOUNDARY_FROM_SOURCE="${ARG_COMPILE_BOUNDARY_FROM_SOURCE:-false}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| USE_BOUNDARY_DIRECTLY="${ARG_USE_BOUNDARY_DIRECTLY:-false}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MODULE_DIR="${ARG_MODULE_DIR:-}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set +o nounset | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
35C4n0r marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| validate_boundary_subcommand() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if hash coder; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if coder boundary --help > /dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Error: 'coder' command found but does not support 'boundary' subcommand. Please enable install_boundary." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
35C4n0r marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Error: 'coder' command not found. boundary cannot be enabled." >&2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Install boundary binary if needed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Uses one of three strategies: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 1. Compile from source (compile_boundary_from_source=true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 2. Install from release (use_boundary_directly=true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 3. Use coder boundary subcommand (default, no installation needed) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| install_boundary() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "${COMPILE_BOUNDARY_FROM_SOURCE}" = "true" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Compiling boundary from source (version: ${BOUNDARY_VERSION})" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Remove existing boundary directory to allow re-running safely | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ -d boundary ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rm -rf boundary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Cloning boundary repository" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| git clone https://github.com/coder/boundary.git | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cd boundary || exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| git checkout "${BOUNDARY_VERSION}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| make build | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sudo cp boundary /usr/local/bin/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sudo chmod +x /usr/local/bin/boundary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cd - || exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+32
to
+48
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Compiling boundary from source (version: ${BOUNDARY_VERSION})" | |
| # Remove existing boundary directory to allow re-running safely | |
| if [[ -d boundary ]]; then | |
| rm -rf boundary | |
| fi | |
| echo "Cloning boundary repository" | |
| git clone https://github.com/coder/boundary.git | |
| cd boundary || exit 1 | |
| git checkout "${BOUNDARY_VERSION}" | |
| make build | |
| sudo cp boundary /usr/local/bin/ | |
| sudo chmod +x /usr/local/bin/boundary | |
| cd - || exit 1 | |
| local build_dir="${MODULE_DIR}/boundary-src" | |
| local original_dir | |
| echo "Compiling boundary from source (version: ${BOUNDARY_VERSION})" | |
| original_dir="$(pwd)" | |
| # Remove existing build directory to allow re-running safely | |
| if [[ -d "${build_dir}" ]]; then | |
| rm -rf "${build_dir}" | |
| fi | |
| echo "Cloning boundary repository" | |
| git clone https://github.com/coder/boundary.git "${build_dir}" | |
| cd "${build_dir}" || exit 1 | |
| git checkout "${BOUNDARY_VERSION}" | |
| make build | |
| sudo cp "${build_dir}/boundary" /usr/local/bin/ | |
| sudo chmod +x /usr/local/bin/boundary | |
| cd "${original_dir}" || exit 1 |
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curl ... | bash executes a remote script from the main branch. Even with --version, this is supply-chain risky and not reproducible. Prefer downloading a version-pinned artifact (or install script from a tag/commit), verifying a checksum/signature, and then executing it.
| curl -fsSL https://raw.githubusercontent.com/coder/boundary/main/install.sh | bash -s -- --version "${BOUNDARY_VERSION}" | |
| if [[ "${BOUNDARY_VERSION}" = "latest" ]]; then | |
| echo "Error: use_boundary_directly requires a version-pinned ARG_BOUNDARY_VERSION, not 'latest'." >&2 | |
| exit 1 | |
| fi | |
| local install_script | |
| install_script="$(mktemp)" | |
| curl -fsSL "https://raw.githubusercontent.com/coder/boundary/${BOUNDARY_VERSION}/install.sh" -o "${install_script}" | |
| bash "${install_script}" --version "${BOUNDARY_VERSION}" | |
| rm -f "${install_script}" |
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setup_boundary relies on MODULE_DIR being set; if it’s empty, paths like ${module_path}/boundary-wrapper.sh become /boundary-wrapper.sh and the script may write into the filesystem root. Add a guard that MODULE_DIR is non-empty (and ideally exists / is writable) before creating wrapper scripts.
Uh oh!
There was an error while loading. Please reload this page.