{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "title": "Enterprise PII Guardrails 1-Click Azure VM Deployment",
    "description": "Launches a hardened, production-ready Ubuntu VM preconfigured with an active evaluation license (10,000 requests included), persistent encrypted storage, and automated systemd container management.",
    "author": "Enterprise PII Guardrails Team",
    "dateUpdated": "2026-09-18"
  },
  "parameters": {
    "vmName": {
      "type": "string",
      "defaultValue": "piiguardrail-vm",
      "metadata": {
        "description": "Name for the Virtual Machine and associated network resources."
      }
    },
    "adminUsername": {
      "type": "string",
      "defaultValue": "azureuser",
      "metadata": {
        "description": "Administrator username for logging into the Ubuntu Virtual Machine via SSH."
      }
    },
    "authenticationType": {
      "type": "string",
      "defaultValue": "password",
      "allowedValues": [
        "password",
        "sshPublicKey"
      ],
      "metadata": {
        "description": "Type of authentication to use for SSH access to the Virtual Machine."
      }
    },
    "adminPasswordOrKey": {
      "type": "securestring",
      "metadata": {
        "description": "SSH Public Key (e.g. 'ssh-rsa AAAAB3NzaC1yc2E...') or Administrator Password for the VM. Passwords must be 12-72 characters with upper, lower, digit, and special characters."
      }
    },
    "adminStudioPassword": {
      "type": "securestring",
      "minLength": 8,
      "metadata": {
        "description": "Master administrative password to access the Enterprise PII Guardrails Studio Web UI (username: admin). Must be at least 8 characters."
      }
    },
    "allowedInboundCIDR": {
      "type": "string",
      "defaultValue": "*",
      "metadata": {
        "description": "Source IPv4 address or CIDR range allowed to connect to Studio Web UI (Port 8000) and SSH (Port 22). Use '*' to allow all, or restrict to your corporate IP range (e.g., '203.0.113.25/32')."
      }
    },
    "trialLicenseKey": {
      "type": "string",
      "defaultValue": "ED4-AQAGWNU7FAAAAJYQ-AAAAAAAAAAAAAKFI-VXRAU4YPAHXPW6JD-CRJIDR5NFJ4ITZA2-ICFCAEEV7OYVNWO7-JDSSZ5RMIUNDHULQ-DMZPYP4ICOFTJF53-AMKICAI6R57R4XM4-QYR4UGEQ4ZTP3DAM",
      "metadata": {
        "description": "Preconfigured evaluation license key (10,000 requests quota included). Leave as default to evaluate immediately, or replace with your commercial production key."
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "eastus2",
      "allowedValues": [
        "eastus2",
        "centralus",
        "westus2",
        "westeurope",
        "northeurope",
        "southeastasia",
        "centralindia"
      ],
      "metadata": {
        "description": "Azure region for the VM and network resources. East US 2 is recommended for guaranteed compute capacity."
      }
    },
    "companyName": {
      "type": "string",
      "defaultValue": "Azure Demo",
      "metadata": {
        "description": "Company or organization name for white-labeling the Web Studio and Reports (Default: 'Azure Demo')."
      }
    },
    "brandLogoURL": {
      "type": "string",
      "defaultValue": "/ui/logo.png",
      "metadata": {
        "description": "HTTPS URL or local path to company logo image (Default: '/ui/logo.png')."
      }
    }
  },
  "variables": {
    "nicName": "[concat(parameters('vmName'), '-nic')]",
    "addressPrefix": "10.0.0.0/16",
    "subnetName": "default",
    "subnetPrefix": "10.0.0.0/24",
    "publicIPAddressName": "[concat(parameters('vmName'), '-ip')]",
    "virtualNetworkName": "[concat(parameters('vmName'), '-vnet')]",
    "networkSecurityGroupName": "[concat(parameters('vmName'), '-nsg')]",
    "linuxConfigurationSSH": {
      "disablePasswordAuthentication": true,
      "ssh": {
        "publicKeys": [
          {
            "path": "[concat('/home/', parameters('adminUsername'), '/.ssh/authorized_keys')]",
            "keyData": "[parameters('adminPasswordOrKey')]"
          }
        ]
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2023-04-01",
      "name": "[variables('publicIPAddressName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard"
      },
      "properties": {
        "publicIPAllocationMethod": "Static"
      },
      "tags": {
        "Application": "EnterprisePIIGuardrails"
      }
    },
    {
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2023-04-01",
      "name": "[variables('networkSecurityGroupName')]",
      "location": "[parameters('location')]",
      "properties": {
        "securityRules": [
          {
            "name": "Allow-HTTP-8000",
            "properties": {
              "priority": 1000,
              "protocol": "Tcp",
              "access": "Allow",
              "direction": "Inbound",
              "sourceAddressPrefix": "[parameters('allowedInboundCIDR')]",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "8000"
            }
          },
          {
            "name": "Allow-SSH-22",
            "properties": {
              "priority": 1010,
              "protocol": "Tcp",
              "access": "Allow",
              "direction": "Inbound",
              "sourceAddressPrefix": "[parameters('allowedInboundCIDR')]",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "22"
            }
          }
        ]
      },
      "tags": {
        "Application": "EnterprisePIIGuardrails"
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2023-04-01",
      "name": "[variables('virtualNetworkName')]",
      "location": "[parameters('location')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('addressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('subnetName')]",
            "properties": {
              "addressPrefix": "[variables('subnetPrefix')]"
            }
          }
        ]
      },
      "tags": {
        "Application": "EnterprisePIIGuardrails"
      }
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2023-04-01",
      "name": "[variables('nicName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]",
        "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]",
        "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]"
              },
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]"
              }
            }
          }
        ],
        "networkSecurityGroup": {
          "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
        }
      },
      "tags": {
        "Application": "EnterprisePIIGuardrails"
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2023-03-01",
      "name": "[parameters('vmName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "Standard_D2s_v7"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "Canonical",
            "offer": "ubuntu-24_04-lts",
            "sku": "server",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "FromImage",
            "managedDisk": {
              "storageAccountType": "Premium_LRS"
            },
            "diskSizeGB": 30
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
            }
          ]
        },
        "osProfile": {
          "computerName": "[parameters('vmName')]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[if(equals(parameters('authenticationType'), 'password'), parameters('adminPasswordOrKey'), json('null'))]",
          "customData": "[base64(concat('#!/bin/bash\nset -e\nexec >> /var/log/customdata.log 2>&1\n\necho \"==========================================================\"\necho \"Initializing Enterprise PII Guardrails 1-Click Environment\"\necho \"==========================================================\"\n\nexport DEBIAN_FRONTEND=noninteractive\napt-get update -y\napt-get install -y docker.io curl openssl\nsystemctl enable --now docker\n\nmkdir -p /opt/piiguardrails/data\nchmod 777 /opt/piiguardrails/data\n\nRANDOM_PASSPHRASE=$(openssl rand -hex 16)\n\ncat <<EOF > /etc/piiguardrails.env\nACCEPT_LICENSE=true\nGUI_PASSWORD=', parameters('adminStudioPassword'), '\nSQLCIPHER_PASSPHRASE=$RANDOM_PASSPHRASE\nPRECONFIGURED_LICENSE_KEY=', parameters('trialLicenseKey'), '\nCOMPANY_NAME=', parameters('companyName'), '\nBRAND_LOGO=', parameters('brandLogoURL'), '\nPORT=8000\nAPP_PORT=8000\nAPP_HOST=0.0.0.0\nDATA_DIR=/app/data\nEOF\nchmod 600 /etc/piiguardrails.env\n\ncat <<EOF > /etc/systemd/system/piiguardrail.service\n[Unit]\nDescription=Enterprise PII Guardrails Engine\nAfter=docker.service\nRequires=docker.service\n\n[Service]\nTimeoutStartSec=0\nRestart=always\nRestartSec=10\nExecStartPre=-/usr/bin/docker stop pii-guardrail-app\nExecStartPre=-/usr/bin/docker rm pii-guardrail-app\nExecStartPre=/usr/bin/docker pull piiguardrails/enterprise-pii-guardrail:latest\nExecStart=/usr/bin/docker run --name pii-guardrail-app -p 8000:8000 -v /opt/piiguardrails/data:/app/data --env-file /etc/piiguardrails.env piiguardrails/enterprise-pii-guardrail:latest\nExecStop=/usr/bin/docker stop pii-guardrail-app\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\nsystemctl daemon-reload\nsystemctl enable --now piiguardrail.service\n\necho \"==========================================================\"\necho \"Enterprise PII Guardrails container launched successfully!\"\necho \"==========================================================\"\n'))]"
        }
      },
      "tags": {
        "Application": "EnterprisePIIGuardrails"
      }
    }
  ],
  "outputs": {
    "webUIURL": {
      "type": "string",
      "value": "[concat('http://', reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).ipAddress, ':8000')]"
    },
    "apiDocsURL": {
      "type": "string",
      "value": "[concat('http://', reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).ipAddress, ':8000/docs')]"
    },
    "publicIPAddress": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).ipAddress]"
    },
    "sshCommand": {
      "type": "string",
      "value": "[concat('ssh ', parameters('adminUsername'), '@', reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).ipAddress)]"
    },
    "hardwareIDGuide": {
      "type": "string",
      "value": "[concat('Log into the Studio Web UI at http://', reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))).ipAddress, ':8000 with username admin. Navigate to the Licensing tab to retrieve your persistent Server Hardware ID. Send this ID to piiguardrails@gmail.com for a permanent node-locked production key.')]"
    }
  }
}