> ## Content Index
> Fetch the complete content index at: https://www.azurebrasil.cloud/llms.txt
> Use this file to discover other available public pages before exploring further.

# Infraestrutura como Código no Azure com Pulumi: deploy de VMs com NGINX e MySQL
- URL: https://www.azurebrasil.cloud/blog/infraestrutura-como-codigo-no-azure-com-pulumi-deploy-de-vms-com-nginx-e-mysql/
- Published: 2025-09-29T19:29:21.000Z
- Updated: 2025-10-03T14:20:36.000Z
- Author: Ricardo Martins

### Introdução

O Pulumi é uma alternativa moderna ao ARM, Bicep ou Terraform para provisionar infraestrutura no Azure. A grande vantagem é que você pode escrever sua infraestrutura com linguagens como **TypeScript**, **Python** ou **C#**, aproveitando:

- Intellisense, testes, controle de fluxo
- Reutilização de código
- Integração com bibliotecas do ecossistema
- Deploy automatizado com CI/CD

Neste exemplo prático, vamos criar:

- Um **Resource Group**
- Duas **VMs Linux** no Azure:
  - Uma rodando o **NGINX**
  - Outra com o **MySQL Server**
- Configuração de **networking** (VNet + Subnet + IP público + NSG)
- E tudo usando **Pulumi com TypeScript**

### Pré-requisitos

- Conta no Azure com permissão de contributor
- Node.js instalado
- Pulumi CLI instalado:

```bash
curl -fsSL https://get.pulumi.com | sh

```

- Login no Azure via CLI:

```bash
az login

```

### Estrutura do projeto

```bash
azure-pulumi-infra/
├── Pulumi.yaml
├── Pulumi.dev.yaml
├── index.ts
├── package.json
└── tsconfig.json

```

### Inicializando o projeto

```bash
pulumi new azure-native-typescript
```

Escolha um nome para o projeto e a stack (ex: dev)

### Código completo (index.ts)

```typescript
import * as azure from "@pulumi/azure-native";

// 1. Resource Group
const rg = new azure.resources.ResourceGroup("app-rg", {
    location: "brazilsouth",
});

// 2. Virtual Network + Subnet
const vnet = new azure.network.VirtualNetwork("vnet", {
    resourceGroupName: rg.name,
    location: rg.location,
    addressSpace: { addressPrefixes: ["10.0.0.0/16"] },
    subnets: [{ name: "default", addressPrefix: "10.0.1.0/24" }],
});

// 3. Public IPs
const publicIpNginx = new azure.network.PublicIPAddress("nginx-ip", {
    resourceGroupName: rg.name,
    location: rg.location,
    publicIPAllocationMethod: "Dynamic",
});

const publicIpMySQL = new azure.network.PublicIPAddress("mysql-ip", {
    resourceGroupName: rg.name,
    location: rg.location,
    publicIPAllocationMethod: "Dynamic",
});

// 4. Network Interface (NIC)
const nicNginx = new azure.network.NetworkInterface("nic-nginx", {
    resourceGroupName: rg.name,
    location: rg.location,
    ipConfigurations: [{
        name: "ipcfg",
        subnet: { id: vnet.subnets.apply(s => s[0].id!) },
        privateIPAllocationMethod: "Dynamic",
        publicIPAddress: { id: publicIpNginx.id },
    }],
});

const nicMySQL = new azure.network.NetworkInterface("nic-mysql", {
    resourceGroupName: rg.name,
    location: rg.location,
    ipConfigurations: [{
        name: "ipcfg",
        subnet: { id: vnet.subnets.apply(s => s[0].id!) },
        privateIPAllocationMethod: "Dynamic",
        publicIPAddress: { id: publicIpMySQL.id },
    }],
});

// 5. VM com NGINX
const vmNginx = new azure.compute.VirtualMachine("vm-nginx", {
    resourceGroupName: rg.name,
    location: rg.location,
    networkProfile: { networkInterfaces: [{ id: nicNginx.id }] },
    hardwareProfile: { vmSize: "Standard_B1s" },
    osProfile: {
        computerName: "nginxvm",
        adminUsername: "azureuser",
        adminPassword: "SenhaForte@123", // evite isso em prod, use secrets!
        customData: Buffer.from(`#!/bin/bash
        sudo apt-get update
        sudo apt-get install -y nginx
        sudo systemctl start nginx`).toString("base64"),
    },
    storageProfile: {
        osDisk: {
            name: "osdisk-nginx",
            createOption: "FromImage",
        },
        imageReference: {
            publisher: "Canonical",
            offer: "UbuntuServer",
            sku: "18.04-LTS",
            version: "latest",
        },
    },
});

// 6. VM com MySQL
const vmMySQL = new azure.compute.VirtualMachine("vm-mysql", {
    resourceGroupName: rg.name,
    location: rg.location,
    networkProfile: { networkInterfaces: [{ id: nicMySQL.id }] },
    hardwareProfile: { vmSize: "Standard_B1s" },
    osProfile: {
        computerName: "mysqlvm",
        adminUsername: "azureuser",
        adminPassword: "SenhaForte@123",
        customData: Buffer.from(`#!/bin/bash
        sudo apt-get update
        sudo apt-get install -y mysql-server
        sudo systemctl start mysql`).toString("base64"),
    },
    storageProfile: {
        osDisk: {
            name: "osdisk-mysql",
            createOption: "FromImage",
        },
        imageReference: {
            publisher: "Canonical",
            offer: "UbuntuServer",
            sku: "18.04-LTS",
            version: "latest",
        },
    },
});

// 7. Outputs
export const ipNginx = publicIpNginx.ipAddress;
export const ipMySQL = publicIpMySQL.ipAddress;

```

### Deploy da infraestrutura

```bash
npm install
pulumi up

```

### Para destruir o ambiente:

```bash
pulumi destroy
  
```

### Boas práticas

| Prática                                           | Justificativa                |
| ------------------------------------------------- | ---------------------------- |
| Use Pulumi Config para senhas e valores sensíveis | Evita hardcoded              |
| Separe lógica em arquivos por recurso             | Melhor manutenção            |
| Use autoTags, stacks, e environments              | Para ambientes dev/prod/test |
| Integre com GitHub Actions ou Azure Pipelines     | CI/CD de IaC completo        |
| Combine com Azure Policy e Key Vault              | Governança e segurança       |

### Referências

- [Pulumi para Azure](https://www.pulumi.com/registry/packages/azure-native/?ref=azurebrasil.cloud)
- [Exemplos Pulumi no GitHub](https://github.com/pulumi/examples?ref=azurebrasil.cloud)
- [Pulumi CLI Docs](https://www.pulumi.com/docs/iac/cli/?ref=azurebrasil.cloud)

### Conclusão

Pulumi traz agilidade e flexibilidade para equipes de infraestrutura modernas que desejam integrar IaC com as práticas de desenvolvimento. Ao usar **TypeScript ou Python**, a curva de aprendizado se torna mais acessível e os recursos do Azure podem ser definidos de forma programática e escalável.