· Nordic  · 3 min read

Building an OTA Firmware Update Server with Django for IoT Devices

Over-the-air (OTA) firmware updates are essential for maintaining and improving IoT devices in the field. In this guide, we’ll build a simple Django-based OTA server to host and deliver firmware updates to Wi-Fi-enabled devices, like those powered by Nordic Semiconductor’s nRF7002. Learn how to create firmware version APIs, serve binary files, and manage updates from a web interface.

Table of Contents

  1. Why You Need an OTA Server
  2. Project Overview
  3. Step-by-Step: Django OTA Server Setup
  4. How Devices Use the API
  5. Next Steps and Enhancements
  6. Conclusion

Why You Need an OTA Server

Updating firmware manually is not scalable in modern IoT applications. An OTA (over-the-air) server allows your devices to:

  • Check for new firmware versions
  • Download updates automatically
  • Stay secure with the latest patches
  • Receive new features remotely

Using Django, we can quickly spin up a REST API server with admin panel support to manage and deliver firmware to remote devices.


Project Overview

We’ll build an OTA firmware server that includes:

  • A database to store firmware version metadata
  • A Django admin panel to upload firmware binaries
  • RESTful endpoints for IoT clients to:
    • Check the latest version
    • Download the latest firmware binary

Step-by-Step: Django OTA Server Setup

1. Create Django Project

django-admin startproject ota_server
cd ota_server
python manage.py startapp firmware

Add 'firmware' to INSTALLED_APPS in settings.py.


2. Define Firmware Model

In firmware/models.py:

from django.db import models

class Firmware(models.Model):
    version = models.CharField(max_length=50)
    file = models.FileField(upload_to='firmware/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Firmware v{self.version}"

Run migrations:

python manage.py makemigrations
python manage.py migrate

3. Set Up Admin Panel

In firmware/admin.py:

from django.contrib import admin
from .models import Firmware

admin.site.register(Firmware)

4. Create API Endpoints

In firmware/views.py:

from django.http import JsonResponse, FileResponse, Http404
from .models import Firmware

def latest_version(request):
    latest = Firmware.objects.order_by('-uploaded_at').first()
    if not latest:
        return JsonResponse({'error': 'No firmware found'}, status=404)
    return JsonResponse({'version': latest.version})

def download_firmware(request):
    latest = Firmware.objects.order_by('-uploaded_at').first()
    if not latest:
        raise Http404("Firmware not found")
    return FileResponse(latest.file.open(), as_attachment=True, filename='app_update.bin')

In firmware/urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('version/', views.latest_version, name='latest_version'),
    path('firmware/', views.download_firmware, name='download_firmware'),
]

In your project’s urls.py:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('firmware.urls')),
]

5. Configure URLs and Media Serving

In settings.py:

MEDIA_URL = '~/assets/media/'
MEDIA_ROOT = BASE_DIR / 'media'

In urls.py:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

6. Upload and Test Firmware

  1. Run the server:

    python manage.py runserver
  2. Visit http://localhost:8000/admin and log in.

  3. Upload a new firmware binary (e.g., app_update.bin) and set its version.

  4. Test the APIs:

    • GET /api/version/ → returns latest version
    • GET /api/firmware/ → downloads firmware binary

How Devices Use the API

Your IoT devices (e.g., an nRF7002-based board) should:

  1. Periodically query /api/version/
  2. Compare version string to current firmware
  3. If a new version is available, fetch /api/firmware/
  4. Write binary to flash and reboot using a bootloader like MCUboot

Next Steps and Enhancements

  • Add authentication: API keys or JWT for secure device access
  • Add changelogs: Let devices see what’s new
  • Support device filtering: Serve firmware per device model or ID
  • Add update reports: Track which devices have successfully updated

Conclusion

Setting up an OTA firmware server using Django is surprisingly straightforward and powerful. With a few models, views, and endpoints, you can fully control how your IoT devices receive updates—whether they’re over Wi-Fi, BLE, or cellular. This setup is a solid foundation for a production-ready update delivery pipeline, and you can scale it up with authentication, metrics, and even a device dashboard.

Now your IoT devices can stay current, secure, and smart—without ever needing a manual update again.

  • nrf7002-dk
  • nordic-semiconductor
  • iot-development
  • ota-firmware-update

Related articles

View All Articles »

Beginner's Guide to Handling Button Inputs on nRF7002 DK with VS Code and nRF Connect SDK

In this guide, we’ll walk you through the process of setting up a project to handle button inputs on the nRF7002 DK. Using the nRF Connect SDK and VS Code, you’ll learn how to configure GPIO, write interrupt-driven button input code, and flash your board. Whether you're just starting with Nordic Semiconductor’s development kits or looking to enhance your embedded projects, this tutorial covers all the essential steps, from environment setup to writing functional code and testing it in action.

Getting Started with the nRF7002: Blink an LED Using the nRF Connect SDK

In this tutorial, we’ll walk you through everything you need to get started with the nRF7002 Development Kit—from setting up your development environment to writing and flashing your first embedded application. We'll use the classic “blinky” example to demonstrate how to blink an LED using Zephyr RTOS and the nRF Connect SDK. By the end of this guide, you’ll have a solid foundation for working with Nordic Semiconductor’s powerful dual-core nRF5340 SoC, which powers the nRF7002 DK.

Understanding Semaphores in Zephyr OS on nRF7002DK

Semaphores are powerful synchronization primitives in Zephyr OS, enabling efficient task coordination and resource management in real-time embedded systems. In this blog post, we explore how semaphores work in Zephyr OS, with a practical example on the nRF7002DK board. Learn how to implement a producer-consumer pattern using semaphores to synchronize threads, and discover best practices for embedded development.

Zephyr OS Logging Module: A Guide with nRF7002DK Example

Discover how to leverage the Zephyr OS logging module for efficient debugging and diagnostics in embedded systems. This guide dives into the module’s features, configuration, and practical implementation using the nRF7002DK, a versatile development kit for IoT applications.