Self-Hosted LoRaWAN with ChirpStack

Posted on 5 2026

ChirpStack is the open source LoRaWAN network server. It handles device authentication, packet deduplication from multiple gateways, adaptive data rate management, and delivery of sensor data to your application layer via MQTT. It is the software that sits at the centre of a private LoRaWAN deployment, doing the work that The Things Network or Helium would do in a public network arrangement, except entirely on your own infrastructure.

This guide walks through installing ChirpStack v4 on an Ubuntu server using the native apt packages. The target is the February homelab server once it is running, but the steps work on any Ubuntu 22.04 or 24.04 server.

Architecture overview

Before touching a command, it is worth being clear about what you are installing and why each component exists.

ChirpStack is the network server itself. It manages devices and applications, receives uplinks, sends downlinks, and exposes an API and web interface.

PostgreSQL is ChirpStack’s database. It stores device profiles, device sessions, application configuration, and gateway registrations.

Redis is ChirpStack’s in-memory store. It handles real-time packet processing, device session state, and caching.

Mosquitto is the MQTT broker. Gateways forward LoRa packets to Mosquitto. ChirpStack subscribes to Mosquitto to receive them. Your application subscribes to Mosquitto to receive processed device data.

ChirpStack Gateway Bridge runs on or close to the gateway. It translates the gateway’s packet format (Semtech UDP or Basics Station) into the MQTT messages ChirpStack expects.

The data flow is:

LoRa Device → Gateway → Gateway Bridge → Mosquitto → ChirpStack → Mosquitto → Your Application

Prerequisites

A running Ubuntu 22.04 or 24.04 server with:

  • At least 1GB RAM (2GB recommended)
  • At least 10GB available storage
  • Network connectivity
  • A non-root user with sudo access

The February homelab server comfortably exceeds these requirements.

Step 1: Install dependencies

Update the system and install required packages:

sudo apt update && sudo apt upgrade -y
sudo apt install -y \
    postgresql \
    redis-server \
    mosquitto \
    mosquitto-clients \
    gpg \
    curl

Step 2: Configure PostgreSQL

Start and enable PostgreSQL:

sudo systemctl enable --now postgresql

Create the ChirpStack database and user. Generate a strong password in KeePassXC first and store it there before running these commands:

sudo -u postgres psql << EOF
CREATE ROLE chirpstack WITH LOGIN PASSWORD 'your-strong-password-here';
CREATE DATABASE chirpstack WITH OWNER chirpstack;
\c chirpstack
CREATE EXTENSION pg_trgm;
\q
EOF

Verify the connection:

psql -h localhost -U chirpstack -d chirpstack -c "\l"

Enter the password when prompted. A successful connection confirms PostgreSQL is configured correctly.

Step 3: Configure Redis

Redis is used for session storage and caching. The default configuration is sufficient for a homelab deployment. Enable persistence so session data survives restarts:

sudo tee -a /etc/redis/redis.conf << 'EOF'

# ChirpStack persistence configuration
appendonly yes
appendfilename "appendonly.aof"
EOF

sudo systemctl enable --now redis-server

Verify Redis is responding:

redis-cli ping

Expected response: PONG

Step 4: Configure Mosquitto

ChirpStack v4 requires an MQTT broker. The default Mosquitto configuration allows unauthenticated connections on localhost, which is acceptable for a homelab behind a firewall. For a more hardened setup, configure username/password authentication.

Create the ChirpStack MQTT configuration:

sudo tee /etc/mosquitto/conf.d/chirpstack.conf << 'EOF'
# ChirpStack MQTT configuration

# Allow anonymous connections from localhost
# For production, use password authentication
listener 1883 127.0.0.1

# Allow connections from gateway bridge on the local network
listener 1883 0.0.0.0
allow_anonymous true

# Log to syslog
log_dest syslog
log_type all
EOF

For a more secure setup with authentication, generate a password file:

sudo mosquitto_passwd -c /etc/mosquitto/passwd chirpstack
sudo mosquitto_passwd /etc/mosquitto/passwd gateway

Then reference it in the configuration:

sudo tee /etc/mosquitto/conf.d/chirpstack.conf << 'EOF'
listener 1883
password_file /etc/mosquitto/passwd
allow_anonymous false
EOF

Enable and start Mosquitto:

sudo systemctl enable --now mosquitto

Step 5: Install ChirpStack

Add the ChirpStack apt repository:

sudo mkdir -p /etc/apt/keyrings/
sudo sh -c 'wget -q -O - https://artifacts.chirpstack.io/packages/chirpstack.key | \
    gpg --dearmor > /etc/apt/keyrings/chirpstack.gpg'

echo "deb [signed-by=/etc/apt/keyrings/chirpstack.gpg] \
    https://artifacts.chirpstack.io/packages/4.x/deb stable main" | \
    sudo tee /etc/apt/sources.list.d/chirpstack.list

sudo apt update
sudo apt install -y chirpstack

Step 6: Configure ChirpStack

The main configuration file is at /etc/chirpstack/chirpstack.toml. Edit it:

sudo nano /etc/chirpstack/chirpstack.toml

Key sections to configure:

PostgreSQL connection

[postgresql]
  dsn="postgres://chirpstack:your-strong-password-here@localhost/chirpstack?sslmode=disable"

Redis connection

[redis]
  servers=["redis://127.0.0.1/"]

API secret key

Generate a unique secret key for securing API tokens:

openssl rand -base64 32

Copy the output and set it in the configuration:

[network]
  net_id="000000"
  enabled_regions=[
    "eu868",
  ]

[api]
  secret="your-generated-secret-here"

The net_id can remain 000000 for a private network. For a network that federates with other LoRaWAN networks, you would need a registered Net ID from the LoRa Alliance.

Region configuration

For the UK, the EU868 region is pre-configured. Verify it is in the enabled regions list. The region configuration file at /etc/chirpstack/region_eu868.toml contains channel configuration, data rates, and other region-specific settings.

The EU868 defaults are correct for the UK. No changes are needed here for a standard deployment.

MQTT integration

[integration]
  enabled=["mqtt"]

  [integration.mqtt]
    server="tcp://localhost:1883"
    # If using Mosquitto authentication:
    # username="chirpstack"
    # password="your-mosquitto-password"

Step 7: Start ChirpStack

Enable and start the service:

sudo systemctl enable --now chirpstack

Check the service status:

sudo systemctl status chirpstack

Follow the logs:

sudo journalctl -u chirpstack -f

The log output should show ChirpStack starting, connecting to PostgreSQL and Redis, and listening for connections. Any configuration errors appear here.

Step 8: Access the web interface

ChirpStack’s web interface runs on port 8080 by default. Access it from the desktop:

http://server.yourdomain.net:8080

Or from the server itself:

http://localhost:8080

The default credentials are:

  • Username: admin
  • Password: admin

Change the admin password immediately after first login. Navigate to Users > admin > Change Password. Generate a strong password in KeePassXC.

Step 9: Install the ChirpStack Gateway Bridge

The Gateway Bridge runs close to the gateway: either on the gateway itself (if it runs Linux) or on a server on the same network. It translates the gateway’s packet format into the MQTT format ChirpStack expects.

Install it on the homelab server alongside ChirpStack:

sudo apt install -y chirpstack-gateway-bridge

Configure it at /etc/chirpstack-gateway-bridge/chirpstack-gateway-bridge.toml:

# UDP packet forwarder backend
[backend]
  type="semtech_udp"

  [backend.semtech_udp]
    udp_bind="0.0.0.0:1700"

# MQTT integration
[integration.mqtt]
  event_topic_template="eu868/gateway/{{ .GatewayID }}/event/{{ .EventType }}"
  command_topic_template="eu868/gateway/{{ .GatewayID }}/command/#"

  [integration.mqtt.auth]
    type="generic"

    [integration.mqtt.auth.generic]
      server="tcp://localhost:1883"

Enable and start the Gateway Bridge:

sudo systemctl enable --now chirpstack-gateway-bridge

Step 10: Configure your gateway

The gateway must be configured to forward packets to the Gateway Bridge. The specific steps depend on the gateway hardware.

For most gateways running the Semtech UDP packet forwarder, configure the forwarder’s server_address to point at the homelab server:

{
    "server_address": "server.yourdomain.net",
    "serv_port_up": 1700,
    "serv_port_down": 1700
}

For Basics Station protocol gateways, configure the Basics Station server URL:

wss://server.yourdomain.net:3001

Once the gateway is configured and connected, it should appear in the ChirpStack web interface under Gateways within a few minutes. The Last Seen timestamp will start updating as the gateway sends stats packets.

Step 11: Add a device profile and device

In the ChirpStack web interface:

  1. Navigate to Device Profiles > Add Device Profile
  2. Set the region to EU868
  3. Set the MAC version to LoRaWAN 1.0.4 (for most current devices) or 1.1.0 (for newer devices)
  4. Enable OTAA (Over-The-Air Activation) for devices that support it

Add an application:

  1. Navigate to Applications > Add Application
  2. Give it a descriptive name

Add a device to the application:

  1. Within the application, click Add Device
  2. Enter the Device EUI from the sensor’s documentation or label
  3. Enter the Application Key (for OTAA devices)

When the device transmits its first Join Request, ChirpStack handles the OTAA join procedure and the device begins appearing in the event log.

Receiving data via MQTT

Once a device is joined and transmitting, its data arrives on MQTT topics. Subscribe to see it:

mosquitto_sub -h localhost -t "application/#" -v

Uplink messages arrive on topics in the format:

application/{applicationId}/device/{devEui}/event/up

The payload is JSON containing the decoded frame data, signal strength, and metadata. This is the data that flows through to InfluxDB, Grafana, and Node-RED via the MQTT pipeline described in the MQTT series.

Firewall rules

Open the required ports on the homelab firewall:

# ChirpStack web interface
sudo ufw allow 8080/tcp

# Gateway Bridge UDP (Semtech UDP packet forwarder)
sudo ufw allow 1700/udp

# Gateway Bridge WebSocket (Basics Station)
sudo ufw allow 3001/tcp

# MQTT (restrict to internal network only)
sudo ufw allow from 10.0.0.0/8 to any port 1883 proto tcp

The MQTT port should not be exposed to the public internet. Restrict it to the internal network address space.

What comes next

A running ChirpStack instance is the foundation. The next steps are:

  • Connecting the gateway hardware and verifying packet reception
  • Importing device profiles from the chirpstack-device-profiles repository for common sensors
  • Configuring the MQTT integration to feed data into InfluxDB
  • Setting up Grafana dashboards for sensor visualisation
  • Configuring Node-RED for automation based on sensor readings