Efficiently Setting Up WildFly on Azure Using Cloud Init and Bicep

In today's fast-paced digital landscape, the ability to swiftly spin up pre-configured infrastructure is not just beneficial—it's essential. This speed facilitates quicker deployment of new features and improvements, contributing significantly to the agility of development teams. Moreover, consistency in infrastructure deployments across various environments like production, development, and user acceptance testing ensures adherence to organizational policies and naming conventions. This blog post details a robust method using Cloud Init for initial virtual machine configuration and Bicep for infrastructure deployment on Azure.

Prerequisites:

To follow this guide, ensure you have:

  • An active Azure subscription
  • Azure CLI installed on your machine
  • Basic familiarity with Cloud Init configurations

Configuring the Virtual Machine with Cloud Init

Cloud Init is a versatile tool used to customize cloud instances. It executes predefined scripts or commands during the first boot of any cloud instance, which simplifies the setup process and ensures that all instances start with an identical configuration.

  1. In your project directory, create a new file named cloudinit.yml.
  2. Enter the following script in your cloudinit.yml file to install WildFly and its prerequisites:
#cloud-config

# Manage package updates and installations
package_update: true
package_upgrade: true
packages:
  - openjdk-17-jdk

# Custom commands for setting up WildFly
runcmd:
  # Download and extract WildFly
  - wget https://github.com/wildfly/wildfly/releases/download/26.1.3.Final/wildfly-26.1.3.Final.tar.gz -O /tmp/wildfly.tar.gz
  - tar -xf /tmp/wildfly.tar.gz -C /opt
  - mv /opt/wildfly-*Final /opt/wildfly

  # Create and configure WildFly user
  - groupadd -r wildfly
  - useradd -r -g wildfly -d /opt/wildfly -s /sbin/nologin wildfly
  - chown -RH wildfly:wildfly /opt/wildfly

  # Configure WildFly installation
  - mkdir -p /etc/wildfly
  - cp /opt/wildfly/docs/contrib/scripts/systemd/wildfly.conf /etc/wildfly/
  - cp /opt/wildfly/docs/contrib/scripts/systemd/wildfly.service /etc/systemd/system/
  - cp /opt/wildfly/docs/contrib/scripts/systemd/launch.sh /opt/wildfly/bin/
  - chmod +x /opt/wildfly/bin/*.sh

  # Enable and start the WildFly service
  - systemctl daemon-reload
  - systemctl enable wildfly
  - systemctl start wildfly

This configuration automatically installs Java, downloads WildFly and enables the service.

Deploying Infrastructure with Azure Bicep

Azure Bicep simplifies the declaration and deployment of Azure resources using a declarative syntax that's easier to read and write compared to traditional ARM templates.

  1. Create a new file named main.bicep in your project directory.
  2. Populate it with the necessary Bicep code to provision an Azure Virtual Machine configured to use your cloudinit.yml. Example snippet:
param appName string = 'wildflydemo'
param adminUsername string = 'user'
param sshKey string
param location string = resourceGroup().location

var cloudInit = base64(loadTextContent('cloudinit.yml'))

module network 'br:latzo.azurecr.io/bicep/modules/network:vnet-snet' = {
  name: 'networkDeployment'
  params: {
    instanceNumber: 001
    environment: 'dev'
    location: location
    addressPrefix: '10.1.0.0/16'
    subnetAddressPrefix: '10.1.0.0/24'
  }
}

module vm 'br:latzo.azurecr.io/bicep/modules/compute:ubuntu-pip' = {
  name: 'vmDeployment'
  params: {
    environment: 'dev'
    instanceNumber: 001
    location: location
    adminPasswordOrKey: sshKey
    adminUsername: adminUsername
    appName: appName
    subnetId: network.outputs.subnetId
    ubuntuOSVersion: 'Ubuntu-2204'
    vmSize: 'Standard_D2s_v3'
    encodedCloudInit: cloudInit
  }
}

output sshCommand string = vm.outputs.sshCommand

Key Components

  1. Parameters and Variables:
    • appName: Identifies the application, facilitating resource tagging.
    • sshKey: Ensures secure VM access via SSH.
    • cloudInit: Encodes initialization settings for the VM from cloudinit.yml.
  2. Network Module:
    • Uses my public custom Bicep module to set up a VNet and subnet with specified IP address ranges, aligning deployment to the development environment.
  3. VM Module:
    • Deploys an Ubuntu VM using my public Bicep module, configured with a public IP, leveraging parameters like ubuntuOSVersion for OS compatibility and vmSize for resource allocation.
    • Utilizes the subnet ID from the network module and the encoded Cloud Init script for initial VM setup.
  4. Output:
    • Provides an SSH command for immediate VM access post-deployment, enhancing usability.

Deploying the Configuration

To deploy your infrastructure using Azure CLI, execute the following command in your terminal:

az deployment group create \
  --name ExampleDeployment \
  --resource-group <YourResourceGroup> \
  --template-file ./main.bicep \
  --parameters appName='wildflydemo' adminUsername='user' sshKey='<YourSSHKey>'

This command initiates the deployment of your virtual machine along with the custom configurations defined in your Cloud Init and Bicep files.

Check the URL you'll get from the Bicep Outputs. For example:

http://wildflydemo-n3yaznwmsxome.switzerlandnorth.cloudapp.azure.com:8080

If you see the default welcoming screen of WildFly like below, congratulations, you successfully set up WildFly in Azure with Bicep and Cloud Init.

Utilizing Cloud Init and Bicep for deploying WildFly on Azure not only streamlines the process but also guarantees consistency and reliability across different deployment stages. This approach ensures that infrastructure setups are not only quick but also aligned with best practices and organizational standards.