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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy