Skip to content

Network Firmware Upgrades and Downgrades

Dashboard Location: Network-wide > Configure > General > Firmware Upgrades

Firmware management in Meraki enables you to control the firmware version running on network devices. Through NAC, you can schedule upgrades and downgrades for specific product types within a network and configure the automatic upgrade window.

Meraki firmware operations are non-declarative by nature. Unlike other NAC resources, NAC does not continuously reconcile firmware state — it pushes the intent (a scheduled upgrade or downgrade) and does not verify the outcome. Use nac-test to operationally validate that the intended firmware version is running after the scheduled window.

Schedule Intent vs Configuration Intent: Most NAC resources declare a desired ongoing state — Terraform enforces them continuously and corrects drift. Firmware is different: it declares an intent to act at a point in time. Once the schedule is created, the intent is considered delivered — NAC does not track whether the upgrade completes. A finished schedule is not a steady-state goal — it does not mean “keep this device on version X forever.” The YAML represents what should happen next, not what should always be. Once a schedule is pushed, NAC does not track it further. If the schedule is still pending, any YAML changes will be pushed as an update. If the schedule has already executed, update to_version, local_time, or both to push a new schedule — see the note below on past-date behaviour.

Re-declaring After a Completed Schedule: Once a scheduled upgrade or downgrade executes, that product’s YAML entry reflects a completed action. To schedule a new upgrade, update local_time and to_version. The provider always sends toVersion.id, time, and predownload together whenever any one of them changes, so:

  • Updating only local_time schedules a new upgrade to the same version at a new time — useful when a device was manually downgraded outside NAC and you want to re-apply the same version.
  • Updating only to_version schedules an upgrade to the new version using the existing local_time. If that time is already in the past, the upgrade will be triggered within approximately 5 minutes of apply.

Changes to one product do not affect the schedules of other products.

Intent Must Be Forward-Looking: The declared to_version must differ from the version currently running on the network — specifying the current firmware version causes an API error. For local_time, always specify a future timestamp, or omit it entirely to trigger the upgrade within approximately 5 minutes of apply.

Upgrade vs Downgrade — Per-Product Mutual Exclusivity: The upgrade and downgrade blocks can coexist in the same firmware definition. However, a single product type can only appear in one of them — never both. For example, wireless can be in downgrade while switch and appliance are in upgrade, but wireless cannot appear in both blocks simultaneously.

Dedicated Workspace: It is recommended to manage firmware upgrades and downgrades in a dedicated Terraform workspace. Because firmware is a schedule intent rather than a configuration intent, it behaves differently from other NAC resources: Meraki may apply automatic upgrades, or operators may manually change firmware versions outside of NAC. Either event can cause the Terraform state to diverge from what the API reports, which produces plan-time errors and can stall a CI/CD pipeline. Isolating firmware operations in a dedicated workspace means these failures are contained and do not block unrelated configuration changes from being applied.

Diagram

firmware (meraki.domains.organizations.networks)

Section titled “firmware (meraki.domains.organizations.networks)”
NameTypeConstraintMandatoryDefault Value
automatic_upgrade_windowClass[automatic_upgrade_window]No
upgradeClass[upgrade]No
downgradeClass[downgrade]No

automatic_upgrade_window (meraki.domains.organizations.networks.firmware)

Section titled “automatic_upgrade_window (meraki.domains.organizations.networks.firmware)”
NameTypeConstraintMandatoryDefault Value
day_of_weekChoicesunday, monday, tuesday, wednesday, thursday, friday, saturdayYes
hour_of_dayChoice0:00, 1:00, 2:00, 3:00, 4:00, 5:00, 6:00, 7:00, 8:00, 9:00, 10:00, 11:00, 12:00, 13:00, 14:00, 15:00, 16:00, 17:00, 18:00, 19:00, 20:00, 21:00, 22:00, 23:00Yes

upgrade (meraki.domains.organizations.networks.firmware)

Section titled “upgrade (meraki.domains.organizations.networks.firmware)”
NameTypeConstraintMandatoryDefault Value
productsClass[products]No

downgrade (meraki.domains.organizations.networks.firmware)

Section titled “downgrade (meraki.domains.organizations.networks.firmware)”
NameTypeConstraintMandatoryDefault Value
productsClass[products]No

products (meraki.domains.organizations.networks.firmware.upgrade)

Section titled “products (meraki.domains.organizations.networks.firmware.upgrade)”
NameTypeConstraintMandatoryDefault Value
switchClass[switch]No
switch_catalystClass[switch_catalyst]No
wirelessClass[wireless]No
applianceClass[appliance]No
cellular_gatewayClass[cellular_gateway]No

products (meraki.domains.organizations.networks.firmware.downgrade)

Section titled “products (meraki.domains.organizations.networks.firmware.downgrade)”
NameTypeConstraintMandatoryDefault Value
switchClass[switch]No
switch_catalystClass[switch_catalyst]No
wirelessClass[wireless]No
applianceClass[appliance]No
cellular_gatewayClass[cellular_gateway]No

switch (meraki.domains.organizations.networks.firmware.upgrade.products)

Section titled “switch (meraki.domains.organizations.networks.firmware.upgrade.products)”
NameTypeConstraintMandatoryDefault Value
participate_in_next_beta_releaseBooleantrue, falseNo
next_upgradeClass[next_upgrade]No

switch_catalyst (meraki.domains.organizations.networks.firmware.upgrade.products)

Section titled “switch_catalyst (meraki.domains.organizations.networks.firmware.upgrade.products)”
NameTypeConstraintMandatoryDefault Value
participate_in_next_beta_releaseBooleantrue, falseNo
next_upgradeClass[next_upgrade]No

wireless (meraki.domains.organizations.networks.firmware.upgrade.products)

Section titled “wireless (meraki.domains.organizations.networks.firmware.upgrade.products)”
NameTypeConstraintMandatoryDefault Value
participate_in_next_beta_releaseBooleantrue, falseNo
next_upgradeClass[next_upgrade]No

appliance (meraki.domains.organizations.networks.firmware.upgrade.products)

Section titled “appliance (meraki.domains.organizations.networks.firmware.upgrade.products)”
NameTypeConstraintMandatoryDefault Value
participate_in_next_beta_releaseBooleantrue, falseNo
next_upgradeClass[next_upgrade]No

cellular_gateway (meraki.domains.organizations.networks.firmware.upgrade.products)

Section titled “cellular_gateway (meraki.domains.organizations.networks.firmware.upgrade.products)”
NameTypeConstraintMandatoryDefault Value
participate_in_next_beta_releaseBooleantrue, falseNo
next_upgradeClass[next_upgrade]No

switch (meraki.domains.organizations.networks.firmware.downgrade.products)

Section titled “switch (meraki.domains.organizations.networks.firmware.downgrade.products)”
NameTypeConstraintMandatoryDefault Value
next_downgradeClass[next_downgrade]No

switch_catalyst (meraki.domains.organizations.networks.firmware.downgrade.products)

Section titled “switch_catalyst (meraki.domains.organizations.networks.firmware.downgrade.products)”
NameTypeConstraintMandatoryDefault Value
next_downgradeClass[next_downgrade]No

wireless (meraki.domains.organizations.networks.firmware.downgrade.products)

Section titled “wireless (meraki.domains.organizations.networks.firmware.downgrade.products)”
NameTypeConstraintMandatoryDefault Value
next_downgradeClass[next_downgrade]No

appliance (meraki.domains.organizations.networks.firmware.downgrade.products)

Section titled “appliance (meraki.domains.organizations.networks.firmware.downgrade.products)”
NameTypeConstraintMandatoryDefault Value
next_downgradeClass[next_downgrade]No

cellular_gateway (meraki.domains.organizations.networks.firmware.downgrade.products)

Section titled “cellular_gateway (meraki.domains.organizations.networks.firmware.downgrade.products)”
NameTypeConstraintMandatoryDefault Value
next_downgradeClass[next_downgrade]No

next_upgrade (meraki.domains.organizations.networks.firmware.upgrade.products.switch)

Section titled “next_upgrade (meraki.domains.organizations.networks.firmware.upgrade.products.switch)”
NameTypeConstraintMandatoryDefault Value
local_timeStringRegex: ^\d{4,}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d$No
to_versionStringmin: 1, max: 127Yes

next_upgrade (meraki.domains.organizations.networks.firmware.upgrade.products.wireless)

Section titled “next_upgrade (meraki.domains.organizations.networks.firmware.upgrade.products.wireless)”
NameTypeConstraintMandatoryDefault Value
local_timeStringRegex: ^\d{4,}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d$No
to_versionStringmin: 1, max: 127Yes
pre_downloadBooleantrue, falseNo

next_downgrade (meraki.domains.organizations.networks.firmware.downgrade.products.switch)

Section titled “next_downgrade (meraki.domains.organizations.networks.firmware.downgrade.products.switch)”
NameTypeConstraintMandatoryDefault Value
local_timeStringRegex: ^\d{4,}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d$No
to_versionStringmin: 1, max: 127Yes
reasonsList[reasons]Yes

next_downgrade (meraki.domains.organizations.networks.firmware.downgrade.products.wireless)

Section titled “next_downgrade (meraki.domains.organizations.networks.firmware.downgrade.products.wireless)”
NameTypeConstraintMandatoryDefault Value
local_timeStringRegex: ^\d{4,}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d$No
to_versionStringmin: 1, max: 127Yes
pre_downloadBooleantrue, falseNo
reasonsList[reasons]Yes

reasons (meraki.domains.organizations.networks.firmware.downgrade.products.switch.next_downgrade)

Section titled “reasons (meraki.domains.organizations.networks.firmware.downgrade.products.switch.next_downgrade)”
NameTypeConstraintMandatoryDefault Value
categoryChoicebroke old features, other, performance, stability, testing, unifying networks versionsNo
commentStringmin: 1, max: 1024No

Example 1: Immediate Upgrade / Network Initialization

Section titled “Example 1: Immediate Upgrade / Network Initialization”

Omitting the local_time field triggers an immediate upgrade (scheduled approximately 5 minutes from the time of apply). This is useful in two scenarios:

  • Network initialization: standardize newly claimed devices to a known-good firmware version before the network goes into production.
  • Forced immediate upgrade: push a version change to existing devices without waiting for a maintenance window.

The example below targets three product types — switch, wireless, and appliance — pinning each to a stable release.

meraki:
domains:
- name: !env domain
administrator:
name: !env org_admin
organizations:
- name: !env org
networks:
- name: !env network_name
product_types:
- appliance
- switch
- wireless
firmware:
upgrade:
products:
switch:
next_upgrade:
to_version: "MS 17.2.2"
wireless:
next_upgrade:
to_version: "MR 32.1.7"
appliance:
next_upgrade:
to_version: "MX 19.2.8"

Example 2: Scheduled Upgrade to a Higher Version

Section titled “Example 2: Scheduled Upgrade to a Higher Version”

The example below schedules an upgrade to higher firmware versions across switch, wireless, and appliance at 10 PM on a specific date. The automatic_upgrade_window defines the recurring window Meraki uses for automatic (Meraki-initiated) upgrades; the local_time on each product controls when this specific scheduled upgrade runs.

local_time is specified as a local time without a timezone designator (e.g. "2026-09-15T22:00:00"). The API requires a trailing Z in this field, but despite the format it does not mean UTC — the time is interpreted in the network’s configured timezone. NAC appends the Z automatically.

The pre_download flag on wireless instructs access points to download the firmware image in advance so that the actual upgrade completes faster during the maintenance window.

The participate_in_next_beta_release flag opts the product into Meraki’s next beta release program. It is independent of next_upgrade and can be set with or without a scheduled upgrade.

meraki:
domains:
- name: !env domain
administrator:
name: !env org_admin
organizations:
- name: !env org
networks:
- name: !env network_name
product_types:
- appliance
- switch
- wireless
firmware:
automatic_upgrade_window:
day_of_week: "sunday"
hour_of_day: "4:00"
upgrade:
products:
switch:
participate_in_next_beta_release: true
next_upgrade:
local_time: "2026-09-15T22:00:00"
to_version: "MS 18.1.7.1"
wireless:
next_upgrade:
local_time: "2026-09-15T22:00:00"
to_version: "MR 32.2.3"
pre_download: true
appliance:
next_upgrade:
local_time: "2026-09-15T22:00:00"
to_version: "MX 26.1.3"

Example 3: Mixed Upgrade and Downgrade Across Products

Section titled “Example 3: Mixed Upgrade and Downgrade Across Products”

upgrade and downgrade can coexist in the same firmware block — the constraint is per product, not per block. A product type can appear in upgrade or downgrade, but never in both at the same time.

The example below upgrades switch and appliance while simultaneously scheduling a downgrade for wireless. wireless appears only in downgrade and is absent from upgrade. If wireless were added to upgrade as well, validation would fail.

A downgrade requires a reasons list with at least one entry — the category must be one of: performance, stability, broke old features, testing, unifying networks versions, other.

meraki:
domains:
- name: !env domain
administrator:
name: !env org_admin
organizations:
- name: !env org
networks:
- name: !env network_name
product_types:
- appliance
- switch
- wireless
firmware:
automatic_upgrade_window:
day_of_week: "sunday"
hour_of_day: "4:00"
upgrade:
products:
switch:
next_upgrade:
local_time: "2026-08-01T22:00:00"
to_version: "MS 18.1.7.1"
appliance:
next_upgrade:
local_time: "2026-08-01T22:00:00"
to_version: "MX 26.1.3"
downgrade:
products:
wireless:
next_downgrade:
local_time: "2026-08-01T22:00:00"
to_version: "MR 31.1.8"
reasons:
- category: "stability"
comment: "MR 32.x introduced intermittent client association failures in high-density environments"