Or: How I spent an entire weekend learning that the hardest part of automating firmware upgrades was convincing two systems to agree on how to say yes.
Tested with: SolarWinds NCM 2026.1.1
Reading time: About 8 minutes
Troubleshooting time: I'd rather not discuss it.
Jump to the recipe button not available (sorry)
For anyone who just wants the working configuration, it's all put together near the bottom of the page. For everyone else, here's how something that should've been straightforward became one of the most ridiculous technical integrations I've ever conducted.
It Started With Simple Firmware Upgrades
I've built automated firmware upgrades in NCM for other network vendors before. The process is very simple, just make the firmware available, build an upgrade template, select the image, execute the operation, and verify the result. So when I started working on FortiGate firmware automation, I wasn't expecting anything particularly unusual.
I figured I'd get the automation running, validate a few upgrade scenarios, and move on to the next part of the project. This was my first mistake.
The FortiGate itself wasn't doing anything strange or unusual, its CLI was behaving as designed. SolarWinds wasn't necessarily misbehaving either. The problem was that the two systems had slightly different expectations about how an the session should answer a question.
Aaaand that tiny difference was about to consume an unreasonable amount of my weekend. Like, quite unreasonable.
First Problem-ish: Getting SolarWinds to Recognize the Firmware
The initial check was simple, just getting Fortinet firmware images recognized by the NCM Firmware Repository. FortiOS firmware files use the .out extension, which wasn't included in the repository's accepted extensions in my environment.
Fortunately, SolarWinds has an advanced configuration setting controlling which firmware file extensions are recognized, and I've adjusted this previously for other vendors as well. After updating that setting, restarting the module engine, and rescanning the repository, the FortiOS images appeared correctly.
Excellent. First issue solved.
At this point, I was still carrying on under the pleasant assumption that I was making normal progress on a straightforward project.
Second Problem: Getting the Image to the Firewall
Next came firmware delivery. NCM has an existing firmware repository and file-staging mechanism, but I encountered timing issues when trying to use its temporary staging location for the FortiGate-initiated transfer. The image existed in the repository, but having it consistently available at the right time through the expected transfer path was becoming unnecessarily complicated.
FortiOS already supports retrieving firmware through FTP. So rather than fight the automated TFTP staging process, I configured a dedicated IIS FTP service with read-only access to the existing NCM firmware repository on my primary server.
That immediately simplified image delivery, and sped it up immensely. The FortiGate could retrieve the firmware directly from the same repository NCM has you pick your image from. More importantly, this preserved the useful parts of NCM's native firmware actions. Engineers could still select the firmware image through NCM, choose their target devices, and run a standard firmware operation. Only the actual image delivery mechanism was different.
The transfer worked.
The firmware downloaded successfully.
Everything looked promising.
Then the FortiGate started asking questions…
-_-
Third Problem: The Firewall Would Like a Word
Anyone familiar with FortiOS firmware upgrades through the CLI has probably encountered something like:
Do you want to continue? (y/n)
A perfectly reasonable question. When you're connected interactively through SSH, answering is simple. Press y. That's it. Just the individual character.
Depending on the firmware versions and upgrade direction, FortiOS often presented additional confirmation prompts or warnings. Which is also reasonable, from a system standpoint. Unfortunately, this was where my reasonably straightforward automation project began developing a cheeky personality.
The problem is, and I'm getting to it, but NCM thinks in commands. FortiOS wants keystrokes. NCM's command execution model is designed around sending commands and recognizing prompts. For an ordinary CLI command, you type the command and press Enter.
Automation platforms typically reproduce that behavior by adding a command terminator. That works beautifully until the remote device is asking for one character rather than an entire command line.
Consider the difference closely with me. An interactive program sends
y
The device receives that character as an affirmative response.
But when I tried issuing multiple responses as separate NCM commands, command terminators entered the interaction.
Conceptually, instead of receiving each confirmation as individual keystrokes, the device was receiving something closer to:
y<Enter>y<Enter>y<Enter>
Those are not equivalent inputs to my paranoid little friend.
You see where I'm going with this? Okay, let's keep going.
FortiOS can receive a y immediately. If an additional Enter follows, that keystroke may arrive after the device has already advanced to the next confirmation. And that can definitely change the outcome.
In my testing, I encountered constant canceled upgrade operations, including Return code -28, as well as sessions that failed to progress correctly. The problem wasn't just what NCM was sending, it was what NCM was sending afterward.
FortiOS wanted a keystroke.
NCM kept treating the response like a command.
Apparently, the firewall wasn't interested in having a civilized conversation. It just wanted unconditional agreement.
The Device-Template Expedition
Naturally, I started deep-diving into how NCM handled interactive prompts. Like, probably more than I'd like to admit. (thank you SolarWinds for your lengthy inclusion of feature documentation)
I explored custom question prompts, RegEx options, command handlers, prompt recognition, and various device-template settings. Basically every combination that made sense. Some combinations made progress, one might get through the first confirmation, only to fail when a second appeared. Another might recognize the prompt but interfere with normal SSH behavior. Others would make it through part of the process, then leave NCM waiting indefinitely like the session just flew right over its head.
It was quite entertaining to discover that the number of confirmations could vary depending on the firmware transition. Forward upgrades didn't always behave exactly like downgrades. Even different testing scenarios could produce slightly different confirmation sequences, like performing an upgrade from my laptop not even asking for a confirmation, and then getting virtually interrogated when doing the same thing from the server. It's kind of like good cop/bad cop behavior, but its just one guy.
You get it, right?
Yeah, you get it.
So, a carefully constructed series of individual responses was not necessarily sufficient here. At this stage, I wasn't really troubleshooting firmware transfer anymore. I was studying the interaction between an SSH automation engine and the input behavior of an interactive CLI.
All because a firewall wanted someone to just press y.
Things Escalated, As You'd Expect
Eventually, I started considering whether the interactive portion of the process should be handled outside NCM entirely just to produce this capability before my deadline. I investigated NCM's firmware-operation data through SWIS. I examined the feasibility of monitoring operation state and using an external service to initiate the FortiGate firmware installation through its REST API.
There were several viable architectural approaches. A service could potentially correlate firmware operations, identify target devices and images, invoke the appropriate FortiGate API operations, track execution, and report outcomes. It would have been an interesting engineering project, but I could also practically feel the future support obligations.
And I kept coming back to one thought: Am I seriously going to have to build a custom orchestration service because I can't get two systems to agree the same way?
The answer was getting dangerously close to a yes. But then something clicked.
The Discovery Nobody Expected
I had spent all this time trying to make NCM recognize each confirmation and send an appropriate response. But what if that entire approach was unnecessary? The FortiGate didn't need separate commands, it needed individual keystrokes, and it was just that the carriage returns were causing trouble because I was treating those questions as individual commands.
So what if I stopped doing that?
What if I could submit the execute restore command normally, then somehow supply a continuous stream of affirmative characters without putting Enter between them? Just enough to get through the needlessly repetitive confirmation process. Not a series of commands, not a complicated prompt-response configuration, just NCM mashing the y key like you do when you're upgrading one of these things.
Come on. You're reading this article. You and I both know we're in the same boat.
Anyway…
I had absolutely no idea whether this would work. But after everything I'd already tried, it seemed worth a quick experiment before I jumped head first into building a custom external service to pair with NCM.
I changed the command structure, ran another test, the firmware downloaded, the first confirmation appeared, all the same as before.
Then the process advanced…
Additional confirmations were handled, and when I was checking to see if it failed, my continuous ping test stopped. The darn thing rebooted.
Yeah.
I just stared at the result after it came back online. Probably because I had also been working on this for over 30 hours.
It actually worked.
There are few feelings in engineering quite like spending an entire weekend researching increasingly complicated solutions, only to accidentally discover that the answer is something so simple that it feels vaguely insulting.
But one successful test obviously wasn't enough. So I ran it again. It worked. I tested another firmware transition. It worked too. I also downgraded the FortiGate. It worked just fine. Then I upgraded it again.
And again.
And again.
By the end of the process, I performed around 150 development and validation attempts, including dozens of successful runs using the final working configuration.
That poor FortiGate has experienced more firmware time travel than any network appliance reasonably should. I'm reasonably certain it no longer knows what year it is.
But, the important part was that the behavior had become idempotent. And the solution was, quite literally, a continuous stream of affirmative responses.
Yes, I linked that word so you could learn what it means. Bite me.
Introducing YaaS
At some point during the resulting exhaustion-enhanced laughter, the technique acquired a name, courtesy of my AI research chatbot, as outlined below:
YaaS: Yes as a Service.
An entirely accidental innovation in enterprise network automation.
YaaS Basic: One affirmative response.
YaaS Professional: Multiple consecutive approvals.
YaaS Enterprise: Uninterrupted affirmative-response delivery for demanding interactive workflows.
Negative responses not supported.
The joke is especially ridiculous because the underlying technique is genuinely useful.
All jokes aside, by keeping the confirmation characters together in one command string, the process entirely avoids inserting command terminators between each y.
FortiOS can consume the individual characters as the interactive prompts occur, and NCM can continue managing the overall firmware operation. No custom orchestration service required, no separate firmware-installation application, and no complicated conditional response engine. Just a surprisingly important distinction between sending commands and sending keystrokes.
There was, however, one more detail to was important to get right.
The Reboot Stage Has a Secret
FortiOS firmware restore commands initiate the installation and resulting reboot itself. Which creates an interesting opportunity in NCM. The firmware upgrade template has one command field for initiating an image installation, and another for rebooting the device afterward.
Ordinarily, those are distinct operations. But in this case, the FortiOS restore command already performs the action that leads to a reboot. So I used NCM's reboot stage to initiate the actual firmware installation, which lets NCM execute the restore command, transition into reboot monitoring, and continue its firmware automation after the device restores.
Technically, we're not telling the FortiGate to reboot through NCM. We're telling it to upgrade itself, which happens to involve rebooting.
There was also a timing wrinkle. During testing, I found that adding a delay between the reboot stage and NCM's first node-up check interfered with the interaction. This appears to be a timing interaction between NCM's firmware automation, prompt and command handling, and the FortiOS confirmation sequence. I haven't independently verified the exact internal mechanism, but after extensive testing, I can say that keeping delay time at zero is an important part of the final working configuration.
And with that, the remaining pieces finally came together.
Working NCM Configuration
For everyone who wished they could click "Jump to Recipe": Welcome. I hope you enjoyed an entire weekend of character development. And if you scrolled past it: Blah.
Let's get into the technicalities.
The following is the final configuration I validated in my environment using SolarWinds NCM 2026.1.1.
This is a tested workaround for the specific interactive behavior, not a claim of universal support across every NCM release, FortiOS version, or hardware model. But we have 20+ FortiGate models, so it's very useful.
Step 1: Allow FortiOS Images in the Firmware Repository
In the SolarWinds Advanced Configuration, locate:
FirmwareRepositoryFileExtensions
Ensure the accepted extensions include .out.
Restart the SolarWinds Orion Module Engine and rescan the repository.
Confirm that the FortiOS image files appear and can be selected.
Step 2: Configure Firmware Delivery
Set up a dedicated FTP service accessible to the managed FortiGates. Doesn't matter where or have to be your firmware repository, it just needs to be reachable.
For this implementation, I used IIS FTP with its root pointed directly at my existing NCM Firmware Repository directory.
Pro Tip: Configure restricted read-only access and any necessary network controls.
The important requirement is that the FortiGate can retrieve the selected firmware image directly from that repository location.
In the NCM firmware upgrade template, configure the storage address to point to the FTP server used for firmware delivery.
The upgrade command will reference it using ${StorageAddress}.
Step 3: Configure the Fortinet Device Template
Add these settings in the NCM Fortinet device template:
<Command Name="UseVirtualPromptForCommands" Value="True"/>
<Command Name="VirtualPrompt" Value="Do you want to continue\? \(y/n\)"/>
This enables virtual-prompt recognition for commands and matches the FortiOS confirmation text.
The virtual prompt doesn't supply any confirmation characters. It influences how NCM recognizes the interactive session state.
Step 4: Configure the Firmware Upgrade Template
The following fields are the important ones.
Upgrade firmware image command:
diagnose sys session stat
It is deliberately a placeholder. This field is required by NCM, but the actual firmware installation is initiated during the reboot stage, because FortiOS initiates its own reboot after image installation.
Reboot command:
execute restore image ftp ${NewImageName} ${StorageAddress}${CRLF}yyyyyyy
Yes, those are seven consecutive y keys. My cat did not walk across my keyboard.
Moving on!
The ${NewImageName} macro uses the firmware image selected through NCM.
The ${StorageAddress} macro uses the storage server configured in the firmware upgrade template. Change this to an IP if you host your FTP server elsewhere.
The ${CRLF} submits the restore command.
Pro Tip: Make sure your image names are exactly the same in your firmware repository and FTP server if they are separate! Keeping them together simplifies this.
The main point of this being the subsequent y characters are supplied without additional command terminators between them.
So, uh, yeah. YaaS.
Enable Reboot device after upgrade
Wait time between reboot and checking that the node is "Up":
0
Leave this set to zero. No touchy.
This is the default value and was necessary for consistent operation in my testing. Introducing an additional wait interfered with the prompt-handling behavior.
Any other diagnostic or information-gathering command fields can be configured according to your needs.
Step 5-ish: Validate the Workflow
Before using the configuration beyond a test environment, confirm that the selected firmware is compatible with the target model and follows an approved upgrade path. This workaround does not evaluate firmware warnings before agreeing to them. Validate those decisions before the automation begins.
Why This Matters Beyond FortiGate
The useful lesson here is broader than firmware upgrades. Many network devices have interactive CLI operations that expect a single character rather than a complete command. Automation platforms that automatically terminate commands can introduce unexpected behavior in those interactions.
SolarWinds already provides powerful device-template capabilities for prompt recognition and command handling. But this experience illustrates the value of more explicit support for multi-prompted interactive behaviors.
Ideally, NCM could provide a way to send individual keystrokes without implicit command terminators, associate responses with specific prompts, and stop when an unexpected confirmation appears. That would make this sort of automation easier to build, easier to audit, and more predictable across vendors.
Or, of course, SolarWinds could add a checkbox labeled:
Enable YaaS Enterprise
Maximum enthusiasm: 7
Moral of the Story
I started with a fairly ordinary firmware automation project. I ended up investigating repository behavior, file staging, SSH command termination, interactive prompt recognition, firmware-operation sequencing, and several alternative integration architectures. The breakthrough was not simply realizing that FortiOS accepts y without Enter. It was realizing that the extra Enter after a valid response could be the very thing preventing the upgrade from proceeding.
Once I stopped treating each confirmation as a separate command, the rest of the upgrade capability became unexpectedly simple.
- A virtual prompt
- A consistent FTP source
- A firmware restore command placed in NCM's reboot stage
- A zero-second reboot wait
- And seven y's
After around 150 attempts, the winning solution was literally just spamming the moody FortiGate with consent:
yyyyyyy
Aaaaanyway…
Hopefully, this saves somebody else in the future from spending a ton of time investigating how two systems disagree about the proper way to say just say yes.
And if you ever discover a suspicious sequence of y's in an NCM firmware upgrade template, don't assume someone accidentally fell asleep on the keyboard. Those characters may represent considerably more engineering effort than they appear to.
YaaS: Yes as a Service. Negative responses are not supported.
Please don't remove them, someone worked very hard on that.