diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7585238
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+book
diff --git a/Dockerfile-devel b/Dockerfile-devel
new file mode 100644
index 0000000..2575587
--- /dev/null
+++ b/Dockerfile-devel
@@ -0,0 +1,10 @@
+FROM rust:1.59.0-buster
+
+WORKDIR /chirpstack-docs
+
+
+RUN cargo install mdbook
+RUN cargo install mdbook-tera
+RUN cargo install mdbook-graphviz
+
+RUN apt-get update && apt-get install -y graphviz
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a3f7e17
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+build:
+ docker-compose run --rm chirpstack-docs mdbook clean
+ docker-compose run --rm chirpstack-docs mdbook build
+
+serve:
+ docker-compose run --rm --service-ports chirpstack-docs mdbook serve -n 0.0.0.0
+
+upload:
+ cd book && rsync -avzh . root@chirpstack.io:/var/www/chirpstack.io/docs/
diff --git a/book.toml b/book.toml
new file mode 100644
index 0000000..50b594a
--- /dev/null
+++ b/book.toml
@@ -0,0 +1,27 @@
+[book]
+title = "ChirpStack open-source LoRaWAN® Network Server documentation"
+authors = []
+language = "en"
+multilingual = false
+src = "src"
+
+[output.html]
+no-section-label = true
+additional-css = ["theme/css/chirpstack.css"]
+git-repository-url = "https://github.com/chirpstack/chirpstack-docs"
+git-repository-icon = "fa-github"
+edit-url-template = "https://github.com/chirpstack/chirpstack-docs/edit/master/{path}"
+
+[output.html.print]
+enable = false
+
+[output.html.fold]
+enable = true
+level = 0
+
+[preprocessor.tera]
+command = "mdbook-tera --json ./src/context.json"
+
+[preprocessor.graphviz]
+command = "mdbook-graphviz"
+
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..a73c0db
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,9 @@
+services:
+ chirpstack-docs:
+ build:
+ context: .
+ dockerfile: Dockerfile-devel
+ ports:
+ - 3000:3000
+ volumes:
+ - ./:/chirpstack-docs
diff --git a/src/SUMMARY.md b/src/SUMMARY.md
new file mode 100644
index 0000000..6cc0b43
--- /dev/null
+++ b/src/SUMMARY.md
@@ -0,0 +1,34 @@
+# Summary
+
+- [Introduction](./index.md)
+- [Architecture](./architecture.md)
+- [v3 to v4 migration](./v3-v4-migration.md)
+
+---
+
+# ChirpStack
+
+- [Changelog](./chirpstack/changelog.md)
+- [Configuration](./chirpstack/configuration.md)
+- [Downloads](./chirpstack/downloads.md)
+- [Features](./chirpstack/features/index.md)
+ - [Multi-region](./chirpstack/features/multi-reagion.md)
+
+# ChirpStack Gateway OS
+
+- [Introduction](./gateway-os/index.md)
+- [Image types](./gateway-os/image-types.md)
+- [Changelog](./gateway-os/changelog.md)
+- [Downloads](./gateway-os/downloads.md)
+- [Guides](./gateway-os/guides/index.md)
+ - [Getting started](./gateway-os/guides/getting-started.md)
+ - [Node-RED](./gateway-os/guides/node-red.md)
+- [Use](./gateway-os/use/index.md)
+ - [Configuration](./gateway-os/use/gateway-config.md)
+ - [Log files](./gateway-os/use/log-files.md)
+ - [Monitoring](./gateway-os/use/monitoring.md)
+ - [Modifying files](./gateway-os/use/modifying-files.md)
+ - [Software update](./gateway-os/use/software-update.md)
+- [Contribute & source](./gateway-os/contribute.md)
+
+---
diff --git a/src/architecture.md b/src/architecture.md
new file mode 100644
index 0000000..f433f73
--- /dev/null
+++ b/src/architecture.md
@@ -0,0 +1,76 @@
+# Architecture
+
+A typical ChirpStack deployment has the following architecture:
+
+```dot process
+digraph G {
+ node [shape=record,fontsize="10"];
+ edge [fontsize="10"];
+ fontsize="10";
+
+ subgraph cluster_0 {
+ style=filled;
+ color="#bbdefb";
+ node [style=filled,color="#e3f2fd"];
+
+ "chirpstack" -> "pub-sub" [dir="both",label="MQTT"];
+ "chirpstack-gateway-bridge-cloud" -> "pub-sub" [dir="both" label="MQTT"];
+
+ "chirpstack" [label="ChirpStack"];
+ "pub-sub" [label="MQTT broker"];
+ "chirpstack-gateway-bridge-cloud" [label="ChirpStack Gateway Bridge"];
+
+ label = "Cloud / server / VM";
+ }
+
+ subgraph cluster_1 {
+ style=filled;
+ color="#bbdefb";
+ node [style=filled,color="#e3f2fd"];
+ label="LoRa® Gateway";
+
+ "chirpstack-gateway-bridge-gw" -> "pub-sub" [label="MQTT",dir="both"];
+ "chirpstack-gateway-bridge-gw" [label="Packet Forwarder +\nChirpStack Gateway Bridge"];
+ }
+
+
+ subgraph cluster_2 {
+ style=filled;
+ color="#bbdefb";
+ node [style=filled,color="#e3f2fd"];
+ label="LoRa® Gateway";
+
+ "packet-forwarder-gw2" -> "chirpstack-gateway-bridge-cloud" [label="UDP",dir="both"];
+ "packet-forwarder-gw2" [label="Packet Forwarder"];
+ }
+
+ subgraph cluster_3 {
+ style=filled;
+ color="#bbdefb";
+ node [style=filled,color="#e3f2fd"];
+ label="LoRa® Gateway";
+
+ "packet-forwarder-gw3" -> "chirpstack-gateway-bridge-cloud" [label="Websockets",dir="both"];
+ "packet-forwarder-gw3" [label="Basics Station"];
+ }
+
+ subgraph cluster_5 {
+ style=filled;
+ color="#bbdefb";
+ node [style=filled,color="#e3f2fd"];
+ label="Integrations";
+
+ "http-int" [label="HTTP"];
+ "mqtt-int" [label="MQTT"];
+ "other-int" [label="Etc ..."];
+ }
+
+
+ "chirpstack" -> "http-int";
+ "chirpstack" -> "mqtt-int";
+ "chirpstack" -> "other-int";
+
+ "as-api-client" -> "chirpstack" [label="gRPC"];
+ "as-api-client" [label="API client"];
+}
+```
diff --git a/src/architecture_0.generated.svg b/src/architecture_0.generated.svg
new file mode 100644
index 0000000..17442e1
--- /dev/null
+++ b/src/architecture_0.generated.svg
@@ -0,0 +1,258 @@
+
+
+
+
+
diff --git a/src/chirpstack/backends/index.md b/src/chirpstack/backends/index.md
new file mode 100644
index 0000000..817deab
--- /dev/null
+++ b/src/chirpstack/backends/index.md
@@ -0,0 +1 @@
+# Backends
diff --git a/src/chirpstack/backends/mqtt.md b/src/chirpstack/backends/mqtt.md
new file mode 100644
index 0000000..172e63c
--- /dev/null
+++ b/src/chirpstack/backends/mqtt.md
@@ -0,0 +1 @@
+# MQTT
diff --git a/src/chirpstack/changelog.md b/src/chirpstack/changelog.md
new file mode 100644
index 0000000..c4325c5
--- /dev/null
+++ b/src/chirpstack/changelog.md
@@ -0,0 +1,156 @@
+# Changelog
+
+## v4.0.0 (in development)
+
+After many months of development, We are really excited to share ChirpStack v4. The
+idea of ChirpStack v4 was born based on experience using ChirpStack for
+various clients, as well as many discussion with community members
+and recurring issues that were reported on the forum.
+
+ChirpStack v4 merges the (v3) ChirpStack Application and ChirpStack Network Server,
+adding support for multi-region without the need to setup multiple ChirpStack
+instances. ChirpStack is a new component, which replaces the ChirpStack Application
+Server and ChirpStack Network Server.
+
+### Main features and changes
+
+#### Multi-region support
+
+ChirpStack v4 adds multi-region support, removing the need to setup multiple
+ChirpStack Network Server instances. Configuration files are included for the
+common regions (as defined by the LoRa Alliance), which should help getting
+started with ChirpStack.
+
+Each enabled region has its own gateway backend, making it possible to use one
+or multiple MQTT brokers for the different gateway pools. In case a single
+MQTT broker is used, each backend must be configured with its own MQTT topic prefix
+(e.g. `eu868/gateway/...`).
+
+ChirpStack v4 also supports multiple configurations of the same region, e.g.
+to configure a US915 for 8 channels and to configure a US915 band for 16
+channels.
+
+#### Configuration
+
+##### Directory
+
+Instead of using a single configuration file (e.g. `chirpstack-network-server.toml`),
+ChirpStack makes use of a configuration directory such that the configuration
+can be split in multiple files. By default you will find a single `chirpstack.toml`
+configuration file, and many `region_...toml` configuration files, split
+by region.
+
+##### Environment variables
+
+ChirpStack v4 removes the TOML hierarchy to environment variable mapping.
+Instead it allows you to define the variables like `$MY_CONFIGURATION`, which
+will get automatically substituted when an environment variable is found with
+the name `MY_CONFIGURATION`.
+
+#### API
+
+The REST interface that was present in ChirpStack Application Server v3 has
+been removed, in favor of the gRPC API interface (please see the `api/` folder
+of the repository for the API definitions). However, a gRPC to REST interface
+bridge component will be provided as a separate service. Please note that
+in v3, this bridge component was embedded and REST interface calls were
+internally translated to gRPC calls. Therefore, gRPC was always recommended
+interface to use.
+
+The ChirpStack v4 gRPC API does support server reflection, making it possible
+to use for example [gRPC UI](https://github.com/fullstorydev/grpcui) or
+[BloomRPC](https://github.com/bloomrpc/bloomrpc) as development interface.
+
+#### ChirpStack Gateway Bridge v3 compatibility
+
+ChirpStack v4 is fully compatibility with the latest version of ChirpStack
+Gateway Bridge v3. This should help migrating from v3 to v4. Please note that
+the ChirpStack Gateway Bridge **must** be configured with the `protobuf`
+marshaler.
+
+#### UI rewrite
+
+ChirpStack v4 contains a rewrite of the ChirpStack Application Server v3 UI.
+The new UI aims to be more user-friendly. Under the hood the API interface
+has been ported to gRPC-web and all code has been ported to Typescript.
+
+### Other changes
+
+#### UUID identifiers
+
+All identifiers that are exposed have been changed to UUID. Previously most
+identifiers (e.g. users, applications...) were incremental integers. In case
+ChirpStack is setup as multi-tenant instance, this could expose some information
+about the number of clients on the network. The migration script (see below)
+will migrate these integers by converting these as strings, prefixed with
+zeros in the UUID format. E.g. ID `123` would be converted to the UUID string
+`00000000-0000-0000-0000-000000000123`.
+
+#### String identifiers in API
+
+All binary identifiers have been changed to string type in the API. While
+binary fields are more efficient, these were confusing when encoded as JSON
+as the Protobuf to JSON mapping uses base64 encoding for binary fields.
+For example, a Gateway ID `0102030405060708` was encoded as `AQIDBAUGBwg=`
+in JSON.
+
+#### JavaScript codec engine
+
+The JavaScript codec engine is based on QuickJS, which is an embeddable
+JavaScript engine which supports the ES2020 specification. In the near future
+support for the NodeJS [Buffer class](https://nodejs.org/api/buffer.html)
+will be added.
+
+#### API interface changes
+
+While the structure of API messages is roughly the same as the ChirpStack
+Application Server API interface, some small changes have been made.
+
+#### Integration events
+
+The integration event messages have been restructured for better consistency.
+Each event message has a `deviceInfo` field which holds device-related
+information (tenant id & name, application id & name, device-profile id &
+name, device EUI & name and tags).
+
+### Development changes
+
+#### Single repository
+
+ChirpStack v4 will make it a lot easier to make customizations, especially
+when API changes are involved, as API definitions are no longer separated
+from the code. In v3 these definitions were moved to an external repository
+to avoid cross dependencies.
+
+### Still missing
+
+There are a few features still missing, that were present in v3. These will be
+added shortly. These are:
+
+* Global integrations (only MQTT is currently implemented)
+* Passive roaming
+* REST API bridge
+* Support for GCP Cloud IoT Core and Azure IoT Hub gateway interfaces
+
+#### Rust
+
+For ChirpStack v4, it was decided to use Rust rather than Go. This was not
+an easy choice and the arguments for this decision are debatable. However,
+as most code was touched during the ChirpStack Application Server and ChirpStack
+Network Server merge, it was the only moment to re-consider this. The Rust
+memory management prevents many memory related pitfalls and with that potential
+bugs, as these can be catched at compile-time rather than during runtime.
+
+### Migrating from v3 to v4
+
+The recommended way to migrate from v3 to ChirpStack v4 is to create a new
+PostgreSQL and Redis database and to use the [ChirpStack v3 to v4](https://github.com/chirpstack/chirpstack-v3-to-v4)
+migration script. This script will **copy** all the data from the "old"
+into the "new" database. While the script does not make any modifications
+to the old database, it is always recommended to make a backup first.
+
+The script is called with at least three configuration files; the
+`chirpstack-network-server.toml` (v3), `chirpstack-application-server.toml` (v3)
+and the `chirpstack.toml` (v4) configuration files. In case you have setup
+multiple ChirpStack Network Server regions, you can repeat the ChirpStack
+Network Server configuration file argument for each region.
diff --git a/src/chirpstack/chirpstack.toml b/src/chirpstack/chirpstack.toml
new file mode 100644
index 0000000..791ae5f
--- /dev/null
+++ b/src/chirpstack/chirpstack.toml
@@ -0,0 +1,401 @@
+
+# PostgreSQL configuration.
+[postgresql]
+
+ # PostgreSQL DSN.
+ #
+ # Format example: postgres://:@/?sslmode=.
+ #
+ # SSL mode options:
+ # * disable - no SSL
+ # * require - Always SSL (skip verification)
+ # * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA)
+ # * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate)
+ dsn="postgresql://chirpstack:chirpstack@localhost/chirpstack?sslmode=disable"
+
+ # Max open connections.
+ #
+ # This sets the max. number of open connections that are allowed in the
+ # PostgreSQL connection pool.
+ max_open_connections=10
+
+ # Min idle connections.
+ #
+ # This sets the min. number of idle connections in the PostgreSQL connection
+ # pool (0 = equal to max_open_connections).
+ min_idle_connections=0
+
+
+# Redis configuration.
+[redis]
+
+ # Server address or addresses.
+ #
+ # Set multiple addresses when connecting to a cluster.
+ servers=[
+ "redis://127.0.0.1/",
+ ]
+
+ # Redis Cluster.
+ #
+ # Set this to true when the provided URLs are pointing to a Redis Cluster
+ # instance.
+ cluster=false
+
+ # Key prefix.
+ #
+ # A key prefix can be used to avoid key collisions when multiple deployments
+ # are using the same Redis database and it is not possible to separate
+ # keys by database index (e.g. when using Redis Cluster, which does not
+ # support multiple databases).
+ key_prefix=""
+
+ # Max open connections.
+ #
+ # This sets the max. number of open connections that are allowed in the
+ # Redis connection pool.
+ max_open_connections=100
+
+ # Min idle connections.
+ #
+ # This sets the min. number of idle connections in the Redis connection
+ # pool (0 = equal to max_open_connections).
+ min_idle_connections=0
+
+
+# API interface configuration.
+[api]
+
+ # interface:port to bind the API interface to.
+ bind="0.0.0.0:8080"
+
+ # Secret.
+ #
+ # This secret is used for generating login and API tokens, make sure this
+ # is never exposed. Changing this secret will invalidate all login and API
+ # tokens. The following command can be used to generate a random secret:
+ # openssl rand -base64 32
+ secret=""
+
+
+# Network related configuration.
+[network]
+
+ # Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203).
+ net_id="000000"
+
+ # Enabled regions.
+ #
+ # Multiple regions can be enabled simultaneously. Each region must match
+ # the 'name' parameter of the region configuration in '[[regions]]'.
+ enabled_regions=[
+ "eu868",
+ ]
+
+ # Device session expiration.
+ #
+ # The TTL value defines the time after which a device-session expires
+ # after no activity.
+ device_session_ttl="1month 13h 26m 24s"
+
+ # Mac-commands disabled.
+ mac_commands_disabled=false
+
+
+ # Scheduler settings.
+ [network.scheduler]
+
+ # Scheduler interval.
+ #
+ # The interval in which the downlink scheduler for multicast, Class-B and
+ # Class-C runs.
+ interval="1s"
+
+ # Class-A lock duration.
+ #
+ # This defines the lock duration between receiving a Class-A uplink and
+ # the next scheduler-run for a device. The purpose of this lock is to
+ # avoid collisions between Class-A and Class-B/C downlinks.
+ class_a_lock_duration="5s"
+
+ # Class-C lock duration.
+ #
+ # This defines the lock duration between scheduling two Class-C downlink
+ # payloads for the same device. The purpose of this lock is to avoid
+ # overlap between scheduling Class-C downlinks and / or spreading the
+ # downlink capacity load on the gateway.
+ class_c_lock_duration="5s"
+
+ # Multicast Class-C use GPS time.
+ #
+ # Use GPS time for scheduling multicast class-c downlinks. If this is enabled
+ # and the downlink must be send by multiple gateways to cover all devices
+ # within the multicast-group, these downlinks will be sent at exactly the same
+ # time by these gateways. If disabled, ChirpStack will use the configured
+ # margin. Only enable this features when all gateways have GNSS support.
+ multicast_class_c_use_gps_time=false
+
+ # Multicast Class-C margin.
+ #
+ # This defines the minimum margin between scheduling multiple multicast downlinks
+ # (within the same multicast-group). This value must be equal or greater than the
+ # scheduler interval.
+ multicast_class_c_margin="5s"
+
+ # Multicast Class-B margin.
+ #
+ # This defines the minimum margin between scheduling multiple multicast downlinks
+ # (within the same multicast-group). This value must be equal or greater than the
+ # scheduler interval.
+ multicast_class_b_margin="5s"
+
+
+# Monitoring related configuration.
+[monitoring]
+
+ # Meta-log max history.
+ #
+ # This defines the max number of meta records that will be persisted in Redis Streams.
+ # Setting this value to 0 disables this feature.
+ meta_log_max_history=10
+
+ # Gateway frame-log max history.
+ #
+ # This defines the max number of frame-log records that will be persisted in Redis Streams.
+ # This stream contains the uplink and downlink frames of all gateways.
+ # Setting this value to 0 disables this feature.
+ gateway_frame_log_max_history=10
+
+ # Device frame-log max history.
+ #
+ # This defines the max number of frame-log records that will be persisted in Redis Streams.
+ # This stream contains the uplink and downlink frames of all devices.
+ # Setting this value to 0 disables this feature.
+ device_frame_log_max_history=10
+
+ # Device event-log max history.
+ #
+ # This defines the max number of event-log records that will be persisted in Redis Streams.
+ # This stream contains the events of all devices.
+ # Setting this value to 0 disables this feature.
+ device_event_log_max_history=10
+
+ # Per gateway frame-log max history.
+ #
+ # Equal to the gateway_frame_log_max_history, but for each gateway a new Redis Stream
+ # is created.
+ # Setting this value to 0 disables this feature.
+ per_gateway_frame_log_max_history=10
+
+ # Per gateway frame-log TTL.
+ #
+ # This defines the TTL of the Redis Stream key.
+ per_gateway_frame_log_ttl="1month 13h 26m 24s"
+
+ # Per device frame-log max history.
+ #
+ # Equal to the device_frame_log_max_history, but for each device a new Redis Stream
+ # is created.
+ # Setting this value to 0 disables this feature.
+ per_device_frame_log_max_history=10
+
+ # Per device frame-log TTL.
+ #
+ # This defines the TTL of the Redis Stream key.
+ per_device_frame_log_ttl="1month 13h 26m 24s"
+
+ # Per device event-log max history.
+ #
+ # Equal to the device_event_log_max_history, but for each device a new Redis Stream
+ # is created.
+ # Setting this value to 0 disables this feature.
+ per_device_event_log_max_history=10
+
+ # Per device event-log TTL.
+ #
+ # This defines the TTL of the Redis Stream key.
+ per_device_event_log_ttl="1month 13h 26m 24s"
+
+
+# Global integration related configuration.
+[integration]
+
+ # Enabled integrations (global).
+ enabled = [
+ ]
+
+ # MQTT integration configuration.
+ [integration.mqtt]
+
+ # Event topic template.
+ event_topic="application/{{application_id}}/device/{{dev_eui}}/event/{{event}}"
+
+ # State topic template.
+ #
+ # Events that expose a certain state of the device, are published as retained messages
+ # to the state topic.
+ state_topic="application/{{application_id}}/device/{{dev_eui}}/state/{{state}}"
+
+ # Command topic.
+ #
+ # This is the topic on which the MQTT subscribes for receiving (enqueue) commands.
+ command_topic="application/{{application_id}}/device/{{dev_eui}}/command/{{command}}"
+
+ # Use JSON encoding instead of Protobuf (binary).
+ json=true
+
+ # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws)
+ server="tcp://127.0.0.1:1883/"
+
+ # Connect with the given username (optional)
+ username=""
+
+ # Connect with the given password (optional)
+ password=""
+
+ # Quality of service level
+ #
+ # 0: at most once
+ # 1: at least once
+ # 2: exactly once
+ #
+ # Note: an increase of this value will decrease the performance.
+ # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels
+ qos=0
+
+ # Clean session
+ #
+ # Set the "clean session" flag in the connect message when this client
+ # connects to an MQTT broker. By setting this flag you are indicating
+ # that no messages saved by the broker for this client should be delivered.
+ clean_session=true
+
+ # Client ID
+ #
+ # Set the client id to be used by this client when connecting to the MQTT
+ # broker. A client id must be no longer than 23 characters. When left blank,
+ # a random id will be generated. This requires clean_session=true.
+ client_id=""
+
+ # CA certificate file (optional)
+ #
+ # Use this when setting up a secure connection (when server uses ssl://...)
+ # but the certificate used by the server is not trusted by any CA certificate
+ # on the server (e.g. when self generated).
+ ca_cert=""
+
+ # TLS certificate file (optional)
+ tls_cert=""
+
+ # TLS key file (optional)
+ tls_key=""
+
+
+# Codec configuration.
+[codec]
+
+ # JS codec configuration.
+ [codec.js]
+
+ # Maximum execution time.
+ max_execution_time="100ms"
+
+
+# User authentication configuration.
+[user_authentication]
+
+ # OpenID Connect.
+ [user_authentication.openid_connect]
+
+ # Enable OpenID Connect authentication.
+ #
+ # Enabling this option replaces password authentication.
+ enabled=false
+
+ # Registration enabled.
+ #
+ # Enabling this will automatically register the user when it is not yet present
+ # in the ChirpStack database. There is no registration form as the user information
+ # is automatically received using the OpenID Connect provided information.
+ # The user will not be associated with any organization, but in order to
+ # facilitate the automatic onboarding of users, it is possible to configure a
+ # registration callback URL (next config option).
+ registration_enabled=false
+
+ # Registration callback URL.
+ #
+ # This (optional) endpoint will be called on the registration of the user and
+ # can implement the association of the user with an organization, create a new
+ # organization, ...
+ # ChirpStack will make a HTTP POST call to this endpoint,
+ # with the following URL parameters:
+ # - user_id, of the newly created user in ChirpStack.
+ #
+ # The POST body contains a JSON payload with the OpenID Connect UserInfo payload.
+ registration_callback_url=""
+
+ # Provider URL.
+ # This is the URL of the OpenID Connect provider.
+ # Example: https://auth.example.org
+ provider_url=""
+
+ # Client ID.
+ client_id=""
+
+ # Client secret.
+ client_secret=""
+
+ # Redirect URL.
+ #
+ # This must contain the ChirpStack Application Server web-interface hostname
+ # with '/auth/oidc/callback' path, e.g. https://example.com/auth/oidc/callback.
+ redirect_url=""
+
+ # Logout URL.
+ #
+ # When set, ChirpStack Application Server will redirect to this URL instead
+ # of redirecting to the login page.
+ logout_url=""
+
+ # Login label.
+ #
+ # The login label is used in the web-interface login form.
+ login_label=""
+
+
+# Join Server configuration.
+[join_server]
+
+ # Per Join Server configuration (this can be repeated).
+ # Example:
+ # [[join_server.servers]]
+ #
+ # # JoinEUI of the Join Server.
+ # join_eui="0102030405060708"
+ #
+ # # Server endpoint.
+ # server="https://example.com:1234/join/endpoint"
+
+ # # Use the async interface scheme.
+ # async_interface=false
+
+ # # Async interface request timeout.
+ # async_interface_timeout="1s"
+
+ # # CA certificate (optional).
+ # #
+ # # Set this to validate the join-server server certificate (e.g. if the
+ # # certificate was self-signed).
+ # ca_cert="/path/to/ca.pem"
+
+ # # TLS client-certificate (optional).
+ # #
+ # # Set this to enable client-certificate authentication with the join-server.
+ # tls_cert="/path/to/tls_cert.pem"
+
+ # # TLS client-certificate key (optional).
+ # #
+ # # Set this to enable client-certificate authentication with the join-server.
+ # tls_key="/path/to/tls_key.pem"
+
+
diff --git a/src/chirpstack/configuration.md b/src/chirpstack/configuration.md
new file mode 100644
index 0000000..d6b0b9e
--- /dev/null
+++ b/src/chirpstack/configuration.md
@@ -0,0 +1,336 @@
+# Configuration
+
+To list all CLI options, start `chirpstack` with the `--help` flag. This will
+print:
+
+```text
+ChirpStack open-source LoRaWAN network-server
+
+USAGE:
+ chirpstack --config-dir [SUBCOMMAND]
+
+FLAGS:
+ -h, --help Prints help information
+ -V, --version Prints version information
+
+OPTIONS:
+ -c, --config-dir Path to configuration directory
+
+SUBCOMMANDS:
+ configfile Print the configuration template
+ help Prints this message or the help of the given subcommand(s)
+ print-ds Print the device-session for debugging
+```
+
+## Configuration files
+
+ChirpStack must be started using the `-c` / `--config-dir` argument. This
+directory must contain one or multiple `.toml` configuration files. Typically
+it will contain a single `chirpstack.toml` configuration file for common
+configuration, and multiple `region_...toml` configuration files, one for
+each region configuration.
+
+## Environment variables
+
+Values in the configuration file can be substituted by environment variables.
+Example:
+
+```toml
+[integration.mqtt]
+ server="tcp://$MQTT_BROKER_HOST:1883/"
+ json=true
+```
+
+In the above example, `$MQTT_BROKER_HOST` gets replaced if the `MQTT_BROKER_HOST`
+variable is set, with the value of this environment variable.
+
+## Configuration examples
+
+Configuration examples are included in most ChirpStack distributables. A
+complete overview of configuration examples can be found here:
+[https://github.com/chirpstack/chirpstack/tree/master/chirpstack/configuration](https://github.com/chirpstack/chirpstack/tree/master/chirpstack/configuration)
+
+### Example `chirpstack.toml` configuration
+
+```toml
+{%raw%}
+{{#include chirpstack.toml}}
+{%endraw%}
+```
+
+### Example `region_eu868.toml` configuration
+
+```toml
+{%raw%}
+# This file contains an example EU868 configuration.
+[[regions]]
+
+ # Name is an user-defined identifier for this region.
+ name="eu868"
+
+ # Common-name refers to the common-name of this region as defined by
+ # the LoRa Alliance.
+ common_name="EU868"
+
+
+ # Gateway configuration.
+ [regions.gateway]
+
+ # Force gateways as private.
+ #
+ # If enabled, gateways can only be used by devices under the same tenant.
+ force_gws_private=false
+
+
+ # Gateway backend configuration.
+ [regions.gateway.backend]
+
+ # The enabled backend type.
+ enabled="mqtt"
+
+ # MQTT configuration.
+ [regions.gateway.backend.mqtt]
+
+ # Event topic template.
+ event_topic="eu868/gateway/+/event/+"
+
+ # Command topic template.
+ command_topic="eu868/gateway/{{ gateway_id }}/command/{{ command }}"
+
+ # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws)
+ server="tcp://localhost:1883"
+
+ # Connect with the given username (optional)
+ username=""
+
+ # Connect with the given password (optional)
+ password=""
+
+ # Quality of service level
+ #
+ # 0: at most once
+ # 1: at least once
+ # 2: exactly once
+ #
+ # Note: an increase of this value will decrease the performance.
+ # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels
+ qos=0
+
+ # Clean session
+ #
+ # Set the "clean session" flag in the connect message when this client
+ # connects to an MQTT broker. By setting this flag you are indicating
+ # that no messages saved by the broker for this client should be delivered.
+ clean_session=true
+
+ # Client ID
+ #
+ # Set the client id to be used by this client when connecting to the MQTT
+ # broker. A client id must be no longer than 23 characters. When left blank,
+ # a random id will be generated. This requires clean_session=true.
+ client_id=""
+
+ # CA certificate file (optional)
+ #
+ # Use this when setting up a secure connection (when server uses ssl://...)
+ # but the certificate used by the server is not trusted by any CA certificate
+ # on the server (e.g. when self generated).
+ ca_cert=""
+
+ # TLS certificate file (optional)
+ tls_cert=""
+
+ # TLS key file (optional)
+ tls_key=""
+
+
+ # Gateway channel configuration.
+ #
+ # Note: this configuration is only used in case the gateway is using the
+ # ChirpStack Concentratord daemon. In any other case, this configuration
+ # is ignored.
+ [[regions.gateway.channels]]
+ frequency=868100000
+ bandwidth=125000
+ modulation="LORA"
+ spreading_factors=[7, 8, 9, 10, 11, 12]
+
+ [[regions.gateway.channels]]
+ frequency=868300000
+ bandwidth=125000
+ modulation="LORA"
+ spreading_factors=[7, 8, 9, 10, 11, 12]
+
+ [[regions.gateway.channels]]
+ frequency=868500000
+ bandwidth=125000
+ modulation="LORA"
+ spreading_factors=[7, 8, 9, 10, 11, 12]
+
+ [[regions.gateway.channels]]
+ frequency=867100000
+ bandwidth=125000
+ modulation="LORA"
+ spreading_factors=[7, 8, 9, 10, 11, 12]
+
+ [[regions.gateway.channels]]
+ frequency=867300000
+ bandwidth=125000
+ modulation="LORA"
+ spreading_factors=[7, 8, 9, 10, 11, 12]
+
+ [[regions.gateway.channels]]
+ frequency=867500000
+ bandwidth=125000
+ modulation="LORA"
+ spreading_factors=[7, 8, 9, 10, 11, 12]
+
+ [[regions.gateway.channels]]
+ frequency=867700000
+ bandwidth=125000
+ modulation="LORA"
+ spreading_factors=[7, 8, 9, 10, 11, 12]
+
+ [[regions.gateway.channels]]
+ frequency=867900000
+ bandwidth=125000
+ modulation="LORA"
+ spreading_factors=[7, 8, 9, 10, 11, 12]
+
+ [[regions.gateway.channels]]
+ frequency=868300000
+ bandwidth=250000
+ modulation="LORA"
+ spreading_factors=[7]
+
+ [[regions.gateway.channels]]
+ frequency=868800000
+ bandwidth=125000
+ modulation="FSK"
+ datarate=50000
+
+
+ # Region specific network configuration.
+ [regions.network]
+
+ # Installation margin (dB) used by the ADR engine.
+ #
+ # A higher number means that the network-server will keep more margin,
+ # resulting in a lower data-rate but decreasing the chance that the
+ # device gets disconnected because it is unable to reach one of the
+ # surrounded gateways.
+ installation_margin=10
+
+ # RX window (Class-A).
+ #
+ # Set this to:
+ # 0: RX1 / RX2
+ # 1: RX1 only
+ # 2: RX2 only
+ rx_window=0
+
+ # RX1 delay (1 - 15 seconds).
+ rx1_delay=1
+
+ # RX1 data-rate offset
+ rx1_dr_offset=0
+
+ # RX2 data-rate
+ rx2_dr=0
+
+ # RX2 frequency (Hz)
+ rx2_frequency=869525000
+
+ # Prefer RX2 on RX1 data-rate less than.
+ #
+ # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate
+ # is smaller than the configured value, then the Network Server will
+ # first try to schedule the downlink for RX2, failing that (e.g. the gateway
+ # has already a payload scheduled at the RX2 timing) it will try RX1.
+ rx2_prefer_on_rx1_dr_lt=0
+
+ # Prefer RX2 on link budget.
+ #
+ # When the link-budget is better for RX2 than for RX1, the Network Server will first
+ # try to schedule the downlink in RX2, failing that it will try RX1.
+ rx2_prefer_on_link_budget=false
+
+ # Downlink TX Power (dBm)
+ #
+ # When set to -1, the downlink TX Power from the configured band will
+ # be used.
+ #
+ # Please consult the LoRaWAN Regional Parameters and local regulations
+ # for valid and legal options. Note that the configured TX Power must be
+ # supported by your gateway(s).
+ downlink_tx_power=-1
+
+ # ADR is disabled.
+ adr_disabled=false
+
+ # Minimum data-rate.
+ min_dr=0
+
+ # Maximum data-rate.
+ max_dr=5
+
+
+ # Rejoin-request configuration (LoRaWAN 1.1)
+ [regions.network.rejoin_request]
+
+ # Request devices to periodically send rejoin-requests.
+ enabled=false
+
+ # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4)
+ # uplink messages. Valid values are 0 to 15.
+ max_count_n=0
+
+ # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10)
+ # seconds. Valid values are 0 to 15.
+ #
+ # 0 = roughly 17 minutes
+ # 15 = about 1 year
+ max_time_n=0
+
+
+ # Class-B configuration.
+ [regions.network.class_b]
+
+ # Ping-slot data-rate.
+ ping_slot_dr=0
+
+ # Ping-slot frequency (Hz)
+ #
+ # set this to 0 to use the default frequency plan for the configured region
+ # (which could be frequency hopping).
+ ping_slot_frequency=0
+
+
+ # Below is the common set of extra channels. Please make sure that these
+ # channels are also supported by the gateways.
+ [[regions.network.extra_channels]]
+ frequency=867100000
+ min_dr=0
+ max_dr=5
+
+ [[regions.network.extra_channels]]
+ frequency=867300000
+ min_dr=0
+ max_dr=5
+
+ [[regions.network.extra_channels]]
+ frequency=867500000
+ min_dr=0
+ max_dr=5
+
+ [[regions.network.extra_channels]]
+ frequency=867700000
+ min_dr=0
+ max_dr=5
+
+ [[regions.network.extra_channels]]
+ frequency=867900000
+ min_dr=0
+ max_dr=5
+{%endraw%}
+```
diff --git a/src/chirpstack/downloads.md b/src/chirpstack/downloads.md
new file mode 100644
index 0000000..ec309a2
--- /dev/null
+++ b/src/chirpstack/downloads.md
@@ -0,0 +1,40 @@
+# Downloads
+
+## Binaries
+
+| File name | Type | OS | Arch |
+| --------- | ---- | -- | ---- |
+| [chirpstack_{{chirpstack_version}}_linux_amd64.deb](https://artifacts.chirpstack.io/downloads/chirpstack/chirpstack_{{chirpstack_version}}_linux_amd64.deb) | .deb | Linux | amd64 |
+| [chirpstack_{{chirpstack_version}}_linux_arm64.deb](https://artifacts.chirpstack.io/downloads/chirpstack/chirpstack_{{chirpstack_version}}_linux_arm64.deb) | .deb | Linux | arm64 |
+| [chirpstack_{{chirpstack_version}}_linux_amd64.tar.gz](https://artifacts.chirpstack.io/downloads/chirpstack/chirpstack_{{chirpstack_version}}_linux_amd64.tar.gz) | .tar.gz | Linux | amd64 |
+| [chirpstack_{{chirpstack_version}}_linux_arm64.tar.gz](https://artifacts.chirpstack.io/downloads/chirpstack/chirpstack_{{chirpstack_version}}_linux_arm64.tar.gz) | .tar.gz | Linux | arm64 |
+| [chirpstack_{{chirpstack_version}}_linux_amd64.rpm](https://artifacts.chirpstack.io/downloads/chirpstack/chirpstack_{{chirpstack_version}}_linux_amd64.rpm) | .rpm | Linux | amd64 |
+| [chirpstack_{{chirpstack_version}}_linux_arm64.rpm](https://artifacts.chirpstack.io/downloads/chirpstack/chirpstack_{{chirpstack_version}}_linux_arm64.rpm) | .rpm | Linux | arm64 |
+
+
+## Debian / Ubuntu repository
+
+ChirpStack provides pre-compiled binaries as Debian (`.deb`) packages. To
+activate this repository, execute the following commands:
+
+```bash
+sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1CE2AFD36DBCCA00
+
+sudo echo "deb https://artifacts.chirpstack.io/packages/4.x/deb stable main" | sudo tee /etc/apt/sources.list.d/chirpstack_4.list
+sudo apt update
+```
+
+ChirpStack also provides a repository for test-builds. To activate the test
+channel use the following commands (notice that `stable` has changed into `testing`):
+
+```bash
+sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1CE2AFD36DBCCA00
+
+sudo echo "deb https://artifacts.chirpstack.io/packages/4.x/deb testing main" | sudo tee /etc/apt/sources.list.d/chirpstack_4.list
+sudo apt update
+```
+
+## Docker
+
+For Docker images, please refer to
+[https://hub.docker.com/r/chirpstack/chirpstack](https://hub.docker.com/r/chirpstack/chirpstack/tags)
diff --git a/src/chirpstack/features/device-activation.md b/src/chirpstack/features/device-activation.md
new file mode 100644
index 0000000..ab96044
--- /dev/null
+++ b/src/chirpstack/features/device-activation.md
@@ -0,0 +1 @@
+# Device activation
diff --git a/src/chirpstack/features/index.md b/src/chirpstack/features/index.md
new file mode 100644
index 0000000..ead0223
--- /dev/null
+++ b/src/chirpstack/features/index.md
@@ -0,0 +1 @@
+# Features
diff --git a/src/chirpstack/features/multi-reagion.md b/src/chirpstack/features/multi-reagion.md
new file mode 100644
index 0000000..9b25166
--- /dev/null
+++ b/src/chirpstack/features/multi-reagion.md
@@ -0,0 +1,41 @@
+# Multi-region
+
+ChirpStack supports multiple regions simultaneously, without the need to start
+multiple ChirpStack instances (like it was needed in ChirpStack v3). It is also
+possible to configure the same region more than once, to support for example a
+mix of 8-channel and 16-channel gateways.
+
+There are two terms that are important:
+
+* **Region name**, which is a user-defined name for a region configuration, this can be anything.
+* **Region common name**, wich is the region common name as defined by the LoRa Alliance.
+
+In the ChirpStack configuration examples, you will find for example region name
+`us915_0` for the channels 0 - 7 configuration, `us915_1` for the channels
+8 - 15 configuration etc...
+
+Each region configuration contains its own gateway backend configuration.
+Either a single MQTT broker can be used for all different regions, or multiple
+MQTT brokers can be used (e.g. for each region a separate MQTT broker).
+
+ChirpStack will automatically assign the _region name_ and _region common name_
+to each gateway, based on the receiving gateway backend.
+
+## Single MQTT broker
+
+The advantage of a single MQTT broker is the ease of setup. Adding a new
+region is changing the ChirpStack configuration and there is no need to deploy
+new MQTT brokers.
+
+However, it is important that each region uses its own MQTT topic prefix, to
+separate the MQTT message flows between regions. It is a good practice to use
+the _region name_ as topic prefix for the gateway.
+
+## Multiple MQTT brokers
+
+The advantage of multiple MQTT brokers can be scalability. Each region
+configuration can have its own MQTT broker, and therefore the load of one
+region does not impact the load of an other region (MQTT broker).
+
+As message flows for the different region configurations is separated by MQTT
+broker instance, there is no need to add a region specific topic prefix.
diff --git a/src/chirpstack/index.md b/src/chirpstack/index.md
new file mode 100644
index 0000000..dda3bad
--- /dev/null
+++ b/src/chirpstack/index.md
@@ -0,0 +1,2 @@
+# ChirpStack
+
diff --git a/src/context.json b/src/context.json
new file mode 100644
index 0000000..5f22e2a
--- /dev/null
+++ b/src/context.json
@@ -0,0 +1,4 @@
+{
+ "chirpstack_version": "4.0.0-test.5",
+ "gateway_os_version": "4.0.0-test.1"
+}
diff --git a/src/gateway-os/changelog.md b/src/gateway-os/changelog.md
new file mode 100644
index 0000000..aa6126b
--- /dev/null
+++ b/src/gateway-os/changelog.md
@@ -0,0 +1,50 @@
+# Changelog
+
+## v4.0.0 (in development)
+
+### Main changes
+
+#### ChirpStack v4
+
+This release replaces ChirpStack Network Server (v3) and ChirpStack Application
+Server (v3) with ChirpStack v4.0.0.
+
+#### MQTT certificates
+
+If using the _full_ image, MQTT TLS certificates will be automatically generated on
+first boot and configured in ChirpStack. For consuming device events throug the
+MQTT integration, you can generate certificates in the web-interface under
+the application integrations.
+
+**Note:** localhost connections (e.g. if using Node-RED) to the MQTT do not
+need TLS certificates for authentication and authorization.
+
+#### gateway-config improvements
+
+If using the _full_ ChirpStack Gateway OS image, which includes the ChirpStack
+Network Server, the `gateway-config` script will automatically create the
+gateway in the ChirpStack database for you.
+
+#### Region configuration
+
+The _full_ image contains update region configuration for the common regions.
+The desired region can be selected using the `gateway-config` configuration script.
+
+#### New shields
+
+Support for the following shields has been added:
+
+- RAK2247
+- RAK5147
+
+#### Yocto Kirkstone
+
+ChirpStack Gateway OS has been updated to Yocto Kirkstone. This should fix
+boot problems on some Pi 4 revisions, as this release contains an updated
+bootloader.
+
+### Other updates
+
+* ChirpStack Concentratord to v3.2.2
+* ChirpStack Gateway Bridge to v3.13.1
+* Node-RED to v2.1.6
diff --git a/src/gateway-os/contribute.md b/src/gateway-os/contribute.md
new file mode 100644
index 0000000..877cbf8
--- /dev/null
+++ b/src/gateway-os/contribute.md
@@ -0,0 +1,56 @@
+# Contribute
+
+## Links
+
+- Community forum: [https://forum.chirpstack.io/](https://forum.chirpstack.io/)
+- Source repository: [https://github.com/brocaar/chirpstack-gateway-os](https://github.com/brocaar/chirpstack-gateway-os)
+ - Issue and bug reports: [https://github.com/brocaar/chirpstack-gateway-os/issues](https://github.com/brocaar/chirpstack-gateway-os/issues)
+
+
+## Building from source
+
+The ChirpStack Gateway OS uses [Docker](https://www.docker.com/) and
+[Docker Compose](https://docs.docker.com/compose/). Make sure you have
+these tools installed.
+
+
+### Initial setup
+
+Run the following command to set the `/build` folder permissions:
+
+```bash
+# on the host
+docker-compose run --rm busybox
+
+# within the container
+chown 999:999 /build
+```
+
+### Building
+
+Run the following command to setup the build environment:
+
+```bash
+# on the host
+docker-compose run --rm yocto bash
+
+# within the container
+
+# update the submodules
+make submodules
+
+# initialize the yocto / openembedded build environment
+source oe-init-build-env /build/ /chirpstack-gateway-os/bitbake/
+
+
+# build the chirpstack-gateway-os-base image
+bitbake chirpstack-gateway-os-base
+```
+
+#### Configuration
+
+By default, Raspberry Pi3 is configured as the target platform. You need to
+update the following configuration files to configure a different target:
+
+* `/build/config/local.conf`
+* `/build/config/bblayers.conf`
diff --git a/src/gateway-os/downloads.md b/src/gateway-os/downloads.md
new file mode 100644
index 0000000..0632a40
--- /dev/null
+++ b/src/gateway-os/downloads.md
@@ -0,0 +1,32 @@
+# Downloads
+
+## Image types
+
+There are two file types:
+
+* `.wic.gz` - Image to use for an initial installation
+* `.swu` - Software update file, see [Software update](../use/software-update.md)
+
+## Image links
+
+* [Raspberry Zero W](http://artifacts.chirpstack.io/downloads/chirpstack-gateway-os/raspberrypi/raspberrypi0-wifi/{{gateway_os_version}}/)
+* [Raspberry Pi 1](http://artifacts.chirpstack.io/downloads/chirpstack-gateway-os/raspberrypi/raspberrypi/{{gateway_os_version}}/)
+* [Raspberry Pi 3](http://artifacts.chirpstack.io/downloads/chirpstack-gateway-os/raspberrypi/raspberrypi3/{{gateway_os_version}}/)
+* [Raspberry Pi 4](http://artifacts.chirpstack.io/downloads/chirpstack-gateway-os/raspberrypi/raspberrypi4/{{gateway_os_version}}/)
+
+## SD card flashing
+
+### Using Balena Etcher
+
+* Download the SD card image for your Raspberry Pi (ending with `.wic.gz`).
+* Click the **Flash from file** option in the [Balena Etcher](https://www.balena.io/etcher/) interface.
+* Flash the SD card.
+
+### Using Win32DiskImager
+
+* Download the SD card image for your Raspberry Pi (ending with `.wic.gz`).
+* Extract the `.wic.gz` image using for example [7-Zip](https://www.7-zip.org/).
+* Within the [Win32DiskImager](http://sourceforge.net/projects/win32diskimager/) interface, select the extracted `.wic` file.
+ Please note that you must select the `*.*` filter in the _Select a disk image_ popup before you can select the `.wic` file.
+* Flash the SD card.
+
diff --git a/src/gateway-os/gateway-config.png b/src/gateway-os/gateway-config.png
new file mode 100644
index 0000000..0db7228
Binary files /dev/null and b/src/gateway-os/gateway-config.png differ
diff --git a/src/gateway-os/guides/getting-started.md b/src/gateway-os/guides/getting-started.md
new file mode 100644
index 0000000..521f568
--- /dev/null
+++ b/src/gateway-os/guides/getting-started.md
@@ -0,0 +1,116 @@
+# Getting started
+
+These steps describe how to get started with ChirpStack Gateway OS **after** you
+have installed ChirpStack Gateway OS on your gateway.
+
+**Important:** The **chirpstack-gateway-os-full** image will setup the PostgreSQL
+on its first boot. This could take a couple of minutes and during this time,
+the gateway will be less responsive!
+
+## Connecting
+
+After booting the gateway, you need to login using SSH. In case the gateway
+running the ChirpStack Gateway OS supports Wi-Fi, then it will be configured
+as access-point with the name `ChirpStackAP` and password `ChirpStackAP`.
+Once connected with `ChirpStackAP` the IP of the gateway is `192.168.0.1`.
+
+If you are connected using ethernet, then it uses DHCP to obtain an IP address.
+Many internet routers provide a web-interface with the IP addresses of connected
+devices.
+
+If the IP of your gateway is `192.168.0.1`:
+
+```bash
+ssh admin@192.168.0.1
+```
+
+The default username is `admin`, the default password is `admin`.
+
+This will prompt the following message:
+
+```text
+ ________ _ _____ __ __ _
+ / ____/ /_ (_)________ / ___// /_____ ______/ /__ (_)___
+ / / / __ \/ / ___/ __ \\__ \/ __/ __ `/ ___/ //_/ / / __ \
+/ /___/ / / / / / / /_/ /__/ / /_/ /_/ / /__/ ,< _ / / /_/ /
+\____/_/ /_/_/_/ / .___/____/\__/\__,_/\___/_/|_(_)_/\____/
+ /_/
+
+Documentation and copyright information:
+> www.chirpstack.io
+
+Commands:
+> sudo gateway-config - configure the gateway
+> sudo monit status - display service monitor
+```
+
+## Configuration
+
+Execute the `sudo gateway-config` to configure the concentrator shield model
+and the channel-configuration that the gateway must use.
+
+### Base image
+
+After the board and channel-plan have been configured, you must update the
+ChirpStack Gateway Bridge configuration, such that it connects to your MQTT
+broker. This can be done using the **Edit ChirpStack Gateway Bridge config**
+option in the `gateway-config` menu.
+
+Use the **Edit configuration file** option to edit the configuration file or
+the **MQTT connection wizzard**. In case you are using (client-)certificate
+authentication / authorization, the latter is recommended as it allows you
+do directly paste the certificate files.
+
+## Full image
+
+Unlike the **chirpstack-gateway-os-base** image, you **should not** update the
+ChirpStack Gateway Bridge configuration. It is configured to point to the MQTT broker
+which comes with the **chirpstack-gateway-os-full** image.
+
+If using the **chirpstack-gateway-os-full** image and after configuring the
+channel-plan, the gateway will be automatically added to ChirpStack. In case
+the `gateway-config` displays an error during this step, it is recommended to
+wait ~ 30 seconds and try again. On first boot, it might take some time to
+setup the database (which happens on the background) and during this process
+it is normal to see an error message.
+
+### Access ChirpStack web-interface
+
+To access the web-interface, you need the IP address of the Raspberry Pi. If it
+is still in Wi-Fi access-point mode, the IP will be `192.168.0.1`, else you
+can usually retrieve the assigned IP address from your internet modem.
+
+Assuming its IP address is `192.168.0.1`, enter the following address in your
+browser to access the web-interface: `http://192.168.0.1:8080`.
+
+The default login credentials are: `admin` / `admin`.
+
+### Create device profile
+
+After login, the first thing to do is creating a device profile. A device
+profile stores the properties for a certain device type (e.g. brand, model, ...)
+that are important for ChirpStack to correctly handle your devices. To do
+so, click **Device profiles** and then **Add device profile**.
+
+**Note:** It is important that the _Region_ field matches the region that you
+have configured using `gateway-config`.
+
+### Create application
+
+To group simmilar devices together, you need to create an application. This can
+be done by clicking **Applications** and then **Add application**.
+
+### Create first device
+
+After creating the application, you are directly redirected to the created
+application, with the _Devices_ tab enabled. You can add your device by clicking
+the **Add device** button.
+
+## Important to know
+
+### SD Card wearout
+
+Although ChirpStack will try to minimize the number of database writes, there
+will be regular writes to the SD Card (PostgreSQL and Redis snapshots).
+According to [Is it true that a SD/MMC Card does wear levelling with its own controller?](https://electronics.stackexchange.com/questions/27619/is-it-true-that-a-sd-mmc-card-does-wear-levelling-with-its-own-controller)
+it might make a difference which SD Card brand you use.
diff --git a/src/gateway-os/guides/index.md b/src/gateway-os/guides/index.md
new file mode 100644
index 0000000..50a8673
--- /dev/null
+++ b/src/gateway-os/guides/index.md
@@ -0,0 +1 @@
+# Guides
diff --git a/src/gateway-os/guides/node-red-echo-flow.png b/src/gateway-os/guides/node-red-echo-flow.png
new file mode 100644
index 0000000..4c491bd
Binary files /dev/null and b/src/gateway-os/guides/node-red-echo-flow.png differ
diff --git a/src/gateway-os/guides/node-red.md b/src/gateway-os/guides/node-red.md
new file mode 100644
index 0000000..1b72ed7
--- /dev/null
+++ b/src/gateway-os/guides/node-red.md
@@ -0,0 +1,136 @@
+# Node-RED
+
+[Node-RED](https://nodered.org/) provides a browser-based flow editor that makes
+it easy to wire together flows using the wide range of nodes in the palette.
+
+If you have installed the **chirpstack-gateway-os-full** image, then Node-RED
+comes pre-installed with ChirpStack Gateway OS since v3.5.0, including the
+[node-red-contrib-chirpstack](https://github.com/brocaar/node-red-contrib-chirpstack/)
+package which provides several nodes to interact with ChirpStack.
+
+## Enabling Node-RED
+
+By default, Node-RED is disabled and must be enabled through the `gateway-config`
+utility. In the root menu, select **Enable / disable applications** and then
+**Enable Node-RED**. Note that once enabled, the option will change to
+**Disable Node-RED**. Starting Node-RED will take some time (~ one minute).
+
+## Access Node-RED
+
+Once started, Node-RED is accessible in your browser on port
+`http://[IP ADDRESS]:1880`. This means that if the IP address of your gateway
+is `192.168.0.1`, that you can access Node-RED at `http://192.168.0.1:1880`.
+
+### Building an echo flow
+
+
+
+Below steps describe how to build an echo flow, which will enqueue the received
+uplink from the device as downlink. While this probably doesn't cover a real
+use-case, it does demonstrate how to receive uplink messages, process these
+and schedule downlinks.
+
+It is assumed that you already have setup your gateway and device. It is also
+assumed that you have some basic knowledge about Node-RED.
+
+#### Receive from MQTT
+
+After opening Node-RED in your browser, first setup a **mqtt in** node. This
+node will be used to receive device events that are published by the MQTT
+broker that is running on the gateway (provided by the ChirpStack Gateway OS).
+
+The following node properties must be set:
+
+* Server:
+ * Server: `localhost`
+ * Port: `1883`
+* Topic: `application/+/device/+/event/+`
+* QoS: `0`
+* Output: *auto-detect*
+
+To test the connection to the MQTT broker, **Deploy** the flow. Under the newly
+added node you should see a label *Connected*.
+
+#### Parse events
+
+Now that you are able to receive events from MQTT, setup a **device event**
+node (you will find this node under the ChirpStack section). This node parses
+the payloads generated by the **mqtt in** node to objects and it will perform
+filtering based on event types.
+
+The following node properties must be set:
+
+* Event Type: *Uplink*
+
+Connect the output side of the **mqtt in** node with the input side of the
+**device event** node.
+
+#### Debug events
+
+For debugging, add a **debug** node and connect it to the **device event**
+output and re-**Deploy** the flow. Open the debug messages tab in the Node-RED
+interface. When one of your devices sends an uplink, you should see the uplink
+event as debug message.
+
+#### Echo payload function
+
+To model the uplink event as downlink enqueue payload, add a **function** node
+and connect the input to the output of the **device event** node.
+
+The following node properties must be set:
+
+**On Message**
+
+```js
+return {
+ devEui: msg.payload.deviceInfo.devEui,
+ fPort: msg.payload.fPort,
+ confirmed: false,
+ payload: msg.payload.data
+};
+```
+
+This will make the **function** node output a message that can be used with the
+**device downlink** node, which will be added in the next step.
+
+#### Enqueue downlink
+
+**Note:** For this step you need to obtain an API token from the ChirpStack
+web-interface first!
+
+To send the downlink message generated by the echo function to ChirpStack, add
+a **device downlink** node and connect the input to the output of the
+**function** node.
+
+The following node properties must be set:
+
+* Server: `localhost:8080`
+* API token: *the API token obtained from the ChirpStack web-interface*
+* Payload Encoding: *Base64*
+
+#### Enqueue output (debug)
+
+To view the message generated by the **device downlink** node, add an other
+**debug** node and connect the input to the output of the **device downlink**
+node.
+
+The following node properties must be set:
+
+* Output: *complete msg object*
+
+#### Testing the flow
+
+Make sure to re-**Deploy** the flow, so that all changes are deployed. When
+sending an uplink frame, you should see two messages in the debug panel:
+
+* The uplink event
+* The response from the downlink enqueue
+
+An example of the downlink enqueue output:
+
+```
+{"id": "c0768c9a-3ff3-4855-846c-7fdfa8894666", "_msgid": "a8264ce66a2c4830"}
+```
+
+**Note:** it is possible that the device receives the downlink after the next
+uplink message.
diff --git a/src/gateway-os/image-types.md b/src/gateway-os/image-types.md
new file mode 100644
index 0000000..64210c9
--- /dev/null
+++ b/src/gateway-os/image-types.md
@@ -0,0 +1,18 @@
+# Image types
+
+## Base
+
+The **chirpstack-gateway-os-base** image provides all the features and components
+to use a Raspberry Pi as LoRa gateway, forwarding data to an external server.
+
+- ChirpStack Concentratord
+- ChirpStack Gateway Bridge
+- Gateway configuration utility (`gateway-config`)
+
+## Full
+
+The **chirpstack-gateway-os-full** provides all the features of the
+**chirpstack-gateway-os-base** image, but is also bundled with the ChirpStack
+Network Server and all requirements to run a complete LoRaWAN stack on the
+Raspberry Pi. As all components are pre-configured, this is ideal when getting
+started with LoRaWAN.
diff --git a/src/gateway-os/index.md b/src/gateway-os/index.md
new file mode 100644
index 0000000..25949fd
--- /dev/null
+++ b/src/gateway-os/index.md
@@ -0,0 +1,50 @@
+# Introduction
+
+ChirpStack Gateway OS is an open-source Linux based embedded OS which can run on
+various LoRa® gateway models. The goal is to make it easy to get started with
+LoRaWAN® and the ChirpStack open-source LoRaWAN Network Server stack with the minimum steps required to setup
+your gateway(s).
+
+
+
+## Supported targets
+
+* [x] Raspberry Pi Zero W
+* [x] Raspberry Pi 1
+* [x] Raspberry Pi 3
+* [x] Raspberry Pi 4
+
+## Supported shields
+
+### IMST
+
+* [x] [IMST - iC880A](https://wireless-solutions.de/products/long-range-radio/ic880a.html)
+* [x] [IMST - iC980A](http://www.imst.com/)
+* [x] [IMST - Lite Gateway](https://wireless-solutions.de/products/long-range-radio/lora-lite-gateway.html)
+
+### Pi Supply
+
+* [x] [Pi Supply - LoRa Gateway Hat](https://uk.pi-supply.com/products/iot-lora-gateway-hat-for-raspberry-pi)
+
+### RAK Wireless
+
+* [x] [RAK - RAK2245](https://store.rakwireless.com/products/rak2245-pi-hat)
+* [x] [RAK - RAK2246 / RAK2246G](https://store.rakwireless.com/products/rak7246-lpwan-developer-gateway)
+* [x] [RAK - RAK2247](https://store.rakwireless.com/products/rak2247-lpwan-gateway-concentrator-module)
+* [x] [RAK - RAK2287](https://store.rakwireless.com/products/rak2287-lpwan-gateway-concentrator-module)
+* [x] [RAK - RAK5146](https://store.rakwireless.com/products/wislink-lpwan-concentrator-rak5146)
+* [x] [RAK - RAK831](https://store.rakwireless.com/products/rak831-gateway-module)
+
+### RisingHF
+
+* [x] [RisingHF - RHF0M301 LoRaWAN IoT Discovery Kit](http://risinghf.com/#/product-details?product_id=9&lang=en)
+
+### Sandbox
+
+* [x] [Sandbox Electronics - LoRaGo PORT](https://sandboxelectronics.com/?product=lorago-port-multi-channel-lorawan-gateway)
+
+### Semtech
+
+* [x] [Semtech - SX1302 evaluation kit](https://www.semtech.com/products/wireless-rf/lora-core/sx1302cxxxgw1)
+* [x] [Semtech - SX1280 2.4 GHz evaluation kit](https://www.semtech.com/products/wireless-rf/lora-24ghz/sx1280zxxxxgw1)
+
diff --git a/src/gateway-os/use/gateway-config.md b/src/gateway-os/use/gateway-config.md
new file mode 100644
index 0000000..aa49de2
--- /dev/null
+++ b/src/gateway-os/use/gateway-config.md
@@ -0,0 +1,19 @@
+# Configuration
+
+ChirpStack Gateway OS comes with an utility called `gateway-config` for
+the configuration of the gateway and the services running on the gateway.
+
+This utility can be accessed using SSH. Use the following command to SSH
+into the gateway (in this example, the IP of the gateway is `192.168.0.1`):
+
+```bash
+ssh admin@192.168.0.1
+```
+
+The default username is admin, the default password is admin.
+
+Then start the `gateway-config` utility as `root` user:
+
+```bash
+sudo gateway-config
+```
diff --git a/src/gateway-os/use/index.md b/src/gateway-os/use/index.md
new file mode 100644
index 0000000..ea7ce31
--- /dev/null
+++ b/src/gateway-os/use/index.md
@@ -0,0 +1 @@
+# Use
diff --git a/src/gateway-os/use/log-files.md b/src/gateway-os/use/log-files.md
new file mode 100644
index 0000000..845a03c
--- /dev/null
+++ b/src/gateway-os/use/log-files.md
@@ -0,0 +1,21 @@
+# Log files
+
+The ChirpStack components are writing their log output to [Syslog](https://en.wikipedia.org/wiki/Syslog),
+which writes to `/var/log/messages`.
+
+## All logs
+
+To view the logs, run:
+
+```bash
+sudo tail -f /var/log/messages
+```
+
+## By service
+
+To filter the messages by a specific service (e.g. `chirpstack-concentratord`),
+run:
+
+```bash
+sudo tail -f /var/log/messages |grep chirpstack-concentratord
+```
diff --git a/src/gateway-os/use/modifying-files.md b/src/gateway-os/use/modifying-files.md
new file mode 100644
index 0000000..7378388
--- /dev/null
+++ b/src/gateway-os/use/modifying-files.md
@@ -0,0 +1,17 @@
+# Modifying files
+
+ChirpStack Gateway OS uses an [OverlayFS](https://en.wikipedia.org/wiki/OverlayFS)
+on top of the read-only root filesystem. This means you can make modifications that
+are persisted even after a software update as these changes are written to a
+different data partition.
+
+## Important
+
+Although this gives the complete freedom to make modifications to the root
+filesystem, it also means that once you make a modification a ChirpStack Gateway OS
+update will never "overwrite" this changed file. In reality, a ChirpStack Gateway OS
+update will still update the file on the root filesystem, the OverlayFS will
+present you the file from the data partition.
+
+To "rollback" changes, you can simply remove these from `/data/upperdir`.
+Removing all the content from `/data/upperdir` would effectively be a "factory reset".
diff --git a/src/gateway-os/use/monitoring.md b/src/gateway-os/use/monitoring.md
new file mode 100644
index 0000000..06ddbfb
--- /dev/null
+++ b/src/gateway-os/use/monitoring.md
@@ -0,0 +1,37 @@
+# Monitoring
+
+ChirpStack Gateway OS uses [Monit](https://mmonit.com/monit/) for monitoring
+the ChirpStack components. It will periodically check if the configured services
+are still running and if not, re-try to start them. It also allows for
+monitoring the usage of resources (e.g. memory, cpu) and restart services
+after a configured threshold. Please refer to the
+[Monit manual](https://mmonit.com/monit/documentation/monit.html) for more
+information.
+
+## Command examples
+
+To list the status of all monitored services, you need to run:
+
+```bash
+sudo monit status
+```
+
+To stop, start or restart a service, you need to run:
+
+```bash
+# start
+sudo monit start SERVICE
+
+# stop
+sudo monit stop SERVICE
+
+# restart
+sudo monit restart SERVICE
+```
+
+## Important to know
+
+Monit uses the `/etc/init.d/SERVICE` scripts to start these services. This
+means you can also (for example) stop a service using `/etc/init.d/SERVICE stop`,
+however Monit will then detect this as a failed service and will automatically
+restart it.
diff --git a/src/gateway-os/use/software-update.md b/src/gateway-os/use/software-update.md
new file mode 100644
index 0000000..0bf0746
--- /dev/null
+++ b/src/gateway-os/use/software-update.md
@@ -0,0 +1,32 @@
+# Software updates
+
+ChirpStack Gateway OS uses [SWUpdate](https://github.com/sbabic/swupdate) for handling updates.
+SWUpdate is open-source and can be used either as a CLI utility on the gateway
+or it can be integrated with [Eclipse hawkBit](https://www.eclipse.org/hawkbit/).
+
+## Partition layout
+
+ChirpStack Gateway OS uses 4 partitions:
+
+* Boot partition
+* RootFS partition A
+* RootFS partition B
+* Data partition (used for OverlayFS)
+
+One RootFS partition is used for booting, the other for the next update.
+The bootloader will automatically revert to the last functioning RootFS
+partition on a failed update.
+
+## CLI update
+
+After downloading the update file (`.swu`) on the gateway, execute the `software-update`
+utility:
+
+```bash
+sudo software-update path/to/update.swu
+```
+
+Please refer to the install section to find the correct `.swu` artifact for
+your gateway.
+
+After `software-update` has completed, reboot the gateway.
diff --git a/src/index.md b/src/index.md
new file mode 100644
index 0000000..59422c5
--- /dev/null
+++ b/src/index.md
@@ -0,0 +1,43 @@
+# The ChirpStack project
+
+ChirpStack is an open-source LoRaWAN Network Server which can be used to
+to setup private or public LoRaWAN networks. ChirpStack provides a web-interface
+for the management of gateways, devices and tenants as well to setup data
+integrations with the major cloud providers, databases and services commonly
+used for handling device data.
+
+### Supported regions
+
+- [x] AS923, AS923-2, AS923-3, AS923-4
+- [x] AU915
+- [x] CN470
+- [x] CN779
+- [x] EU433
+- [x] EU868
+- [x] IN865
+- [x] KR920
+- [x] RU864
+- [x] US915
+- [x] ISM2400 (LoRaWAN 2.4 GHz)
+
+### Device classes
+
+- [x] Class A
+- [x] Class B unicast & multicast
+- [x] Class C unicast & multicast
+
+### LoRaWAN versions
+
+- [x] LoRaWAN 1.0.0
+- [x] LoRaWAN 1.0.1
+- [x] LoRaWAN 1.0.2
+- [x] LoRaWAN 1.0.3
+- [x] LoRaWAN 1.0.4
+- [x] LoRaWAN 1.1.0
+
+### Regional parameter revisions
+
+- [x] RP002-1.0.0
+- [x] RP002-1.0.1
+- [x] RP002-1.0.2
+- [x] RP002-1.0.3
diff --git a/src/v3-v4-migration.md b/src/v3-v4-migration.md
new file mode 100644
index 0000000..a9e0f72
--- /dev/null
+++ b/src/v3-v4-migration.md
@@ -0,0 +1,96 @@
+# ChirpStack v3 to v4 migration
+
+The purpose of this document is to describe the steps needed to migrate
+data from ChirpStack v3 to ChirpStack v4.
+
+## Preparation
+
+### ChirpStack Application Server
+
+Please make sure to upgrade to the latest v3 version. It is recommended to
+make a database backup.
+
+### ChirpStack Network Server
+
+Please make sure to upgrade to the latest v3 version. It is recommended to
+make a database backup.
+
+### ChirpStack Gateway Bridge
+
+Please make sure to upgrade to the latest v3 version.
+
+ChirpStack v4 supports the latest ChirpStack Gateway Bridge v3, but it does
+require the `marshaler` option to be set to `protobuf` (this is the default).
+Once ChirpStack Gateway Bridge v4 has been released, it will be possible again
+to use the `json` `marshaler` option for debugging purposes.
+
+### ChirpStack (v4)
+
+Please make sure that the latest ChirpStack v4 version has been installed
+and is up and running. You must create a new PostgreSQL database, while not
+strictly required, it is also recommended to create a new Redis server.
+
+**Note:** Do not create any gateways and devices yet, as the migration script
+will delete all objects from the ChirpStack v4 database, before copying over
+the data from the v3 databases.
+
+## Data migration
+
+The ChirpStack project provides a migration script which will copy data from
+the ChirpStack Application Server and ChirpStack Network Server databases:
+[https://github.com/chirpstack/chirpstack-v3-to-v4](https://github.com/chirpstack/chirpstack-v3-to-v4).
+Please see the [Releases](https://github.com/chirpstack/chirpstack-v3-to-v4/releases)
+for pre-compiled binaries.
+
+This script requires at least three configuration files (see below):
+
+1. `chirpstack-application-server.toml` (ChirpStack Application Server v3)
+1. `chirpstack-network-server.toml` (ChirpStack Network Server v3)
+1. `chirpstack.toml` (ChirpStack v4)
+
+Example:
+
+```
+./chirpstack-v3-to-v4 \
+ --as-config-file /etc/chirpstack-application-server/chirpstack-application-server.toml \
+ --ns-config-file /etc/chirpstack-network-server/chirpstack-network-server.toml \
+ --cs-config-file /etc/chirpstack/chirpstack.toml
+```
+
+It will iterate over all the items in the v3 databases (ChirpStack Application
+Server and ChirpStack Network Server), and will write these into the
+ChirpStack v4 database.
+
+**Important:** In case you have multiple ChirpStack Network Server instances setup for
+multi-region support, you must repeat the `--ns-config-file` option for each
+instance.
+
+Example:
+
+```
+./chirpstack-v3-to-v4 \
+ --as-config-file /etc/chirpstack-application-server/chirpstack-application-server.toml \
+ --ns-config-file /etc/chirpstack-network-server/chirpstack-network-server-eu868.toml \
+ --ns-config-file /etc/chirpstack-network-server/chirpstack-network-server-us915.toml \
+ --cs-config-file /etc/chirpstack/chirpstack.toml
+```
+
+## Configuration
+
+You must confirm that the ChirpStack Gateway Bridge and MQTT topics configured
+in the ChirpStack region configuration are aligned.
+
+The default configuration that is provided by ChirpStack v4 assumes a region
+name as MQTT topic prefix (e.g. `eu868/gateway/...` or `us915_0/gateway/...` for
+the US915 region with channels 0 - 7). Please refer to the [Multi region](./chirpstack/features/multi-reagion.md)
+documentation for more information.
+
+## Validation
+
+To make validate that the migration was successful, validate the following
+steps in the ChirpStack v4 web-interface:
+
+- [ ] Gateways last seen status is periodically updated
+- [ ] Gateway frames are being reported
+- [ ] Device frames are appearing in the web-interface
+- [ ] Device events are appearing in the web-interface
diff --git a/theme/css/chirpstack.css b/theme/css/chirpstack.css
new file mode 100644
index 0000000..e5f7705
--- /dev/null
+++ b/theme/css/chirpstack.css
@@ -0,0 +1,66 @@
+@media only screen and (max-width: 768px) {
+ .chirpstack-header {
+ display: none;
+ }
+}
+
+@media only screen and (min-width: 768px) {
+ .chirpstack-header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 32px;
+ background-color: white;
+ box-shadow: 0 0 10px 0 #ccc;
+ padding: 16px;
+ z-index: 999;
+ }
+
+ .chirpstack-logo {
+ float: left;
+ height: 32px;
+ }
+
+ .chirpstack-links {
+ margin-top: 7px;
+ font-size: 16px;
+ margin-right: 32px;
+ float: right;
+ }
+
+ .sidebar {
+ margin-top: 64px;
+ }
+
+ .page-wrapper {
+ margin-top: 64px;
+ }
+
+ .nav-chapters {
+ top: 64px;
+ }
+
+ .chirpstack-links a {
+ color: black;
+ text-decoration: none;
+ }
+
+ .chirpstack-links a:hover {
+ text-decoration: underline;
+ }
+
+ #menu-bar.sticky,
+ .js #menu-bar-hover-placeholder:hover + #menu-bar,
+ .js #menu-bar:hover,
+ .js.sidebar-visible #menu-bar {
+ top: 64px !important;
+ }
+ #menu-bar-hover-placeholder {
+ top: 64px;
+ }
+}
+
+#theme-toggle {
+ display: none;
+}
diff --git a/theme/header.hbs b/theme/header.hbs
new file mode 100644
index 0000000..1b7dca9
--- /dev/null
+++ b/theme/header.hbs
@@ -0,0 +1,8 @@
+