Introducing: terraform-azurerm-jmusicbot v1.1.0 – Cost Savings, Azure Function, and Linux Service Creation
The first version of tf-jdiscord module was just okay.
I had to manually deploy it to Azure whenever someone in my Discord wanted to play a song or when I was in the mood for some background music. We’re pretty big on music, so that ended up being a frequent task—over 50 manual deployments in the last year alone. Needless to say, the constant cycle of applying and destroying the module got old fast.
The real issue arose when I’d forget to run terraform destroy
after logging off for the night. Leaving the bot’s server active in Azure led to unnecessary charges, and it happened more times than I’d care to admit. Each instance where I slipped up and let the bot run idle meant extra, unplanned costs, highlighting the need for a change to avoid such wasteful mistakes in the future.
Introducing v1.1.0
https://registry.terraform.io/modules/RCFromCLE/jmusicbot/azure/latest
To address this, I’ve upgraded terraform-azurerm-jmusicbot, automating the music bot’s server to spin up based on voice channel activity and allowing the entire solution to live in Azure, no more manaully deploying it on demand. Now, the bot springs to life whenever atleast one user is present in a voice channel (excluding our AFK channel), ensuring our Discord never misses a beat ;).
This post will explore the enhancements made to the module to keep our server’s soundtrack uninterrupted, all while optimizing resource usage and cutting costs. If you want a reliable music bot for your Discord server and an educational Azure-Terraform-Linux-Javascript experience, give this project a shot!
Recap of challenges from version 1.0.0 of the module.
- I had to manually deploy the music bot from my local workstation.
- I’d often forget to destroy the resources which would result in unintended costs.
- I was not always around to start the music bot or I was occupied and couldn’t start it.
To address these challenges, I decided to implement a Linux-based Azure Function to run a JavaScript app, which controls the Discord music bot by starting and stopping its corresponding virtual machine based on voice channel activity. This approach was chosen for several reasons.
First, I’ve been keen on developing a serverless application for some time.
Second, Azure Functions offers a scalable platform that facilitates future application enhancements, unlike alternatives such as Logic App or Power BI, which do not offer the same level of flexibility for expansion.
Additionally, I wanted the ease of creating and deploying directly from VSCode using the Azure extension.
Lastly, my prior experience with the Azure Management SDK for JavaScript, gained through a separate project, was beneficial. The SDK works very well within an Azure Function (I’ve heard), so all these reasons combined made Azure Function the most suitable for this project’s needs.
Deploying the Module
To deploy JMusicBot into Azure, you can include the following module in your existing Terraform configuration:module "jmusicbot" {
source = "RCFromCLE/jmusicbot/azure"
version = "1.1.0"
azure_tenant_id = "your-tenant-id"
sub = "your-subscription-id"
discord_bot_token = "your-discord-bot-token"
general_channel_id = "your-general-channel-id"
afk_channel_id = "your-afk-channel-id"
azure_client_id = "your-service-principal-client-id"
azure_client_secret = "your-service-principal-client-secret"}
Customize the module variables (azure_tenant_id, sub, discord_bot_token, etc.) with your Azure and Discord configurations.
Ensure you have a config.txt file in the same directory as your Terraform configuration,
containing valid values for the token, owner ID, and prefix required by JMusicBot.
Example config.txt:
token = YOUR_DISCORD_BOT_TOKEN
owner = YOUR_DISCORD_OWNER_ID
prefix = "!"
The config.txt file is essential for configuring JMusicBot and should contain valid values for its parameters. In the example above, we have provided placeholders for the Discord bot token, owner ID, and prefix. Ensure it’s located in the root directory of your Terraform configuration.
Be sure to create an SPN and grant it permissions to the subscription or resource group scope where you will deploy this solution.
Deploying the Function App
To deploy the function app jdiscord-function, follow these steps:
Open Visual Studio Code (VSCode): Launch Visual Studio Code on your local machine.
Clone the Repository: Clone the terraform-azure-jmusicbot repository to your local machine. You can do this by opening a terminal in VSCode.
git clone https://github.com/RCFromCLE/terraform-azure-jmusicbot
Navigate to the Function App Location: Once the repository is cloned, navigate to the function directory within your cloned repository. You can do this by opening the cloned repository folder in VSCode’s file explorer and then navigating to the function folder.
Prepare Local Settings: Create a local.settings.json file in the function directory and populate it with the following placeholder values:
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzureWebJobsStorage": "<your-storage-connection-string>",
"DISCORD_BOT_TOKEN": "<your-discord-bot-token>",
"SUBSCRIPTION_ID": "<your-subscription-id>",
"RESOURCE_GROUP_NAME": "<your-resource-group-name>",
"VM_NAME": "<your-vm-name>",
"GENERAL_CHANNEL_ID": "<your-general-channel-id>",
"AFK_CHANNEL_ID": "<your-afk-channel-id>"
}
}
Replace the placeholder values with your actual configurations.
Ensure Azure CLI is Installed and Logged In: Make sure you have the Azure CLI installed on your local machine. If not, you can download and install it from the official website.
Then, log in to the Azure CLI using the following command:
az login
Follow the on-screen instructions to complete the login process.
Deploy Function App: With the function app folder (function) open in VSCode, run the following command in the integrated terminal to publish the function app:
func azure functionapp publish jdiscord-function --publish-local-settings
This command will deploy the function app to Azure using the settings provided in the local.settings.json file.
By following these steps, you can deploy the function app and integrate it with your existing jmusicbot deployment. This function app is crucial for managing the lifecycle of the virtual machine based on activity in your Discord voice channels.
Example of jdiscord-function running successfully when voice users are already present and VM is running.
Example of jdiscord-function running successfully when voice users are online and the VM is deallocated.
Example of jdiscord-function running successfully when no voice users online and the VM is running.
index.js Deeper Dive:
- Function Entry:
- The main function is where everything starts. It’s triggered by a timer and receives context information.
- Discord Client Setup:
- We set up a Discord client using discord.js, a popular library for creating Discord bots in Node.js. It provides powerful features for interacting with Discord servers and users.
- Event Handling:
- We listen for the ready event from the Discord client, indicating successful login and readiness to operate. We also handle any errors that might occur during operation.
- Configuration Retrieval:
- We retrieve configuration details such as Azure subscription information and Discord bot token from environment variables using the dotenv library for managing environment variables in Node.js applications.
- Guild Connection:
- The bot establishes a connection with the Discord server using the Discord client. This allows it to access channels and members within the server.
- Monitoring Voice Channels:
- We use Discord.js to iterate through voice channels in the server, excluding the AFK channel, and count the number of users present in those channels.
- VM Management:
- Based on the activity in the voice channels, we use the @azure/identity and @azure/arm-compute libraries to manage the Azure VM hosting the bot. We start or stop the VM as needed to optimize usage and reduce costs.
- Message to Channel:
- If the VM state changes, we use Discord.js to send a message to the designated Discord channel, informing users of the bot’s status change.
You can view the complete JavaScript code here. This code runs inside our Node.Js function app.
The integration blade of the function shows the trigger and the function code itself. Note: You can only edit this function app via VSCode and deploy it using the above method. You cannot edit it directly through the Azure portal.
Screenshot of resource group where the module has been deployed.
This has been a really fun and educational project for me. I know my friends in our Discord server will find value in this solution so that’s cool! I hope someone out there can find use from this solution.
If you have any questions or need help getting the module deployed hit me up on here or LinkedIn.
Thanks for reading!
-Rudy
Related Links:
https://jmusicbot.com/
https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs?pivots=isolated