RabbitMQ: How to move configuration, data and log directories on Windows

A good part of my job has to do with enterprise messaging. When a piece of data -a message- needs to be sent from, say, an invoicing system to an accounting system and then to a customer relationship system and then to the customer portal… it has to navigate treacherous waters.

Avast ye bilge-sucking scurvy dogs! A JSON message from accounting says they hornswaggled 1000 doubloons! Aarrr!!!

So we need to make sure that whatever happens, say if a system is overloaded while receiving the message, the message will not be lost.

A key component in this is message queues (MQ), like RabbitMQ. An MQ plays the middleman; it receives a message from a system and stores it reliably until the next system has confirmed that it picked it up.

My daily duties includes setting up, configuring and maintaining a few RabbitMQ instances. It works great! Honestly, so far -for loads up to a couple of 100s of messages per second- I haven’t even had the need to do any serious tuning.

But one thing that annoys me on Windows is that, after installation, the location of everything except the binaries -configuration, data, logs- is under the profile dir of the user (C:\Users\USERNAME\AppData\Roaming\RabbitMQ) that did the installation, even if the service runs as LocalSystem. Not very good, is it?

Therefore I’ve created this script to help me. The easiest way to use it is run it before you install RabbitMQ. Change the directories in this part and run it from an admin powershell:

# ========== Customize here ==========
$BaseLocation = "C:\mqroot\conf"
$DbLocation = "C:\mqroot\db"
$LogLocation = "C:\mqroot\log"
# ====================================

Then just reboot and run the installation normally; when it starts, RabbitMQ will use the directories you specified.

You can also do it after installation, if you have a running instance and want to move it. In this case do the following (you can find these steps also in the script):

  1. Stop the RabbitMQ service.
  2. From Task Manager, kill the epmd.exe process if present.
  3. Go to the existing base dir (usually C:\Users\USERNAME\AppData\Roaming\RabbitMQ)
    and move it somewhere else (say, C:\temp).
  4. Run this script (don’t forget to change the paths).
  5. Reboot the machine
  6. Run the “RabbitMQ Service (re)install” (from Start Menu).
  7. Copy the contents of the old log dir to $LogLocation.
  8. Copy the contents of the old db dir to $DbLocation.
  9. Copy the files on the root of the old base dir (e.g. advanced.config, enabled_plugins) to $BaseLocation.
  10. Start the RabbitMQ service.

Here’s the script. Have fun 🙂

#
# Source: DotJim blog (http://dandraka.com)
# Jim Andrakakis, March 2021
#

# What this script does is:
#   1. Creates the directories where the configuration, queue data and logs will be stored.
#   2. Downloads a sample configuration file (it's necessary to have one).
#   3. Sets the necessary environment variables.

# If you're doing this before installation: 
# Just run it, reboot and then install RabbitMQ.

# If you're doing this after installation, i.e. if you have a 
# running service and want to move its files:
#   1. Stop the RabbitMQ service
#   2. From Task Manager, kill the epmd.exe process if present
#   3. Go to the existing base dir (usually C:\Users\USERNAME\AppData\Roaming\RabbitMQ)
#      and move it somewhere else (say, C:\temp).
#   4. Run this script.
#   5. Reboot the machine
#   6. Run the "RabbitMQ Service (re)install" (from Start Menu)
#   7. Copy the contents of the old log dir to $LogLocation.
#   8. Copy the contents of the old db dir to $DbLocation.
#   9. Copy the files on the root of the old base dir (e.g. advanced.config, enabled_plugins) 
#      to $BaseLocation.
#   10. Start the RabbitMQ service.

# ========== Customize here ==========

$BaseLocation = "C:\mqroot\conf"
$DbLocation = "C:\mqroot\db"
$LogLocation = "C:\mqroot\log"

# ====================================

$exampleConfUrl = "https://raw.githubusercontent.com/rabbitmq/rabbitmq-server/master/deps/rabbit/docs/rabbitmq.conf.example"

Clear-Host
$ErrorActionPreference = "Stop"

$dirList = @($BaseLocation, $DbLocation, $LogLocation)
foreach($dir in $dirList) {
    if (-not (Test-Path -Path $dir)) {
        New-Item -ItemType Directory -Path $dir
    }
}

# If this fails (e.g. because there's a firewall) you have to download the file 
# from $exampleConfUrl manually and copy it to $BaseLocation\rabbitmq.conf
try {
    Invoke-WebRequest -Uri $exampleConfUrl -OutFile ([System.IO.Path]::Combine($BaseLocation, "rabbitmq.conf"))
}
catch {
    Write-Host "(!) Download of conf file failed. Please download the file manually and copy it to $BaseLocation\rabbitmq.conf"
    Write-Host "(!) Url: $exampleConfUrl"
}

&setx /M RABBITMQ_BASE $BaseLocation
&setx /M RABBITMQ_CONFIG_FILE "$BaseLocation\rabbitmq"
&setx /M RABBITMQ_MNESIA_BASE $DbLocation
&setx /M RABBITMQ_LOG_BASE $LogLocation

Write-Host "Finished. Now you can install RabbitMQ."

16 thoughts on “RabbitMQ: How to move configuration, data and log directories on Windows”

  1. Have you ever considered running RabbitMQ as a docker container in Windows to avoid configuration clutter under certain directories?

    1. I did that when I was experimenting, on my dev machine. But my shop doesn’t support dockerized apps for production (yet; they’re working on it) so it have to run it “normally”, installed on a server. When I installed on a test server, I discovered in horror that the queue staorage was under the user profile.

  2. Thank you! Rabbit does not start because of cyrillic symbols in my profile. You save me lots of time!

    1. As a rule of thumb, certain programs I do not install in default locations, rather in C:\P\Program_Name (all English ASCII and no spaces) to avoid weird issues just in case.

      1. Same here 🙂 If there’s no installer that defaults to, say, Program Files, I use C:\app.

  3. Hey Jim I have a RabbitMQ log file on a Windows server that has grown to nearly 100GB and is filling up my OS drive. Am I right in thinking that I can’t just delete the log file? If so can I edit/truncate it? If not, how do I just change the location of the log file so I can then delete the old one? I should add that this is a server I have inherited and I am a complete RabbitMQ novice.

    1. Hi Peter! That’s not a great place to find yourself in, but take it as a chance to learn 😊

      What log file is this? You can take a look without opening the whole behemoth using powershell:

      $path = 'C:\somepath\somelogfile.log'
      $pathOut = 'c:\temp\sneakpeak.txt'
      $numBytes = 10000
      $bytes = Get-Content -Path $path -Encoding byte -TotalCount $numBytes
      $str = [System.Text.Encoding]::UTF8.GetString($bytes)
      Out-File -FilePath $pathOut -InputObject $str
      

      Change $path, $pathOut and $numBytes to suit you. As it is, you’ll get c:\temp\sneakpeak.txt containing the first 10KB of the file, so you’ll get an idea of what is in there.

      If it’s a regular log file (the ones humans are supposed to look at in case of problems) what I would do is 1) stop the service 2) use 7zip to zip it 3) store it somewhere in case it’s needed and 4) change the log file location and 5) start the service again.

      Changing the log location is described in https://www.rabbitmq.com/relocate.html , but you can also use my script above.

      Hope that helps! Let me know how it went.

      Jim

      1. Hey Jim, thanks for getting back so quickly. I ran your sneakpeek script but it failed as follows:

        PS C:\Windows\system32> $path = ‘C:\Users\MattF\AppData\Roaming\RabbitMQ\rabbit@prodweb-0.log’
        PS C:\Windows\system32> $pathOut = ‘c:\temp\sneakpeak.txt’
        PS C:\Windows\system32> $numBytes = 10000
        PS C:\Windows\system32> $bytes = Get-Content -Path $path -Encoding byte -TotalCount $numBytes
        Get-Content : Cannot find path ‘C:\Users\MattF\AppData\Roaming\RabbitMQ\rabbit@prodweb-0.log’ because it does not
        exist.
        At line:1 char:10
        + $bytes = Get-Content -Path $path -Encoding byte -TotalCount $numBytes
        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : ObjectNotFound: (C:\Users\MattF\…t@prodweb-0.log:String) [Get-Content], ItemNotFoundEx
        ception
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

        PS C:\Windows\system32> $str = [System.Text.Encoding]::UTF8.GetString($bytes)
        Exception calling “GetString” with “1” argument(s): “Array cannot be null.
        Parameter name: bytes”
        At line:1 char:1
        + $str = [System.Text.Encoding]::UTF8.GetString($bytes)
        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : ArgumentNullException

        PS C:\Windows\system32> Out-File -FilePath $pathOut -InputObject $str

        I know there is nothing wrong with the path as it would have failed at the first step wouldn’t it?

  4. No 😊 the 1st line just declares a variable. It’s the Get-Content where the file is read, and you can see that it fails (“ObjectNotFound: (C:\Users\MattF\…t@prodweb-0.log:String) [Get-Content]”). Can you double-check the path?

    1. Also, it usually helps if you open Powershell ISE (the one with the text editor on top), paste the code there and save it as .ps1. Then you can also set breakpoints and see what the problem is.

      1. Hey Jim I ran the exact same script today and it worked! Don’t ask me why. The information generated in the text file is from 2017 and therefore not a great deal of use. Would there be any way of grabbing the end of the log as opposed to the beginning? Thanks again for your help.

    1. Hi! Just saw your message 🙂 Sure, there’s the -tail option. Just go:

      # see the last 50 lines
      Get-Content 'C:\somepath\somelogfile.log'  -tail 50 | Out-File -FilePath 'C:\temp\mylogtail.txt'
      

Leave a comment