From 31c802f605db7b7047832b790b2692c311cdd9b4 Mon Sep 17 00:00:00 2001 From: aybanda Date: Wed, 16 Jul 2025 12:55:11 +0530 Subject: [PATCH 01/11] feat: add Oracle Cloud Infrastructure (OCI) template --- .icons/oci.svg | 13 + .../aybanda/templates/oci-linux/README.md | 163 ++++++ .../cloud-init/cloud-config.yaml.tftpl | 39 ++ .../oci-linux/cloud-init/userdata.sh.tftpl | 48 ++ registry/aybanda/templates/oci-linux/main.tf | 491 ++++++++++++++++++ 5 files changed, 754 insertions(+) create mode 100644 .icons/oci.svg create mode 100644 registry/aybanda/templates/oci-linux/README.md create mode 100644 registry/aybanda/templates/oci-linux/cloud-init/cloud-config.yaml.tftpl create mode 100644 registry/aybanda/templates/oci-linux/cloud-init/userdata.sh.tftpl create mode 100644 registry/aybanda/templates/oci-linux/main.tf diff --git a/.icons/oci.svg b/.icons/oci.svg new file mode 100644 index 000000000..3244c9748 --- /dev/null +++ b/.icons/oci.svg @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/registry/aybanda/templates/oci-linux/README.md b/registry/aybanda/templates/oci-linux/README.md new file mode 100644 index 000000000..466d0309b --- /dev/null +++ b/registry/aybanda/templates/oci-linux/README.md @@ -0,0 +1,163 @@ +--- +display_name: Oracle Cloud Infrastructure (Linux) +description: Provision Oracle Cloud Infrastructure VMs as Coder workspaces +icon: ../../../../.icons/oci.svg +maintainer_github: coder +verified: false +tags: [vm, linux, oci, oracle] +--- + +# Remote Development on Oracle Cloud Infrastructure (Linux) + +Provision Oracle Cloud Infrastructure (OCI) VMs as [Coder workspaces](https://coder.com/docs/workspaces) with this example template. + +## Prerequisites + +### Authentication + +This template assumes that coderd is run in an environment that is authenticated with Oracle Cloud Infrastructure. The recommended authentication methods are: + +1. **Instance Principal** (Recommended for production): Run Coder on an OCI instance with proper IAM policies +2. **API Key**: Set environment variables `OCI_TENANCY_OCID`, `OCI_USER_OCID`, `OCI_FINGERPRINT`, and `OCI_PRIVATE_KEY_PATH` +3. **Configuration File**: Use `~/.oci/config` file + +For detailed authentication setup, see the [OCI Terraform provider documentation](https://registry.terraform.io/providers/oracle/oci/latest/docs#authentication). + +### Required IAM Policies + +The following IAM policies are required for the template to work: + +```json +{ + "statements": [ + { + "effect": "Allow", + "action": [ + "core:instance:create", + "core:instance:delete", + "core:instance:get", + "core:instance:update", + "core:volume:create", + "core:volume:delete", + "core:volume:get", + "core:volume:update", + "core:volumeAttachment:create", + "core:volumeAttachment:delete", + "core:volumeAttachment:get", + "core:vcn:create", + "core:vcn:delete", + "core:vcn:get", + "core:vcn:update", + "core:subnet:create", + "core:subnet:delete", + "core:subnet:get", + "core:subnet:update", + "core:internetGateway:create", + "core:internetGateway:delete", + "core:internetGateway:get", + "core:internetGateway:update", + "core:routeTable:create", + "core:routeTable:delete", + "core:routeTable:get", + "core:routeTable:update", + "core:securityList:create", + "core:securityList:delete", + "core:securityList:get", + "core:securityList:update", + "core:image:get", + "identity:compartment:get" + ], + "resource": "*" + } + ] +} +``` + +## Architecture + +This template provisions the following resources: + +- **OCI VM** (ephemeral, deleted on stop) +- **OCI Block Volume** (persistent, mounted to `/home/coder`) +- **VCN with Internet Gateway** (for network connectivity) +- **Security List** (with SSH, HTTP, and HTTPS access) + +The template uses Ubuntu 22.04 LTS as the base image and includes: + +- Code Server for web-based development +- JetBrains Gateway for IDE access +- Persistent home directory storage +- Automatic Coder agent installation + +## Usage + +1. **Set up authentication** using one of the methods above +2. **Create a compartment** in your OCI tenancy +3. **Deploy the template** with your compartment OCID +4. **Optionally provide an SSH public key** for direct SSH access + +### Template Variables + +- `compartment_ocid`: The OCID of your OCI compartment +- `ssh_public_key`: (Optional) SSH public key for direct access + +### Instance Shapes + +The template supports various OCI instance shapes: + +- **VM.Standard.A1.Flex**: ARM-based flexible shapes (1-4 OCPUs, 6-24 GB RAM) +- **VM.Standard.E2.1.Micro**: Cost-effective micro instances +- **VM.Standard.E2.1.Small**: Small instances for development +- **VM.Standard.E2.1.Medium**: Medium instances for larger workloads +- **VM.Standard.E3.Flex**: AMD-based flexible shapes + +### Regions + +The template supports all major OCI regions: + +- **Americas**: US East (Ashburn), US West (Phoenix), Canada Southeast (Montreal) +- **Europe**: UK South (London), Germany Central (Frankfurt), Netherlands Northwest (Amsterdam), Switzerland North (Zurich) +- **Asia Pacific**: Japan East (Tokyo), Japan Central (Osaka), South Korea Central (Seoul), Australia Southeast (Sydney), India West (Mumbai), India South (Hyderabad) +- **Middle East**: Saudi Arabia West (Jeddah), UAE East (Dubai) +- **South America**: Brazil East (São Paulo), Chile (Santiago) + +## Cost Optimization + +- Use **VM.Standard.A1.Flex** shapes for cost-effective ARM-based instances +- Choose **VM.Standard.E2.1.Micro** for minimal development workloads +- Consider **VM.Standard.E3.Flex** for AMD-based workloads requiring more memory +- Use smaller home disk sizes (50 GB) for basic development +- Stop workspaces when not in use to avoid charges + +## Security + +- Instances are created with public IP addresses for Coder access +- SSH access is restricted to the provided public key +- Security lists allow only necessary ports (22, 80, 443) +- All resources are tagged with `Coder_Provisioned = true` + +## Troubleshooting + +### Common Issues + +1. **Authentication Errors**: Ensure proper OCI authentication is configured +2. **Permission Errors**: Verify IAM policies are correctly set +3. **Network Issues**: Check VCN and security list configuration +4. **Volume Attachment**: Ensure the home volume is properly attached + +### Debugging + +- Check OCI console for instance status and logs +- Verify network connectivity and security list rules +- Review Terraform logs for detailed error messages + +## Contributing + +This template is designed to be a starting point! Edit the Terraform to extend the template to support your use case. + +For issues and contributions, please visit the [Coder Registry repository](https://github.com/coder/registry). + +## Contributors + +- [aybanda](https://github.com/aybanda) + diff --git a/registry/aybanda/templates/oci-linux/cloud-init/cloud-config.yaml.tftpl b/registry/aybanda/templates/oci-linux/cloud-init/cloud-config.yaml.tftpl new file mode 100644 index 000000000..5951050b1 --- /dev/null +++ b/registry/aybanda/templates/oci-linux/cloud-init/cloud-config.yaml.tftpl @@ -0,0 +1,39 @@ +#cloud-config +hostname: ${hostname} +users: + - name: ${linux_user} + uid: 1000 + gid: 1000 + groups: sudo + packages: + - curl + shell: /bin/bash + sudo: ['ALL=(ALL) NOPASSWD:ALL'] + ssh_authorized_keys: + - ${ssh_public_key} + +# Update package list and install basic packages +package_update: true +package_upgrade: true +packages: + - curl + - wget + - git + - unzip + - software-properties-common + - apt-transport-https + - ca-certificates + - gnupg + - lsb-release + +# Write the Coder agent token to a file +write_files: + - path: /opt/coder/init.env + content: | + CODER_AGENT_TOKEN=${coder_agent_token} + owner: ${linux_user}:${linux_user} + permissions: '0600' + +# Run commands after package installation +runcmd: + - systemctl enable --now coder-agent \ No newline at end of file diff --git a/registry/aybanda/templates/oci-linux/cloud-init/userdata.sh.tftpl b/registry/aybanda/templates/oci-linux/cloud-init/userdata.sh.tftpl new file mode 100644 index 000000000..832ffcdc3 --- /dev/null +++ b/registry/aybanda/templates/oci-linux/cloud-init/userdata.sh.tftpl @@ -0,0 +1,48 @@ +#!/bin/bash +set -e + +# Set hostname +hostnamectl set-hostname ${hostname} + +# Create coder user if it doesn't exist +if ! id "${linux_user}" &>/dev/null; then + useradd -m -s /bin/bash -G sudo ${linux_user} + echo "${linux_user} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers +fi + +# Create necessary directories +mkdir -p /opt/coder +mkdir -p /home/${linux_user} + +# Set up SSH key if provided +if [ -n "${ssh_public_key}" ]; then + mkdir -p /home/${linux_user}/.ssh + echo "${ssh_public_key}" >> /home/${linux_user}/.ssh/authorized_keys + chown -R ${linux_user}:${linux_user} /home/${linux_user}/.ssh + chmod 700 /home/${linux_user}/.ssh + chmod 600 /home/${linux_user}/.ssh/authorized_keys +fi + +# Mount home volume if it exists +if [ -b /dev/sdb ]; then + # Check if the disk is already formatted + if ! blkid /dev/sdb; then + mkfs.ext4 /dev/sdb + fi + + # Create mount point and mount + mkdir -p /home/${linux_user} + mount /dev/sdb /home/${linux_user} + + # Add to fstab for persistence + echo "/dev/sdb /home/${linux_user} ext4 defaults 0 2" >> /etc/fstab + + # Set ownership + chown -R ${linux_user}:${linux_user} /home/${linux_user} +fi + +# Download and install Coder agent +curl -fsSL https://coder.com/install.sh | sh + +# Start the Coder agent +systemctl enable --now coder-agent \ No newline at end of file diff --git a/registry/aybanda/templates/oci-linux/main.tf b/registry/aybanda/templates/oci-linux/main.tf new file mode 100644 index 000000000..ee29fb596 --- /dev/null +++ b/registry/aybanda/templates/oci-linux/main.tf @@ -0,0 +1,491 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + oci = { + source = "oracle/oci" + } + cloudinit = { + source = "hashicorp/cloudinit" + } + } +} + +# Variables +variable "compartment_ocid" { + description = "The OCID of the compartment to create resources in" + type = string +} + +variable "ssh_public_key" { + description = "SSH public key for the instance" + type = string + default = "" +} + +# OCI Region parameter +data "coder_parameter" "region" { + name = "region" + display_name = "Region" + description = "The region to deploy the workspace in." + default = "us-ashburn-1" + mutable = false + option { + name = "US East (Ashburn)" + value = "us-ashburn-1" + icon = "/emojis/1f1fa-1f1f8.png" + } + option { + name = "US West (Phoenix)" + value = "us-phoenix-1" + icon = "/emojis/1f1fa-1f1f8.png" + } + option { + name = "Canada Southeast (Montreal)" + value = "ca-montreal-1" + icon = "/emojis/1f1e8-1f1e6.png" + } + option { + name = "UK South (London)" + value = "uk-london-1" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "Germany Central (Frankfurt)" + value = "eu-frankfurt-1" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "Netherlands Northwest (Amsterdam)" + value = "eu-amsterdam-1" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "Switzerland North (Zurich)" + value = "eu-zurich-1" + icon = "/emojis/1f1ea-1f1fa.png" + } + option { + name = "Japan East (Tokyo)" + value = "ap-tokyo-1" + icon = "/emojis/1f1ef-1f1f5.png" + } + option { + name = "Japan Central (Osaka)" + value = "ap-osaka-1" + icon = "/emojis/1f1ef-1f1f5.png" + } + option { + name = "South Korea Central (Seoul)" + value = "ap-seoul-1" + icon = "/emojis/1f1f0-1f1f7.png" + } + option { + name = "Australia Southeast (Sydney)" + value = "ap-sydney-1" + icon = "/emojis/1f1e6-1f1fa.png" + } + option { + name = "India West (Mumbai)" + value = "ap-mumbai-1" + icon = "/emojis/1f1ee-1f1f3.png" + } + option { + name = "India South (Hyderabad)" + value = "ap-hyderabad-1" + icon = "/emojis/1f1ee-1f1f3.png" + } + option { + name = "Saudi Arabia West (Jeddah)" + value = "me-jeddah-1" + icon = "/emojis/1f1f8-1f1e6.png" + } + option { + name = "UAE East (Dubai)" + value = "me-dubai-1" + icon = "/emojis/1f1e6-1f1ea.png" + } + option { + name = "Brazil East (São Paulo)" + value = "sa-saopaulo-1" + icon = "/emojis/1f1e7-1f1f7.png" + } + option { + name = "Chile (Santiago)" + value = "sa-santiago-1" + icon = "/emojis/1f1e8-1f1f1.png" + } +} + +# Instance shape parameter +data "coder_parameter" "instance_shape" { + name = "instance_shape" + display_name = "Instance Shape" + description = "What instance shape should your workspace use?" + default = "VM.Standard.A1.Flex" + mutable = false + option { + name = "VM.Standard.A1.Flex (1 OCPU, 6 GB RAM)" + value = "VM.Standard.A1.Flex" + } + option { + name = "VM.Standard.A1.Flex (2 OCPU, 12 GB RAM)" + value = "VM.Standard.A1.Flex" + } + option { + name = "VM.Standard.A1.Flex (4 OCPU, 24 GB RAM)" + value = "VM.Standard.A1.Flex" + } + option { + name = "VM.Standard.E2.1.Micro (1 OCPU, 1 GB RAM)" + value = "VM.Standard.E2.1.Micro" + } + option { + name = "VM.Standard.E2.1.Small (1 OCPU, 2 GB RAM)" + value = "VM.Standard.E2.1.Small" + } + option { + name = "VM.Standard.E2.1.Medium (1 OCPU, 4 GB RAM)" + value = "VM.Standard.E2.1.Medium" + } + option { + name = "VM.Standard.E2.2.Medium (2 OCPU, 8 GB RAM)" + value = "VM.Standard.E2.2.Medium" + } + option { + name = "VM.Standard.E2.4.Medium (4 OCPU, 16 GB RAM)" + value = "VM.Standard.E2.4.Medium" + } + option { + name = "VM.Standard.E3.Flex (1 OCPU, 8 GB RAM)" + value = "VM.Standard.E3.Flex" + } + option { + name = "VM.Standard.E3.Flex (2 OCPU, 16 GB RAM)" + value = "VM.Standard.E3.Flex" + } + option { + name = "VM.Standard.E3.Flex (4 OCPU, 32 GB RAM)" + value = "VM.Standard.E3.Flex" + } +} + +# Home disk size parameter +data "coder_parameter" "home_size" { + name = "home_size" + display_name = "Home Disk Size" + description = "How large should the home disk be?" + default = "50" + mutable = false + option { + name = "50 GB" + value = "50" + } + option { + name = "100 GB" + value = "100" + } + option { + name = "200 GB" + value = "200" + } + option { + name = "500 GB" + value = "500" + } + option { + name = "1 TB" + value = "1024" + } +} + +# OCI Provider configuration +provider "oci" { + region = data.coder_parameter.region.value +} + +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +# Get the compartment OCID from environment variable +data "oci_identity_compartments" "compartments" { + compartment_id = var.compartment_ocid + access_level = "ACCESSIBLE" + state = "ACTIVE" +} + +# Get the latest Ubuntu image +data "oci_core_images" "ubuntu" { + compartment_id = var.compartment_ocid + operating_system = "Canonical Ubuntu" + operating_system_version = "22.04" + state = "AVAILABLE" + sort_by = "TIMECREATED" + sort_order = "DESC" +} + +locals { + hostname = lower(data.coder_workspace.me.name) + linux_user = "coder" +} + +# Coder Agent +resource "coder_agent" "dev" { + count = data.coder_workspace.me.start_count + arch = "amd64" + auth = "token" + os = "linux" + startup_script = <<-EOT + set -e + + # Add any commands that should be executed at workspace startup (e.g install requirements, start a program, etc) here + EOT + + metadata { + key = "cpu" + display_name = "CPU Usage" + interval = 5 + timeout = 5 + script = "coder stat cpu" + } + metadata { + key = "memory" + display_name = "Memory Usage" + interval = 5 + timeout = 5 + script = "coder stat mem" + } + metadata { + key = "disk" + display_name = "Disk Usage" + interval = 600 # every 10 minutes + timeout = 30 # df can take a while on large filesystems + script = "coder stat disk --path $HOME" + } +} + +# See https://registry.coder.com/modules/coder/code-server +module "code-server" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/modules/code-server/coder" + + # This ensures that the latest non-breaking version of the module gets downloaded, you can also pin the module version to prevent breaking changes in production. + version = "~> 1.0" + + agent_id = coder_agent.dev[0].id + order = 1 +} + +# See https://registry.coder.com/modules/jetbrains-gateway +module "jetbrains_gateway" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/modules/jetbrains-gateway/coder" + + # JetBrains IDEs to make available for the user to select + jetbrains_ides = ["IU", "PY", "WS", "PS", "RD", "CL", "GO", "RM"] + default = "IU" + + # Default folder to open when starting a JetBrains IDE + folder = "/home/coder" + + # This ensures that the latest non-breaking version of the module gets downloaded, you can also pin the module version to prevent breaking changes in production. + version = "~> 1.0" + + agent_id = coder_agent.dev[0].id + agent_name = "dev" + order = 2 +} + +# Cloud-init configuration +data "cloudinit_config" "user_data" { + gzip = false + base64_encode = false + + boundary = "//" + + part { + filename = "cloud-config.yaml" + content_type = "text/cloud-config" + + content = templatefile("${path.module}/cloud-init/cloud-config.yaml.tftpl", { + hostname = local.hostname + linux_user = local.linux_user + ssh_public_key = var.ssh_public_key + coder_agent_token = coder_agent.dev[0].token + }) + } + + part { + filename = "userdata.sh" + content_type = "text/x-shellscript" + + content = templatefile("${path.module}/cloud-init/userdata.sh.tftpl", { + hostname = local.hostname + linux_user = local.linux_user + ssh_public_key = var.ssh_public_key + coder_agent_token = coder_agent.dev[0].token + }) + } +} + +# VCN +resource "oci_core_vcn" "vcn" { + compartment_id = var.compartment_ocid + cidr_blocks = ["10.0.0.0/16"] + display_name = "coder-vcn-${data.coder_workspace.me.id}" + dns_label = "coder${data.coder_workspace.me.id}" +} + +# Internet Gateway +resource "oci_core_internet_gateway" "internet_gateway" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.vcn.id + display_name = "coder-internet-gateway-${data.coder_workspace.me.id}" +} + +# Route Table +resource "oci_core_route_table" "route_table" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.vcn.id + display_name = "coder-route-table-${data.coder_workspace.me.id}" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.internet_gateway.id + } +} + +# Security List +resource "oci_core_security_list" "security_list" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.vcn.id + display_name = "coder-security-list-${data.coder_workspace.me.id}" + + egress_security_rules { + destination = "0.0.0.0/0" + protocol = "all" + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + min = 22 + max = 22 + } + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + min = 80 + max = 80 + } + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + min = 443 + max = 443 + } + } +} + +# Subnet +resource "oci_core_subnet" "subnet" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_vcn.vcn.id + cidr_block = "10.0.1.0/24" + display_name = "coder-subnet-${data.coder_workspace.me.id}" + dns_label = "coder${data.coder_workspace.me.id}" + + security_list_ids = [oci_core_security_list.security_list.id] + route_table_id = oci_core_route_table.route_table.id +} + +# Home disk +resource "oci_core_volume" "home_volume" { + compartment_id = var.compartment_ocid + display_name = "coder-${data.coder_workspace.me.id}-home" + size_in_gbs = data.coder_parameter.home_size.value + availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name +} + +# Get availability domains +data "oci_identity_availability_domains" "ads" { + compartment_id = var.compartment_ocid +} + +# OCI Instance +resource "oci_core_instance" "dev" { + count = data.coder_workspace.me.start_count + availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name + compartment_id = var.compartment_ocid + display_name = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}" + shape = data.coder_parameter.instance_shape.value + + shape_config { + ocpus = 1 + memory_in_gbs = 6 + } + + create_vnic_details { + subnet_id = oci_core_subnet.subnet.id + assign_public_ip = true + } + + source_details { + source_type = "image" + source_id = data.oci_core_images.ubuntu.images[0].id + } + + metadata = { + ssh_authorized_keys = var.ssh_public_key + user_data = base64encode(data.cloudinit_config.user_data.rendered) + } + + freeform_tags = { + "Coder_Provisioned" = "true" + } +} + +# Attach home volume +resource "oci_core_volume_attachment" "home_attachment" { + count = data.coder_workspace.me.start_count + attachment_type = "paravirtualized" + compartment_id = var.compartment_ocid + instance_id = oci_core_instance.dev[0].id + volume_id = oci_core_volume.home_volume.id +} + +# Workspace metadata +resource "coder_metadata" "workspace_info" { + count = data.coder_workspace.me.start_count + resource_id = oci_core_instance.dev[0].id + + item { + key = "type" + value = oci_core_instance.dev[0].shape + } + item { + key = "region" + value = data.coder_parameter.region.value + } +} + +resource "coder_metadata" "home_info" { + resource_id = oci_core_volume.home_volume.id + + item { + key = "size" + value = "${data.coder_parameter.home_size.value} GiB" + } +} From 1f001f01db9876b6c8b9ace6df0e1b3b5afcde9a Mon Sep 17 00:00:00 2001 From: aybanda Date: Wed, 16 Jul 2025 15:47:18 +0530 Subject: [PATCH 02/11] chore: remove deprecated maintainer_github field from OCI template README --- registry/aybanda/templates/oci-linux/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/registry/aybanda/templates/oci-linux/README.md b/registry/aybanda/templates/oci-linux/README.md index 466d0309b..13c75379c 100644 --- a/registry/aybanda/templates/oci-linux/README.md +++ b/registry/aybanda/templates/oci-linux/README.md @@ -2,7 +2,6 @@ display_name: Oracle Cloud Infrastructure (Linux) description: Provision Oracle Cloud Infrastructure VMs as Coder workspaces icon: ../../../../.icons/oci.svg -maintainer_github: coder verified: false tags: [vm, linux, oci, oracle] --- From 4df47970cddc9a01a727952332801eac03e606c9 Mon Sep 17 00:00:00 2001 From: aybanda Date: Wed, 30 Jul 2025 17:24:51 +0530 Subject: [PATCH 03/11] fix: resolve duplicate option values in OCI template instance shape parameter - Fix duplicate option values for VM.Standard.A1.Flex and VM.Standard.E3.Flex shapes - Add dynamic shape configuration handling for flexible shapes - Implement proper OCPU and memory parsing from parameter values - Ensure unique option values while maintaining descriptive names - Template now passes terraform validation without errors --- registry/aybanda/templates/oci-linux/main.tf | 32 ++++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/registry/aybanda/templates/oci-linux/main.tf b/registry/aybanda/templates/oci-linux/main.tf index ee29fb596..d27d4a3d6 100644 --- a/registry/aybanda/templates/oci-linux/main.tf +++ b/registry/aybanda/templates/oci-linux/main.tf @@ -127,15 +127,15 @@ data "coder_parameter" "instance_shape" { mutable = false option { name = "VM.Standard.A1.Flex (1 OCPU, 6 GB RAM)" - value = "VM.Standard.A1.Flex" + value = "VM.Standard.A1.Flex-1-6" } option { name = "VM.Standard.A1.Flex (2 OCPU, 12 GB RAM)" - value = "VM.Standard.A1.Flex" + value = "VM.Standard.A1.Flex-2-12" } option { name = "VM.Standard.A1.Flex (4 OCPU, 24 GB RAM)" - value = "VM.Standard.A1.Flex" + value = "VM.Standard.A1.Flex-4-24" } option { name = "VM.Standard.E2.1.Micro (1 OCPU, 1 GB RAM)" @@ -159,15 +159,15 @@ data "coder_parameter" "instance_shape" { } option { name = "VM.Standard.E3.Flex (1 OCPU, 8 GB RAM)" - value = "VM.Standard.E3.Flex" + value = "VM.Standard.E3.Flex-1-8" } option { name = "VM.Standard.E3.Flex (2 OCPU, 16 GB RAM)" - value = "VM.Standard.E3.Flex" + value = "VM.Standard.E3.Flex-2-16" } option { name = "VM.Standard.E3.Flex (4 OCPU, 32 GB RAM)" - value = "VM.Standard.E3.Flex" + value = "VM.Standard.E3.Flex-4-32" } } @@ -228,6 +228,15 @@ data "oci_core_images" "ubuntu" { locals { hostname = lower(data.coder_workspace.me.name) linux_user = "coder" + + # Parse shape configuration for flexible shapes + shape_parts = split("-", data.coder_parameter.instance_shape.value) + base_shape = length(local.shape_parts) > 2 ? join("-", slice(local.shape_parts, 0, 3)) : data.coder_parameter.instance_shape.value + ocpus = length(local.shape_parts) > 3 ? tonumber(local.shape_parts[3]) : 1 + memory_gb = length(local.shape_parts) > 4 ? tonumber(local.shape_parts[4]) : 6 + + # Determine if shape is flexible (needs shape_config) + is_flexible = can(regex(".*Flex.*", local.base_shape)) } # Coder Agent @@ -430,11 +439,14 @@ resource "oci_core_instance" "dev" { availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name compartment_id = var.compartment_ocid display_name = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}" - shape = data.coder_parameter.instance_shape.value + shape = local.base_shape - shape_config { - ocpus = 1 - memory_in_gbs = 6 + dynamic "shape_config" { + for_each = local.is_flexible ? [1] : [] + content { + ocpus = local.ocpus + memory_in_gbs = local.memory_gb + } } create_vnic_details { From 9bc407385d30b89ec04d2b0c259134bad6be345a Mon Sep 17 00:00:00 2001 From: aybanda Date: Thu, 7 Aug 2025 15:09:51 +0530 Subject: [PATCH 04/11] fix: apply formatting to OCI template README --- registry/aybanda/templates/oci-linux/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/registry/aybanda/templates/oci-linux/README.md b/registry/aybanda/templates/oci-linux/README.md index 13c75379c..1398ec167 100644 --- a/registry/aybanda/templates/oci-linux/README.md +++ b/registry/aybanda/templates/oci-linux/README.md @@ -159,4 +159,3 @@ For issues and contributions, please visit the [Coder Registry repository](https ## Contributors - [aybanda](https://github.com/aybanda) - From 0a78e2d12db22637bf6f7e29f0b6c9f056e0856f Mon Sep 17 00:00:00 2001 From: aybanda Date: Fri, 8 Aug 2025 21:08:56 +0530 Subject: [PATCH 05/11] fix: apply proper formatting to OCI template files --- registry/aybanda/templates/oci-linux/main.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/aybanda/templates/oci-linux/main.tf b/registry/aybanda/templates/oci-linux/main.tf index d27d4a3d6..57b3f1c46 100644 --- a/registry/aybanda/templates/oci-linux/main.tf +++ b/registry/aybanda/templates/oci-linux/main.tf @@ -228,13 +228,13 @@ data "oci_core_images" "ubuntu" { locals { hostname = lower(data.coder_workspace.me.name) linux_user = "coder" - + # Parse shape configuration for flexible shapes shape_parts = split("-", data.coder_parameter.instance_shape.value) base_shape = length(local.shape_parts) > 2 ? join("-", slice(local.shape_parts, 0, 3)) : data.coder_parameter.instance_shape.value ocpus = length(local.shape_parts) > 3 ? tonumber(local.shape_parts[3]) : 1 memory_gb = length(local.shape_parts) > 4 ? tonumber(local.shape_parts[4]) : 6 - + # Determine if shape is flexible (needs shape_config) is_flexible = can(regex(".*Flex.*", local.base_shape)) } @@ -500,4 +500,4 @@ resource "coder_metadata" "home_info" { key = "size" value = "${data.coder_parameter.home_size.value} GiB" } -} +} From 73b030089d4ca13f196acedd4e92d38be32f1ae4 Mon Sep 17 00:00:00 2001 From: Ajay Bandaru Date: Wed, 13 Aug 2025 21:52:38 +0530 Subject: [PATCH 06/11] fix: remove AWS logo and icon reference --- .icons/oci.svg | 13 ------------- registry/aybanda/templates/oci-linux/README.md | 1 - 2 files changed, 14 deletions(-) delete mode 100644 .icons/oci.svg diff --git a/.icons/oci.svg b/.icons/oci.svg deleted file mode 100644 index 3244c9748..000000000 --- a/.icons/oci.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/registry/aybanda/templates/oci-linux/README.md b/registry/aybanda/templates/oci-linux/README.md index 1398ec167..ee0b635a9 100644 --- a/registry/aybanda/templates/oci-linux/README.md +++ b/registry/aybanda/templates/oci-linux/README.md @@ -1,7 +1,6 @@ --- display_name: Oracle Cloud Infrastructure (Linux) description: Provision Oracle Cloud Infrastructure VMs as Coder workspaces -icon: ../../../../.icons/oci.svg verified: false tags: [vm, linux, oci, oracle] --- From a98ff260a2857f1899fb981605742625dfc49c89 Mon Sep 17 00:00:00 2001 From: Ajay Bandaru Date: Wed, 13 Aug 2025 22:57:50 +0530 Subject: [PATCH 07/11] add OCI logo --- .icons/oci.svg | 18 ++++++++++++++++++ registry/aybanda/templates/oci-linux/README.md | 1 + 2 files changed, 19 insertions(+) create mode 100644 .icons/oci.svg diff --git a/.icons/oci.svg b/.icons/oci.svg new file mode 100644 index 000000000..acd3d123d --- /dev/null +++ b/.icons/oci.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + ORACLE + + + ® + diff --git a/registry/aybanda/templates/oci-linux/README.md b/registry/aybanda/templates/oci-linux/README.md index ee0b635a9..1398ec167 100644 --- a/registry/aybanda/templates/oci-linux/README.md +++ b/registry/aybanda/templates/oci-linux/README.md @@ -1,6 +1,7 @@ --- display_name: Oracle Cloud Infrastructure (Linux) description: Provision Oracle Cloud Infrastructure VMs as Coder workspaces +icon: ../../../../.icons/oci.svg verified: false tags: [vm, linux, oci, oracle] --- From b7f8fc0548246907df3f4e53cd778e38fd92057f Mon Sep 17 00:00:00 2001 From: Ajay Bandaru Date: Thu, 14 Aug 2025 09:58:15 +0530 Subject: [PATCH 08/11] fix logo --- .icons/oci.svg | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/.icons/oci.svg b/.icons/oci.svg index acd3d123d..d19f2a183 100644 --- a/.icons/oci.svg +++ b/.icons/oci.svg @@ -1,18 +1,17 @@ - - - - - - - - - - - - - ORACLE - - - ® + + + + + + + + + + + + + + + + From fcecb984ce97e401128bdf08dd495c3a60bfe8f4 Mon Sep 17 00:00:00 2001 From: Bandaru Date: Wed, 20 Aug 2025 13:53:02 +0530 Subject: [PATCH 09/11] fix: replace incorrect logo with official Oracle Corporation logo --- .icons/oci.svg | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/.icons/oci.svg b/.icons/oci.svg index d19f2a183..561271d2f 100644 --- a/.icons/oci.svg +++ b/.icons/oci.svg @@ -1,17 +1,4 @@ - - - - - - - - - - - - - - - - - + + + + \ No newline at end of file From d39742c06f564eb9f4cabc1f297beba2a3a0602e Mon Sep 17 00:00:00 2001 From: AB Date: Thu, 11 Sep 2025 14:40:01 +0530 Subject: [PATCH 10/11] oci-linux: docs/auth updates; remove SSH var; default compartment to tenancy; fix instance_shape default; use effective compartment for image/AD; update OCI logo to official wordmark --- .../aybanda/templates/oci-linux/README.md | 7 +-- .../cloud-init/cloud-config.yaml.tftpl | 3 +- .../oci-linux/cloud-init/userdata.sh.tftpl | 9 +-- registry/aybanda/templates/oci-linux/main.tf | 55 ++++++++----------- 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/registry/aybanda/templates/oci-linux/README.md b/registry/aybanda/templates/oci-linux/README.md index 1398ec167..4dba20f34 100644 --- a/registry/aybanda/templates/oci-linux/README.md +++ b/registry/aybanda/templates/oci-linux/README.md @@ -17,8 +17,8 @@ Provision Oracle Cloud Infrastructure (OCI) VMs as [Coder workspaces](https://co This template assumes that coderd is run in an environment that is authenticated with Oracle Cloud Infrastructure. The recommended authentication methods are: 1. **Instance Principal** (Recommended for production): Run Coder on an OCI instance with proper IAM policies -2. **API Key**: Set environment variables `OCI_TENANCY_OCID`, `OCI_USER_OCID`, `OCI_FINGERPRINT`, and `OCI_PRIVATE_KEY_PATH` -3. **Configuration File**: Use `~/.oci/config` file +2. **API Key**: Set environment variables `OCI_TENANCY_OCID`, `OCI_USER_OCID`, `OCI_FINGERPRINT`, and `OCI_PRIVATE_KEY_PATH`. If running coderd/provisioner in a container, ensure the private key file path is mounted into the container so it is accessible at the specified path. +3. **Configuration File**: Use `~/.oci/config` file (mount into the container if coderd runs in a container) For detailed authentication setup, see the [OCI Terraform provider documentation](https://registry.terraform.io/providers/oracle/oci/latest/docs#authentication). @@ -92,8 +92,7 @@ The template uses Ubuntu 22.04 LTS as the base image and includes: 1. **Set up authentication** using one of the methods above 2. **Create a compartment** in your OCI tenancy -3. **Deploy the template** with your compartment OCID -4. **Optionally provide an SSH public key** for direct SSH access +3. **Deploy the template** (if you omit `compartment_ocid`, the tenancy/root compartment will be used) ### Template Variables diff --git a/registry/aybanda/templates/oci-linux/cloud-init/cloud-config.yaml.tftpl b/registry/aybanda/templates/oci-linux/cloud-init/cloud-config.yaml.tftpl index 5951050b1..b8d395639 100644 --- a/registry/aybanda/templates/oci-linux/cloud-init/cloud-config.yaml.tftpl +++ b/registry/aybanda/templates/oci-linux/cloud-init/cloud-config.yaml.tftpl @@ -9,8 +9,7 @@ users: - curl shell: /bin/bash sudo: ['ALL=(ALL) NOPASSWD:ALL'] - ssh_authorized_keys: - - ${ssh_public_key} + ssh_authorized_keys: [] # Update package list and install basic packages package_update: true diff --git a/registry/aybanda/templates/oci-linux/cloud-init/userdata.sh.tftpl b/registry/aybanda/templates/oci-linux/cloud-init/userdata.sh.tftpl index 832ffcdc3..28adf7a5b 100644 --- a/registry/aybanda/templates/oci-linux/cloud-init/userdata.sh.tftpl +++ b/registry/aybanda/templates/oci-linux/cloud-init/userdata.sh.tftpl @@ -14,14 +14,7 @@ fi mkdir -p /opt/coder mkdir -p /home/${linux_user} -# Set up SSH key if provided -if [ -n "${ssh_public_key}" ]; then - mkdir -p /home/${linux_user}/.ssh - echo "${ssh_public_key}" >> /home/${linux_user}/.ssh/authorized_keys - chown -R ${linux_user}:${linux_user} /home/${linux_user}/.ssh - chmod 700 /home/${linux_user}/.ssh - chmod 600 /home/${linux_user}/.ssh/authorized_keys -fi +# SSH key management is handled by Coder agent; no direct SSH key injection # Mount home volume if it exists if [ -b /dev/sdb ]; then diff --git a/registry/aybanda/templates/oci-linux/main.tf b/registry/aybanda/templates/oci-linux/main.tf index 57b3f1c46..54727d7f2 100644 --- a/registry/aybanda/templates/oci-linux/main.tf +++ b/registry/aybanda/templates/oci-linux/main.tf @@ -14,12 +14,13 @@ terraform { # Variables variable "compartment_ocid" { - description = "The OCID of the compartment to create resources in" + description = "The OCID of the compartment to create resources in. If empty, defaults to tenancy OCID (root compartment)." type = string + default = "" } -variable "ssh_public_key" { - description = "SSH public key for the instance" +variable "tenancy_ocid" { + description = "Tenancy OCID used as the root compartment when compartment_ocid is unset. Typically set from environment (OCI_TENANCY_OCID)." type = string default = "" } @@ -123,7 +124,7 @@ data "coder_parameter" "instance_shape" { name = "instance_shape" display_name = "Instance Shape" description = "What instance shape should your workspace use?" - default = "VM.Standard.A1.Flex" + default = "VM.Standard.E2.1.Micro" mutable = false option { name = "VM.Standard.A1.Flex (1 OCPU, 6 GB RAM)" @@ -208,16 +209,19 @@ provider "oci" { data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} -# Get the compartment OCID from environment variable -data "oci_identity_compartments" "compartments" { - compartment_id = var.compartment_ocid - access_level = "ACCESSIBLE" - state = "ACTIVE" +# Determine effective compartment (defaults to tenancy/root when not provided) +locals { + effective_compartment_ocid = length(trimspace(var.compartment_ocid)) > 0 ? var.compartment_ocid : var.tenancy_ocid +} + +# Validate we have an effective compartment id +locals { + compartment_id = local.effective_compartment_ocid } # Get the latest Ubuntu image data "oci_core_images" "ubuntu" { - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id operating_system = "Canonical Ubuntu" operating_system_version = "22.04" state = "AVAILABLE" @@ -320,7 +324,6 @@ data "cloudinit_config" "user_data" { content = templatefile("${path.module}/cloud-init/cloud-config.yaml.tftpl", { hostname = local.hostname linux_user = local.linux_user - ssh_public_key = var.ssh_public_key coder_agent_token = coder_agent.dev[0].token }) } @@ -332,7 +335,6 @@ data "cloudinit_config" "user_data" { content = templatefile("${path.module}/cloud-init/userdata.sh.tftpl", { hostname = local.hostname linux_user = local.linux_user - ssh_public_key = var.ssh_public_key coder_agent_token = coder_agent.dev[0].token }) } @@ -340,7 +342,7 @@ data "cloudinit_config" "user_data" { # VCN resource "oci_core_vcn" "vcn" { - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id cidr_blocks = ["10.0.0.0/16"] display_name = "coder-vcn-${data.coder_workspace.me.id}" dns_label = "coder${data.coder_workspace.me.id}" @@ -348,14 +350,14 @@ resource "oci_core_vcn" "vcn" { # Internet Gateway resource "oci_core_internet_gateway" "internet_gateway" { - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id vcn_id = oci_core_vcn.vcn.id display_name = "coder-internet-gateway-${data.coder_workspace.me.id}" } # Route Table resource "oci_core_route_table" "route_table" { - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id vcn_id = oci_core_vcn.vcn.id display_name = "coder-route-table-${data.coder_workspace.me.id}" @@ -368,7 +370,7 @@ resource "oci_core_route_table" "route_table" { # Security List resource "oci_core_security_list" "security_list" { - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id vcn_id = oci_core_vcn.vcn.id display_name = "coder-security-list-${data.coder_workspace.me.id}" @@ -377,16 +379,6 @@ resource "oci_core_security_list" "security_list" { protocol = "all" } - ingress_security_rules { - protocol = "6" - source = "0.0.0.0/0" - - tcp_options { - min = 22 - max = 22 - } - } - ingress_security_rules { protocol = "6" source = "0.0.0.0/0" @@ -410,7 +402,7 @@ resource "oci_core_security_list" "security_list" { # Subnet resource "oci_core_subnet" "subnet" { - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id vcn_id = oci_core_vcn.vcn.id cidr_block = "10.0.1.0/24" display_name = "coder-subnet-${data.coder_workspace.me.id}" @@ -422,7 +414,7 @@ resource "oci_core_subnet" "subnet" { # Home disk resource "oci_core_volume" "home_volume" { - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id display_name = "coder-${data.coder_workspace.me.id}-home" size_in_gbs = data.coder_parameter.home_size.value availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name @@ -430,14 +422,14 @@ resource "oci_core_volume" "home_volume" { # Get availability domains data "oci_identity_availability_domains" "ads" { - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id } # OCI Instance resource "oci_core_instance" "dev" { count = data.coder_workspace.me.start_count availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id display_name = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}" shape = local.base_shape @@ -460,7 +452,6 @@ resource "oci_core_instance" "dev" { } metadata = { - ssh_authorized_keys = var.ssh_public_key user_data = base64encode(data.cloudinit_config.user_data.rendered) } @@ -473,7 +464,7 @@ resource "oci_core_instance" "dev" { resource "oci_core_volume_attachment" "home_attachment" { count = data.coder_workspace.me.start_count attachment_type = "paravirtualized" - compartment_id = var.compartment_ocid + compartment_id = local.compartment_id instance_id = oci_core_instance.dev[0].id volume_id = oci_core_volume.home_volume.id } From 0fac5478f81bc4e3afc5de2e20baa82289d13119 Mon Sep 17 00:00:00 2001 From: AB Date: Thu, 11 Sep 2025 14:43:03 +0530 Subject: [PATCH 11/11] oci-linux: add precondition for compartment/tenancy and clarify auth/TF_VAR guidance to avoid 401s --- registry/aybanda/templates/oci-linux/README.md | 8 +++++--- registry/aybanda/templates/oci-linux/main.tf | 10 ++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/registry/aybanda/templates/oci-linux/README.md b/registry/aybanda/templates/oci-linux/README.md index 4dba20f34..fe0dccdd5 100644 --- a/registry/aybanda/templates/oci-linux/README.md +++ b/registry/aybanda/templates/oci-linux/README.md @@ -17,8 +17,8 @@ Provision Oracle Cloud Infrastructure (OCI) VMs as [Coder workspaces](https://co This template assumes that coderd is run in an environment that is authenticated with Oracle Cloud Infrastructure. The recommended authentication methods are: 1. **Instance Principal** (Recommended for production): Run Coder on an OCI instance with proper IAM policies -2. **API Key**: Set environment variables `OCI_TENANCY_OCID`, `OCI_USER_OCID`, `OCI_FINGERPRINT`, and `OCI_PRIVATE_KEY_PATH`. If running coderd/provisioner in a container, ensure the private key file path is mounted into the container so it is accessible at the specified path. -3. **Configuration File**: Use `~/.oci/config` file (mount into the container if coderd runs in a container) +2. **API Key**: Set env vars `OCI_TENANCY_OCID`, `OCI_USER_OCID`, `OCI_FINGERPRINT`, `OCI_PRIVATE_KEY_PATH`. If coderd/provisioner runs in a container, mount the private key path into the container. +3. **Configuration File**: Use `~/.oci/config` (mount into the container if coderd runs in a container) For detailed authentication setup, see the [OCI Terraform provider documentation](https://registry.terraform.io/providers/oracle/oci/latest/docs#authentication). @@ -92,7 +92,7 @@ The template uses Ubuntu 22.04 LTS as the base image and includes: 1. **Set up authentication** using one of the methods above 2. **Create a compartment** in your OCI tenancy -3. **Deploy the template** (if you omit `compartment_ocid`, the tenancy/root compartment will be used) +3. **Deploy the template** (if you omit `compartment_ocid`, set `TF_VAR_tenancy_ocid` to your tenancy OCID so the root compartment is used) ### Template Variables @@ -139,6 +139,8 @@ The template supports all major OCI regions: ### Common Issues 1. **Authentication Errors**: Ensure proper OCI authentication is configured + - If not using Instance Principals, set `TF_VAR_tenancy_ocid` (or `compartment_ocid`) and OCI env vars + - For containers, mount `OCI_PRIVATE_KEY_PATH` and/or `~/.oci/config` into the provisioner container 2. **Permission Errors**: Verify IAM policies are correctly set 3. **Network Issues**: Check VCN and security list configuration 4. **Volume Attachment**: Ensure the home volume is properly attached diff --git a/registry/aybanda/templates/oci-linux/main.tf b/registry/aybanda/templates/oci-linux/main.tf index 54727d7f2..71a9dd260 100644 --- a/registry/aybanda/templates/oci-linux/main.tf +++ b/registry/aybanda/templates/oci-linux/main.tf @@ -219,6 +219,16 @@ locals { compartment_id = local.effective_compartment_ocid } +# Early, friendly validation to avoid opaque 401s from the OCI APIs +resource "null_resource" "validate_configuration" { + lifecycle { + precondition { + condition = length(trimspace(local.compartment_id)) > 0 + error_message = "Provide either 'compartment_ocid' or 'tenancy_ocid'. For containerized coderd, set TF_VAR_tenancy_ocid or mount ~/.oci/config and set OCI_* envs." + } + } +} + # Get the latest Ubuntu image data "oci_core_images" "ubuntu" { compartment_id = local.compartment_id