Skip to content

Commit 049e7cb

Browse files
authored
azure-linux example template (#3348)
* azure-linux example template Signed-off-by: Spike Curtis <spike@coder.com> * Use azurerm_linux_virtual_machine and wait for attachment Signed-off-by: Spike Curtis <spike@coder.com> * Use azure-instance-identity Signed-off-by: Spike Curtis <spike@coder.com>
1 parent a848e71 commit 049e7cb

File tree

3 files changed

+284
-0
lines changed

3 files changed

+284
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: Develop in Linux on Azure
3+
description: Get started with Linux development on Microsoft Azure.
4+
tags: [cloud, azure, linux]
5+
---
6+
7+
# azure-linux
8+
9+
To get started, run `coder templates init`. When prompted, select this template.
10+
Follow the on-screen instructions to proceed.
11+
12+
## Authentication
13+
14+
This template assumes that coderd is run in an environment that is authenticated
15+
with Azure. For example, run `az login` then `az account set --subscription=<id>`
16+
to import credentials on the system and user running coderd. For other ways to
17+
authenticate [consult the Terraform docs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs#authenticating-to-azure).
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#cloud-config
2+
cloud_final_modules:
3+
- [scripts-user, always]
4+
bootcmd:
5+
# work around https://github.com/hashicorp/terraform-provider-azurerm/issues/6117
6+
- until [ -e /dev/disk/azure/scsi1/lun10 ]; do sleep 1; done
7+
device_aliases:
8+
homedir: /dev/disk/azure/scsi1/lun10
9+
disk_setup:
10+
homedir:
11+
table_type: gpt
12+
layout: true
13+
fs_setup:
14+
- label: coder_home
15+
filesystem: ext4
16+
device: homedir.1
17+
mounts:
18+
- ["LABEL=coder_home", "/home/${username}"]
19+
hostname: ${hostname}
20+
users:
21+
- name: ${username}
22+
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
23+
groups: sudo
24+
shell: /bin/bash
25+
packages:
26+
- git
27+
write_files:
28+
- path: /opt/coder/init
29+
permissions: "0755"
30+
encoding: b64
31+
content: ${init_script}
32+
- path: /etc/systemd/system/coder-agent.service
33+
permissions: "0644"
34+
content: |
35+
[Unit]
36+
Description=Coder Agent
37+
After=network-online.target
38+
Wants=network-online.target
39+
40+
[Service]
41+
User=${username}
42+
ExecStart=/opt/coder/init
43+
Restart=always
44+
RestartSec=10
45+
TimeoutStopSec=90
46+
KillMode=process
47+
48+
OOMScoreAdjust=-900
49+
SyslogIdentifier=coder-agent
50+
51+
[Install]
52+
WantedBy=multi-user.target
53+
runcmd:
54+
- chown ${username}:${username} /home/${username}
55+
- systemctl enable coder-agent
56+
- systemctl start coder-agent
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
version = "0.4.3"
6+
}
7+
azurerm = {
8+
source = "hashicorp/azurerm"
9+
version = "=3.0.0"
10+
}
11+
}
12+
}
13+
14+
variable "location" {
15+
description = "What location should your workspace live in?"
16+
default = "eastus"
17+
validation {
18+
condition = contains([
19+
"eastus",
20+
"southcentralus",
21+
"westus2",
22+
"australiaeast",
23+
"southeastasia",
24+
"northeurope",
25+
"westeurope",
26+
"centralindia",
27+
"eastasia",
28+
"japaneast",
29+
"brazilsouth",
30+
"asia",
31+
"asiapacific",
32+
"australia",
33+
"brazil",
34+
"india",
35+
"japan",
36+
"southafrica",
37+
"switzerland",
38+
"uae",
39+
], var.location)
40+
error_message = "Invalid location!"
41+
}
42+
}
43+
44+
variable "instance_type" {
45+
description = "What instance type should your workspace use?"
46+
default = "Standard_B4ms"
47+
validation {
48+
condition = contains([
49+
"Standard_B1ms",
50+
"Standard_B2ms",
51+
"Standard_B4ms",
52+
"Standard_B8ms",
53+
"Standard_B12ms",
54+
"Standard_B16ms",
55+
"Standard_D2as_v5",
56+
"Standard_D4as_v5",
57+
"Standard_D8as_v5",
58+
"Standard_D16as_v5",
59+
"Standard_D32as_v5",
60+
], var.instance_type)
61+
error_message = "Invalid instance type!"
62+
}
63+
}
64+
65+
variable "home_size" {
66+
type = number
67+
description = "How large would you like your home volume to be (in GB)?"
68+
default = 20
69+
validation {
70+
condition = var.home_size >= 1
71+
error_message = "Value must be greater than or equal to 1."
72+
}
73+
}
74+
75+
provider "azurerm" {
76+
features {}
77+
}
78+
79+
data "coder_workspace" "me" {
80+
}
81+
82+
resource "coder_agent" "main" {
83+
arch = "amd64"
84+
os = "linux"
85+
auth = "azure-instance-identity"
86+
}
87+
88+
locals {
89+
prefix = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}"
90+
91+
userdata = templatefile("cloud-config.yaml.tftpl", {
92+
username = lower(substr(data.coder_workspace.me.owner, 0, 32))
93+
init_script = base64encode(coder_agent.main.init_script)
94+
hostname = lower(data.coder_workspace.me.name)
95+
})
96+
}
97+
98+
resource "azurerm_resource_group" "main" {
99+
name = "${local.prefix}-resources"
100+
location = var.location
101+
102+
tags = {
103+
Coder_Provisioned = "true"
104+
}
105+
}
106+
107+
// Uncomment here and in the azurerm_network_interface resource to obtain a public IP
108+
#resource "azurerm_public_ip" "main" {
109+
# name = "publicip"
110+
# resource_group_name = azurerm_resource_group.main.name
111+
# location = azurerm_resource_group.main.location
112+
# allocation_method = "Static"
113+
#
114+
# tags = {
115+
# Coder_Provisioned = "true"
116+
# }
117+
#}
118+
119+
resource "azurerm_virtual_network" "main" {
120+
name = "network"
121+
address_space = ["10.0.0.0/24"]
122+
location = azurerm_resource_group.main.location
123+
resource_group_name = azurerm_resource_group.main.name
124+
125+
tags = {
126+
Coder_Provisioned = "true"
127+
}
128+
}
129+
130+
resource "azurerm_subnet" "internal" {
131+
name = "internal"
132+
resource_group_name = azurerm_resource_group.main.name
133+
virtual_network_name = azurerm_virtual_network.main.name
134+
address_prefixes = ["10.0.0.0/29"]
135+
}
136+
137+
resource "azurerm_network_interface" "main" {
138+
name = "nic"
139+
resource_group_name = azurerm_resource_group.main.name
140+
location = azurerm_resource_group.main.location
141+
142+
ip_configuration {
143+
name = "internal"
144+
subnet_id = azurerm_subnet.internal.id
145+
private_ip_address_allocation = "Dynamic"
146+
// Uncomment for public IP address as well as azurerm_public_ip resource above
147+
//public_ip_address_id = azurerm_public_ip.main.id
148+
}
149+
150+
tags = {
151+
Coder_Provisioned = "true"
152+
}
153+
}
154+
155+
resource "azurerm_managed_disk" "home" {
156+
create_option = "Empty"
157+
location = azurerm_resource_group.main.location
158+
name = "home"
159+
resource_group_name = azurerm_resource_group.main.name
160+
storage_account_type = "StandardSSD_LRS"
161+
disk_size_gb = var.home_size
162+
}
163+
164+
// azurerm requires an SSH key (or password) for an admin user or it won't start a VM. However,
165+
// cloud-init overwrites this anyway, so we'll just use a dummy SSH key.
166+
resource "tls_private_key" "dummy" {
167+
algorithm = "RSA"
168+
rsa_bits = 4096
169+
}
170+
171+
resource "azurerm_linux_virtual_machine" "main" {
172+
count = data.coder_workspace.me.transition == "start" ? 1 : 0
173+
name = "vm"
174+
resource_group_name = azurerm_resource_group.main.name
175+
location = azurerm_resource_group.main.location
176+
size = var.instance_type
177+
// cloud-init overwrites this, so the value here doesn't matter
178+
admin_username = "adminuser"
179+
admin_ssh_key {
180+
public_key = tls_private_key.dummy.public_key_openssh
181+
username = "adminuser"
182+
}
183+
184+
network_interface_ids = [
185+
azurerm_network_interface.main.id,
186+
]
187+
computer_name = lower(data.coder_workspace.me.name)
188+
os_disk {
189+
caching = "ReadWrite"
190+
storage_account_type = "Standard_LRS"
191+
}
192+
source_image_reference {
193+
publisher = "Canonical"
194+
offer = "0001-com-ubuntu-server-focal"
195+
sku = "20_04-lts-gen2"
196+
version = "latest"
197+
}
198+
user_data = base64encode(local.userdata)
199+
200+
tags = {
201+
Coder_Provisioned = "true"
202+
}
203+
}
204+
205+
resource "azurerm_virtual_machine_data_disk_attachment" "home" {
206+
count = data.coder_workspace.me.transition == "start" ? 1 : 0
207+
managed_disk_id = azurerm_managed_disk.home.id
208+
virtual_machine_id = azurerm_linux_virtual_machine.main[0].id
209+
lun = "10"
210+
caching = "ReadWrite"
211+
}

0 commit comments

Comments
 (0)